Closed Bug 1831328 Opened 2 years ago Closed 2 years ago

Appending nonce'd style tag from one document object into another document object causes the nonce to be ignored

Categories

(Core :: DOM: Core & HTML, defect)

Firefox 112
defect

Tracking

()

RESOLVED FIXED
115 Branch
Tracking Status
firefox115 --- fixed

People

(Reporter: ericryancotter, Assigned: emilio)

References

Details

Attachments

(5 files)

User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36 Edg/112.0.1722.58

Steps to reproduce:

When you have a nonce'd <style> tag stored in something like a document object, and you take that node and append it into another document object, the nonce is ignored in the new document. If you make further changes to that content now that it is sourced in the document it moved to, the nonce gets reevaluated and is now accepted.

I can see this both with native JavaScript, and something presumably similar in Firefox developer tools when editing HTML when the <head> or <body> nodes are the source (nonce ignored) versus editing the HTML of any other child nodes of the body (nonce is accepted).

Actual results:

The nonce is ignored and the styles that should have been allowed are blocked by the content security policy even though the nonce was permitted in that policy.
In developer tools, the nonce attribute is actual visible with its value, whereas if it had been accepted, the nonce attribute would be there but the value would be hidden.

This script shows the JavaScript problem in action. The attached picture shows it in developer tools.

Sample HTML page reproducing the problem.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="style-src 'self' 'nonce-allowme';">
<title>Tyring to duplicate firefox nonce issue</title>
<style type="text/css" nonce="allowme">
p {
color: red;
}
</style>

	<script type="text/javascript">
		function doWork()
		{
			var differentDocument = document.implementation.createDocument("http://www.w3.org/1999/xhtml","html");
			var body = differentDocument.createElement("body");
			body.setAttribute("id", "abc");
			differentDocument.documentElement.appendChild(body);				
			var elementToAdd = document.createElement("div");
			var htmlToAdd = 'Content replaced with style tag that should change this text to blue <style type="text/css" nonce="allowme">p {color: blue;}</style>';
			elementToAdd.innerHTML = htmlToAdd;
			differentDocument.body.appendChild(elementToAdd);  // The problem is introduced here when the "elementToAdd" is moved to another document...  Comment this line out and the problem is resolved
			
			// this causes a CSP violation when the element is returned to the original document
			document.getElementById('contentDiv').appendChild(elementToAdd);

			// this does not cause a CSP violation
			//document.getElementById('contentDiv').innerHTML = (differentDocument.body.innerHTML);
		}
		setTimeout(doWork,1000);
		

	</script>	
</head>

<body>		
	<p class="green">What color is this?</p>
	<div id="contentDiv">This has content in it, but will be appended by script</div>		
	
</body>

</html>

Expected results:

The nonce should be immediately accepted, the styles from it applied if they pass the Content Security Policy, and the nonce value should be hidden from developer tools.

The Bugbug bot thinks this bug should belong to the 'Core::DOM: Core & HTML' component, and is moving the bug to that component. Please correct in case you think the bot is wrong.

Component: Untriaged → DOM: Core & HTML
Product: Firefox → Core
Attached file test.html

I reformatted the test case into a test file, for better visibility.

I'll take a look this.

Flags: needinfo?(sefeng)
Severity: -- → S3
Flags: needinfo?(sefeng)
Flags: needinfo?(sefeng)

For context, I saw this bug in a website using handlebars.js where a handlebars variable was swapped out with content supplied from a safe endpoint returning styled html. Essentially for that site, the functionality on that page is completely broken in Firefox.

yeah okay, this involves style parsing and adding which I am not familiar with.

Emilio, do you know why the style is missing for this? I can poke if you give some directions, though I have no idea where to look at.

Flags: needinfo?(sefeng) → needinfo?(emilio)

I can't be sure since I am not at all familiar with the code, but it seems to me it is trying to apply the styles because it logs that Content Security Policy violation. And when nonces and CSP are not involved, it works fine. So style parsing is probably not the issue?

My wild guess is that there is some kind of code that indexes nonce'd content permitted by a given DOM, and when the style node is brought in from a node stored in another document, that hypothetical index is not updated in the destination document and the style tag is blocked from being used. Subsequent edits to that content in the destination document cause things to be interpreted correctly... So it seems something about bringing the content over from another document causes whatever keeps tracked of nonces to not be updated.

This is not about css parsing. The nonce is stored as a property (here, and similar code for SVGElement).

When moving documents, the properties aren't transferred by default, see aTransfer in here.

I verified that the rather simple property tweak above fixes the test-case. I need to add a test and so on, but not going to have time for that until later today at least. Ideally we'd move the nonce slot to DOM slots if possible? Those are faster anyways...

Flags: needinfo?(emilio)
Assignee: nobody → emilio
Attachment #9334546 - Attachment description: WIP: Bug 1831328 - Transfer nonce slot when moved across documents. → Bug 1831328 - Transfer nonce slot when moved across documents. r=sefeng,smaug
Status: UNCONFIRMED → ASSIGNED
Ever confirmed: true

This frees one node bit and should be similarly fast. The check for the
csp header changes from the attribute setting step to the bind-to-tree
step, but I don't see anything in
https://html.spec.whatwg.org/#nonce-attributes that would forbid that.
That probably needs more details on the spec side...

I filed https://github.com/whatwg/html/issues/9306 but this behavior is
closer to what other browsers do.

Depends on D178297

Pushed by ealvarez@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/4ad54b70bd15 Transfer nonce slot when moved across documents. r=sefeng
Created web-platform-tests PR https://github.com/web-platform-tests/wpt/pull/40063 for changes under testing/web-platform/tests
Status: ASSIGNED → RESOLVED
Closed: 2 years ago
Resolution: --- → FIXED
Target Milestone: --- → 115 Branch
Upstream PR merged by moz-wptsync-bot
Duplicate of this bug: 1804210

Emilio do we still want D178338?

Flags: needinfo?(emilio)

I still think it is worth it but relatively low priority atm for me.

Flags: needinfo?(emilio)
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: