tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 9212b47900ea7a1a701a832ece3e7ca0ce88da05
parent 7cc5cf4f08bc73c2eeeb67a9a133e60ce0558294
Author: Daniel Vogelheim <vogelheim@chromium.org>
Date:   Mon,  8 Dec 2025 12:29:20 +0000

Bug 2004565 [wpt PR 56536] - [Sanitizer] Ensure SanitizerAPI is called before nodes are active., a=testonly

Automatic update from web-platform-tests
[Sanitizer] Ensure SanitizerAPI is called before nodes are active.

Sanitizer API requires that the HTML parser will parse into an
inert / inactive DocumentFragment. After the parse, this fragment
will then be sanitized, and only then inserted into the intended
and possibly active document.

To accomplish this, we change three things:

- CreateFragmentForInnerOuterHTML gets an additional parameter
  which can force parsing into an inert fragment.
- We move the sanitization call into Element::SetInnerHTML, so that
  it can execute after CreateFragmentForInnerOuterHTML, but before
  inserting the nodes into the document.
- We are more precise on the sanitizer side to distinguish between
  the context node (usually part the existing, possibly active
  document) and the root node to be sanitized.

Additionally, we add an end-to-end WPT test for this, checking that
an image won't load, and CHECKs in all Sanitizer API entry points
that the root node is not in an active document.

See also:
- https://wicg.github.io/sanitizer-api/#sanitizer-api
- https://github.com/WICG/sanitizer-api/issues/363

Bug: 40138584
Change-Id: I86639b5dc529e9292b2614ccc41e7d99c6ce3f88
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7203943
Reviewed-by: Noam Rosenthal <nrosenthal@google.com>
Commit-Queue: Daniel Vogelheim <vogelheim@chromium.org>
Reviewed-by: Mason Freed <masonf@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1554822}

--

wpt-commits: be4f92e3f3a73591823f83a00315062b7b26e2fc
wpt-pr: 56536

Diffstat:
Atesting/web-platform/tests/sanitizer-api/sanitizer-inert-document.tentative.html | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 79 insertions(+), 0 deletions(-)

diff --git a/testing/web-platform/tests/sanitizer-api/sanitizer-inert-document.tentative.html b/testing/web-platform/tests/sanitizer-api/sanitizer-inert-document.tentative.html @@ -0,0 +1,79 @@ +<!DOCTYPE html> +<html> +<head> +<title>Test whether fragment created for sanitization is inert.</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id="test"></div> +<script> +promise_test(t => { + return new Promise((resolve, fail) => { + globalThis.failsafe = fail; + globalThis.resolvesafe = resolve; + + const div = document.createElement("div"); + document.getElementById("test").appendChild(div); + div.setHTML(`<img src="data:image/png," onerror="globalThis.failsafe('shouldnt load')">`); + + const div2 = document.createElement("div"); + document.getElementById("test").appendChild(div2); + div2.innerHTML = `<img src="data:image/png," onerror="globalThis.resolvesafe('shoud load')">`; + }); +}, "Test whether setHTML executes the fail handler."); + +promise_test(t => { + return new Promise((resolve, fail) => { + globalThis.failunsafe = fail; + globalThis.resolveunsafe = resolve; + + const div = document.createElement("div"); + document.getElementById("test").appendChild(div); + div.setHTMLUnsafe( + `<img src="data:image/png," onerror="globalThis.failunsafe()">`, + {sanitizer: {removeElements: ["img"]}}); + + const div2 = document.createElement("div"); + document.getElementById("test").appendChild(div2); + div2.innerHTML = `<img src="data:image/png," onerror="globalThis.resolveunsafe()">`; + }); +}, "Test whether setHTMLUnsafe executes the fail handler."); + +const url = "/fetch/metadata/resources/record-header.py?file=image"; +const options = {sanitizer: {removeElements: ["img"]}}; + +promise_test(t => { + return new Promise((resolve, fail) => { + const div = document.createElement("div"); + document.getElementById("test").appendChild(div); + div.setHTML(`<img src="${url}">`, options); + fetch(url + "&retrieve=true") + .then(response => response.text()) + .then(text => { + if (text.includes("No header has been recorded")) + resolve() + else + fail("The server observed a request. It shouldn't have."); + }); + }); +}, "Test whether setHTML loads the image."); + +promise_test(t => { + return new Promise((resolve, fail) => { + const div = document.createElement("div"); + document.getElementById("test").appendChild(div); + div.setHTMLUnsafe(`<img src="${url}">`, options); + fetch(url + "&retrieve=true") + .then(response => response.text()) + .then(text => { + if (text.includes("No header has been recorded")) + resolve() + else + fail("The server observed a request. It shouldn't have."); + }); + }); +}, "Test whether setHTMLUnsafe loads the image."); +</script> +</body> +</html>