Add JavaScript to sanitize user generated CSS
On every page, a mutation observer is created for the `#content` element. Whenever stuff is added to the page, it will run a little sanitize script. This goes to every `.user_content` element, loops through all of the children, and checks to see if it has `position:fixed` applied to it. If it does, it replaces it with `position:relative`. See the attached JIRA for an explanation of the security vulnerability this fixes. Test Plan: In an RCE on any page, include the following iframe content: ```<iframe style="position: fixed; left: 0; top: 0; right: 0; width: 100vw; height: 100vh;" src="https://www.badgerbadgerbadger.com/"></iframe>``` Save it and navigate to the page which renders your content. If you see badgers across the entire page, this commit failed. Fixes SEC-2876 Refs LS-743 flags=none Change-Id: I11bedc6946e851085503e87f892d3f9edac64bd5 Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/243025 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Product-Review: Peyton Craighill <pcraighill@instructure.com> Reviewed-by: Ed Schiebel <eschiebel@instructure.com> QA-Review: Robin Kuss <rkuss@instructure.com>
This commit is contained in:
parent
bd30d2e246
commit
b5389273af
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (C) 2020 - present Instructure, Inc.
|
||||
*
|
||||
* This file is part of Canvas.
|
||||
*
|
||||
* Canvas is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License as published by the Free
|
||||
* Software Foundation, version 3 of the License.
|
||||
*
|
||||
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import ready from '@instructure/ready'
|
||||
|
||||
// Dynamically disallow fixed position element in user generated content.
|
||||
// Based on the comments made in the comments of this Jira ticket
|
||||
// https://instructure.atlassian.net/browse/SEC-2876
|
||||
function sanitizeOverflow() {
|
||||
document.querySelectorAll('.user_content').forEach(element =>
|
||||
element.querySelectorAll('*').forEach(innerElement => {
|
||||
const style = getComputedStyle(innerElement)
|
||||
if (style.position === 'fixed') {
|
||||
innerElement.style.position = 'relative'
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
const observer = new MutationObserver(function(e) {
|
||||
// If there are any added nodes, sanitize them.
|
||||
if (e.find(mutationRecord => mutationRecord.addedNodes.length > 0)) {
|
||||
sanitizeOverflow()
|
||||
}
|
||||
})
|
||||
|
||||
const contentEl = document.getElementById('content')
|
||||
if (contentEl) {
|
||||
// We need childList so we can get addedNodes, and we need
|
||||
// subtree so we can get mutations on all of the children
|
||||
observer.observe(contentEl, {childList: true, subtree: true})
|
||||
}
|
||||
const asideEl = document.getElementById('right-side')
|
||||
if (asideEl) {
|
||||
observer.observe(asideEl, {childList: true, subtree: true})
|
||||
}
|
||||
|
||||
ready(() => {
|
||||
sanitizeOverflow()
|
||||
})
|
|
@ -40,6 +40,7 @@ import 'compiled/behaviors/instructure_inline_media_comment'
|
|||
import 'compiled/behaviors/ping'
|
||||
import 'compiled/behaviors/broken-images'
|
||||
import 'LtiThumbnailLauncher'
|
||||
import './css_overflow_sanitize'
|
||||
|
||||
if (ENV.page_view_update_url) import('page_views')
|
||||
|
||||
|
|
Loading…
Reference in New Issue