Commit 6d360c21 authored by Fatih Acet's avatar Fatih Acet Committed by André Luís

Properly sanitize JSON data to fix XSS on Issue details page.

parent c56f2b96
import Vue from 'vue'; import Vue from 'vue';
import sanitize from 'sanitize-html';
import issuableApp from './components/app.vue'; import issuableApp from './components/app.vue';
import '../vue_shared/vue_resource_interceptor'; import '../vue_shared/vue_resource_interceptor';
document.addEventListener('DOMContentLoaded', () => { export default function initIssueableApp() {
const initialDataEl = document.getElementById('js-issuable-app-initial-data'); const initialDataEl = document.getElementById('js-issuable-app-initial-data');
const props = JSON.parse(initialDataEl.innerHTML.replace(/"/g, '"')); const props = JSON.parse(sanitize(initialDataEl.textContent).replace(/"/g, '"'));
return new Vue({ return new Vue({
el: document.getElementById('js-issuable-app'), el: document.getElementById('js-issuable-app'),
...@@ -17,4 +18,4 @@ document.addEventListener('DOMContentLoaded', () => { ...@@ -17,4 +18,4 @@ document.addEventListener('DOMContentLoaded', () => {
}); });
}, },
}); });
}); }
...@@ -3,9 +3,10 @@ import Issue from '~/issue'; ...@@ -3,9 +3,10 @@ import Issue from '~/issue';
import ShortcutsIssuable from '~/shortcuts_issuable'; import ShortcutsIssuable from '~/shortcuts_issuable';
import ZenMode from '~/zen_mode'; import ZenMode from '~/zen_mode';
import '~/notes/index'; import '~/notes/index';
import '~/issue_show/index'; import initIssueableApp from '~/issue_show';
export default function () { export default function () {
initIssueableApp();
new Issue(); // eslint-disable-line no-new new Issue(); // eslint-disable-line no-new
new ShortcutsIssuable(); // eslint-disable-line no-new new ShortcutsIssuable(); // eslint-disable-line no-new
new ZenMode(); // eslint-disable-line no-new new ZenMode(); // eslint-disable-line no-new
......
---
title: Sanitize JSON data properly to fix XSS on Issue details page
merge_request:
author:
type: security
...@@ -18,6 +18,23 @@ describe 'Issue Detail', :js do ...@@ -18,6 +18,23 @@ describe 'Issue Detail', :js do
end end
end end
context 'when issue description has xss snippet' do
before do
issue.update!(description: '![xss" onload=alert(1);//](a)')
sign_in(user)
visit project_issue_path(project, issue)
wait_for_requests
end
it 'should encode the description to prevent xss issues' do
page.within('.issuable-details .detail-page-description') do
expect(page).to have_selector('img', count: 1)
expect(find('img')['onerror']).to be_nil
expect(find('img')['src']).to end_with('/a')
end
end
end
context 'when edited by a user who is later deleted' do context 'when edited by a user who is later deleted' do
before do before do
sign_in(user) sign_in(user)
......
import initIssueableApp from '~/issue_show';
describe('Issue show index', () => {
describe('initIssueableApp', () => {
it('should initialize app with no potential XSS attack', () => {
const d = document.createElement('div');
d.id = 'js-issuable-app-initial-data';
d.innerHTML = JSON.stringify({
initialDescriptionHtml: '<img src=x onerror=alert(1)>',
});
document.body.appendChild(d);
const alertSpy = spyOn(window, 'alert');
initIssueableApp();
expect(alertSpy).not.toHaveBeenCalled();
});
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment