Properly sanitize JSON data to fix XSS on Issue details page.
This commit is contained in:
parent
c56f2b9615
commit
6d360c210d
|
@ -1,10 +1,11 @@
|
||||||
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', () => {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
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
|
||||||
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)
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue