Merge branch 'security-acet-issue-details' into 'master'

[master] Fix XSS on Issue details page.

See merge request gitlab/gitlabhq!2468
This commit is contained in:
Bob Van Landuyt 2018-10-01 16:47:39 +00:00
commit bfd3062cd3
5 changed files with 47 additions and 4 deletions

View File

@ -1,10 +1,11 @@
import Vue from 'vue';
import sanitize from 'sanitize-html';
import issuableApp from './components/app.vue';
import '../vue_shared/vue_resource_interceptor';
document.addEventListener('DOMContentLoaded', () => {
export default function initIssueableApp() {
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({
el: document.getElementById('js-issuable-app'),
@ -17,4 +18,4 @@ document.addEventListener('DOMContentLoaded', () => {
});
},
});
});
}

View File

@ -3,9 +3,10 @@ import Issue from '~/issue';
import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
import ZenMode from '~/zen_mode';
import '~/notes/index';
import '~/issue_show/index';
import initIssueableApp from '~/issue_show';
export default function () {
initIssueableApp();
new Issue(); // eslint-disable-line no-new
new ShortcutsIssuable(); // eslint-disable-line no-new
new ZenMode(); // eslint-disable-line no-new

View File

@ -0,0 +1,5 @@
---
title: Sanitize JSON data properly to fix XSS on Issue details page
merge_request:
author:
type: security

View File

@ -18,6 +18,23 @@ describe 'Issue Detail', :js do
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
before do
sign_in(user)

View File

@ -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();
});
});
});