From e3de39893f724005537059b474a69f6e24a71731 Mon Sep 17 00:00:00 2001 From: Tim van der Lippe Date: Sun, 7 Sep 2025 14:31:40 +0200 Subject: [PATCH] Disable scripting when sandbox flag is set (#39163) While I adding spec comments to the CSP crate, I discovered two issues: 1. We should only use the last sandbox value (WPT test added) 2. We weren't checking for the scripting sandbox flag in document Also, the autoplay test should have allowed scripts to run, otherwise the test doesn't run. Since we weren't checking the flag before, the test ran fine for Servo. However, it wouldn't run for other browsers. Also realized that an existing test was pointing to a non-existent file (since it doesn't have `.sub`). Updated that and confirmed that in other browsers it now properly works (it no longer shows a 404). However, Servo now fails that test as we don't fire an load event. Part of #913 Signed-off-by: Tim van der Lippe --- Cargo.lock | 2 +- components/script/dom/document.rs | 21 ++- components/script/dom/eventtarget.rs | 2 +- .../script/dom/html/htmlscriptelement.rs | 6 +- tests/wpt/meta/MANIFEST.json | 134 ++++++++++++++---- .../sandbox/sandbox-empty.sub.html.ini | 3 + ...ed-types-sandbox-no-allow-scripts.html.ini | 3 - .../sandbox/autoplay-disabled-by-csp.html | 29 ++++ .../sandbox/sandbox-empty.sub.html | 2 +- .../sandbox/sandbox-last-directive-csp.html | 18 +++ .../sandbox/support/autoplay.html | 1 + .../sandbox/support/autoplay.html.headers | 1 + .../sandboxed-last-directive-csp.headers | 1 + .../support/sandboxed-last-directive-csp.html | 4 + .../sandboxed-post-message-to-parent.headers | 1 + 15 files changed, 180 insertions(+), 48 deletions(-) create mode 100644 tests/wpt/meta/content-security-policy/sandbox/sandbox-empty.sub.html.ini delete mode 100644 tests/wpt/meta/trusted-types/trusted-types-sandbox-no-allow-scripts.html.ini create mode 100644 tests/wpt/tests/content-security-policy/sandbox/autoplay-disabled-by-csp.html create mode 100644 tests/wpt/tests/content-security-policy/sandbox/sandbox-last-directive-csp.html create mode 100644 tests/wpt/tests/content-security-policy/sandbox/support/autoplay.html create mode 100644 tests/wpt/tests/content-security-policy/sandbox/support/autoplay.html.headers create mode 100644 tests/wpt/tests/content-security-policy/sandbox/support/sandboxed-last-directive-csp.headers create mode 100644 tests/wpt/tests/content-security-policy/sandbox/support/sandboxed-last-directive-csp.html create mode 100644 tests/wpt/tests/content-security-policy/sandbox/support/sandboxed-post-message-to-parent.headers diff --git a/Cargo.lock b/Cargo.lock index 02730d18a27..ec1075c4f63 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1650,7 +1650,7 @@ dependencies = [ [[package]] name = "content-security-policy" version = "0.5.4" -source = "git+https://github.com/servo/rust-content-security-policy?branch=servo-csp#fc927dfefb1fdc052fa4fa18c2ca3c3f6b87047b" +source = "git+https://github.com/servo/rust-content-security-policy?branch=servo-csp#b437ae2001616161ce4729b49408e7785b2f6960" dependencies = [ "base64 0.22.1", "bitflags 2.9.4", diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 25579678307..ab28b2b85d4 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -357,9 +357,6 @@ pub(crate) struct Document { asap_in_order_scripts_list: PendingInOrderScriptVec, /// asap_scripts_set: DomRefCell>>, - /// - /// True if scripting is enabled for all scripts in this document - scripting_enabled: bool, /// /// Current identifier of animation frame callback animation_frame_ident: Cell, @@ -1115,14 +1112,17 @@ impl Document { } /// Return whether scripting is enabled or not - pub(crate) fn is_scripting_enabled(&self) -> bool { - self.scripting_enabled - } - - /// Return whether scripting is enabled or not - /// + /// pub(crate) fn scripting_enabled(&self) -> bool { - self.has_browsing_context() + // Scripting is enabled for a node node if node's node document's browsing context is non-null, + // and scripting is enabled for node's relevant settings object. + self.has_browsing_context() && + // Either settings's global object is not a Window object, + // or settings's global object's associated Document's active sandboxing flag + // set does not have its sandboxed scripts browsing context flag set. + !self.has_active_sandboxing_flag( + SandboxingFlagSet::SANDBOXED_SCRIPTS_BROWSING_CONTEXT_FLAG, + ) } /// Return the element that currently has focus. @@ -3365,7 +3365,6 @@ impl Document { deferred_scripts: Default::default(), asap_in_order_scripts_list: Default::default(), asap_scripts_set: Default::default(), - scripting_enabled: has_browsing_context, animation_frame_ident: Cell::new(0), animation_frame_list: DomRefCell::new(VecDeque::new()), running_animation_callbacks: Cell::new(false), diff --git a/components/script/dom/eventtarget.rs b/components/script/dom/eventtarget.rs index b35c1bf6a58..1ffc1e59707 100644 --- a/components/script/dom/eventtarget.rs +++ b/components/script/dom/eventtarget.rs @@ -720,7 +720,7 @@ impl EventTarget { }; // Step 3.2 - if !document.is_scripting_enabled() { + if !document.scripting_enabled() { return None; } diff --git a/components/script/dom/html/htmlscriptelement.rs b/components/script/dom/html/htmlscriptelement.rs index ddd98330179..8921dc9fa5b 100644 --- a/components/script/dom/html/htmlscriptelement.rs +++ b/components/script/dom/html/htmlscriptelement.rs @@ -688,7 +688,7 @@ impl HTMLScriptElement { } // Step 17. If scripting is disabled for el, then return. - if !doc.is_scripting_enabled() { + if !doc.scripting_enabled() { return; } @@ -1093,7 +1093,7 @@ impl HTMLScriptElement { // TODO use a settings object rather than this element's document/window // Step 2 let document = self.owner_document(); - if !document.is_fully_active() || !document.is_scripting_enabled() { + if !document.is_fully_active() || !document.scripting_enabled() { return; } @@ -1130,7 +1130,7 @@ impl HTMLScriptElement { // TODO use a settings object rather than this element's document/window // Step 2 let document = self.owner_document(); - if !document.is_fully_active() || !document.is_scripting_enabled() { + if !document.is_fully_active() || !document.scripting_enabled() { return; } diff --git a/tests/wpt/meta/MANIFEST.json b/tests/wpt/meta/MANIFEST.json index bc5552f1cb4..d998116bafe 100644 --- a/tests/wpt/meta/MANIFEST.json +++ b/tests/wpt/meta/MANIFEST.json @@ -5070,7 +5070,9 @@ "545f2919b55ffe31f942e547d5299c00ee89d715", [ null, - {} + { + "testdriver": true + } ] ], "table-col-and-dead-row-group-crash.html": [ @@ -8076,7 +8078,9 @@ "63111d03e3fab4673ec4d14cff6ad5737fd4f39c", [ null, - {} + { + "testdriver": true + } ] ] } @@ -8259,7 +8263,9 @@ "39acf9eca17597838a4eec54f31d70be3f9abbb7", [ null, - {} + { + "testdriver": true + } ] ] }, @@ -9121,7 +9127,9 @@ "24bb1ca19e11c516299d8b7cc6ceae21ec981566", [ null, - {} + { + "testdriver": true + } ] ] } @@ -10320,7 +10328,9 @@ "853884b99301e22383e0fd0936cf154beab5e93e", [ null, - {} + { + "testdriver": true + } ] ] }, @@ -38416,7 +38426,9 @@ "==" ] ], - {} + { + "testdriver": true + } ] ] } @@ -196055,7 +196067,7 @@ "grid-items-relative-positioned-containing-block-001.html": [ "7683e485c05caea40361416bc533dc95fbfcd837", [ - "css/css-grid/grid-items/grid-items-relative-positioned-containing-block-001.html", + null, [ [ "/css/reference/ref-filled-green-100px-square.xht", @@ -196068,7 +196080,7 @@ "grid-items-relative-positioned-containing-block-002.html": [ "1e7a754f74da30e327feb06e05527012d1a3917d", [ - "css/css-grid/grid-items/grid-items-relative-positioned-containing-block-002.html", + null, [ [ "/css/reference/ref-filled-green-100px-square.xht", @@ -196081,7 +196093,7 @@ "grid-items-relative-positioned-containing-block-003.html": [ "be0305181914e9b872d0ef1bdc801f974c5918f7", [ - "css/css-grid/grid-items/grid-items-relative-positioned-containing-block-003.html", + null, [ [ "/css/reference/ref-filled-green-100px-square.xht", @@ -196094,7 +196106,7 @@ "grid-items-relative-positioned-containing-block-004.html": [ "61d50a10c10290b55a7439d6b59528f01accc4bf", [ - "css/css-grid/grid-items/grid-items-relative-positioned-containing-block-004.html", + null, [ [ "/css/reference/ref-filled-green-100px-square.xht", @@ -196107,7 +196119,7 @@ "grid-items-relative-positioned-containing-block-005.html": [ "4473cb8d2ba4ea847669cde34ce10e27e6bfb001", [ - "css/css-grid/grid-items/grid-items-relative-positioned-containing-block-005.html", + null, [ [ "/css/reference/ref-filled-green-100px-square.xht", @@ -196120,7 +196132,7 @@ "grid-items-relative-positioned-containing-block-006.html": [ "79350eac516f2850545a6446f570c6c7778a4e3b", [ - "css/css-grid/grid-items/grid-items-relative-positioned-containing-block-006.html", + null, [ [ "/css/reference/ref-filled-green-100px-square.xht", @@ -197559,7 +197571,9 @@ "==" ] ], - {} + { + "testdriver": true + } ] ], "grid-layout-stale-002.html": [ @@ -197572,7 +197586,9 @@ "==" ] ], - {} + { + "testdriver": true + } ] ], "grid-margins-no-collapse-001.html": [ @@ -246133,7 +246149,9 @@ "==" ] ], - {} + { + "testdriver": true + } ] ], "interaction-with-placeholder.html": [ @@ -278427,7 +278445,9 @@ "==" ] ], - {} + { + "testdriver": true + } ] ] }, @@ -312839,7 +312859,9 @@ "==" ] ], - {} + { + "testdriver": true + } ] ], "hit-test-unrelated-element.html": [ @@ -312852,7 +312874,9 @@ "==" ] ], - {} + { + "testdriver": true + } ] ], "iframe-and-main-frame-transition-new-main-new-iframe.html": [ @@ -344798,7 +344822,9 @@ "==" ] ], - {} + { + "testdriver": true + } ] ], "root-siblings.html": [ @@ -346752,7 +346778,9 @@ "==" ] ], - {} + { + "testdriver": true + } ] ], "backdrop-inherit.html": [ @@ -346765,7 +346793,9 @@ "==" ] ], - {} + { + "testdriver": true + } ] ], "backdrop-object.html": [ @@ -346793,7 +346823,9 @@ "==" ] ], - {} + { + "testdriver": true + } ] ] } @@ -359365,7 +359397,7 @@ "input-date-content-size.html": [ "d026771f3c89c736b397db6a10c15fde5d73a3a8", [ - "html/rendering/widgets/input-date-content-size.html", + null, [ [ "/html/rendering/widgets/input-date-content-size-ref.html", @@ -359456,7 +359488,7 @@ "input-time-content-size.html": [ "4a378f6923a8910b96f8afa84125a8fbac4a5d05", [ - "html/rendering/widgets/input-time-content-size.html", + null, [ [ "/html/rendering/widgets/input-time-content-size-ref.html", @@ -365315,7 +365347,9 @@ "==" ] ], - {} + { + "testdriver": true + } ] ], "testdriver-in-ref.html": [ @@ -365341,7 +365375,9 @@ "==" ] ], - {} + { + "testdriver": true + } ] ] }, @@ -404513,6 +404549,14 @@ }, "sandbox": { "support": { + "autoplay.html": [ + "62d0adc3d204f2df9337bf30343591bfb1958e67", + [] + ], + "autoplay.html.headers": [ + "09e65834224c8b917d0a6a2fae17f79ff251fcb6", + [] + ], "empty.html": [ "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", [] @@ -404537,6 +404581,18 @@ "c7e4e7cc5bd3fa25851c1e26c3c04eb95050d94b", [] ], + "sandboxed-last-directive-csp.headers": [ + "371abe3b936e686c901cc9f6f366b8c68e6f3f8b", + [] + ], + "sandboxed-last-directive-csp.html": [ + "9480e521de21ef930674721de943f96e1fd1219a", + [] + ], + "sandboxed-post-message-to-parent.headers": [ + "0368ae01896a2cadb6019ab2c1eb5346d9c3b764", + [] + ], "sandboxed-post-message-to-parent.html": [ "ef4b1a0b95a7e00275c423d49dd28f98545950d3", [] @@ -582583,6 +582639,13 @@ ] }, "sandbox": { + "autoplay-disabled-by-csp.html": [ + "1d1ed0e50b7182ed0d1f8ab7d1b7c7b98e709030", + [ + null, + {} + ] + ], "iframe-inside-csp.sub.html": [ "cd402bdba0198bf763e1733004c2005614b9a542", [ @@ -582619,7 +582682,14 @@ ] ], "sandbox-empty.sub.html": [ - "47034710203a1fb8a3326cd7c8d8367166837628", + "47c3aa1e3657cf2eb5acfeb06bd1936b6e117d0f", + [ + null, + {} + ] + ], + "sandbox-last-directive-csp.html": [ + "b4b2cdbe3296dff091594f73dafb4f4791e5ca72", [ null, {} @@ -762513,7 +762583,12 @@ "5b05e2374e2b4b451a0f98eabd36a6e72a03f933", [ null, - {} + { + "testdriver": true, + "testdriver_features": [ + "bidi" + ] + } ] ] } @@ -762745,6 +762820,9 @@ "script", "/resources/testdriver.js?feature=bidi" ] + ], + "testdriver_features": [ + "bidi" ] } ] diff --git a/tests/wpt/meta/content-security-policy/sandbox/sandbox-empty.sub.html.ini b/tests/wpt/meta/content-security-policy/sandbox/sandbox-empty.sub.html.ini new file mode 100644 index 00000000000..d9a90039a88 --- /dev/null +++ b/tests/wpt/meta/content-security-policy/sandbox/sandbox-empty.sub.html.ini @@ -0,0 +1,3 @@ +[sandbox-empty.sub.html] + [Expecting logs: ["PASS2"\]] + expected: FAIL diff --git a/tests/wpt/meta/trusted-types/trusted-types-sandbox-no-allow-scripts.html.ini b/tests/wpt/meta/trusted-types/trusted-types-sandbox-no-allow-scripts.html.ini deleted file mode 100644 index b608e9999bc..00000000000 --- a/tests/wpt/meta/trusted-types/trusted-types-sandbox-no-allow-scripts.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[trusted-types-sandbox-no-allow-scripts.html] - [Trusted Types CSP directives don't affect the behavior of sandboxed page without allow-scripts.] - expected: FAIL diff --git a/tests/wpt/tests/content-security-policy/sandbox/autoplay-disabled-by-csp.html b/tests/wpt/tests/content-security-policy/sandbox/autoplay-disabled-by-csp.html new file mode 100644 index 00000000000..1d1ed0e50b7 --- /dev/null +++ b/tests/wpt/tests/content-security-policy/sandbox/autoplay-disabled-by-csp.html @@ -0,0 +1,29 @@ + + + + + Test that autoplay is blocked by a document's active sandboxing flags + + + + + + + + + + diff --git a/tests/wpt/tests/content-security-policy/sandbox/sandbox-empty.sub.html b/tests/wpt/tests/content-security-policy/sandbox/sandbox-empty.sub.html index 47034710203..47c3aa1e365 100644 --- a/tests/wpt/tests/content-security-policy/sandbox/sandbox-empty.sub.html +++ b/tests/wpt/tests/content-security-policy/sandbox/sandbox-empty.sub.html @@ -18,7 +18,7 @@ } - diff --git a/tests/wpt/tests/content-security-policy/sandbox/sandbox-last-directive-csp.html b/tests/wpt/tests/content-security-policy/sandbox/sandbox-last-directive-csp.html new file mode 100644 index 00000000000..b4b2cdbe329 --- /dev/null +++ b/tests/wpt/tests/content-security-policy/sandbox/sandbox-last-directive-csp.html @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/wpt/tests/content-security-policy/sandbox/support/autoplay.html b/tests/wpt/tests/content-security-policy/sandbox/support/autoplay.html new file mode 100644 index 00000000000..62d0adc3d20 --- /dev/null +++ b/tests/wpt/tests/content-security-policy/sandbox/support/autoplay.html @@ -0,0 +1 @@ + diff --git a/tests/wpt/tests/content-security-policy/sandbox/support/autoplay.html.headers b/tests/wpt/tests/content-security-policy/sandbox/support/autoplay.html.headers new file mode 100644 index 00000000000..09e65834224 --- /dev/null +++ b/tests/wpt/tests/content-security-policy/sandbox/support/autoplay.html.headers @@ -0,0 +1 @@ +Content-Security-Policy: sandbox \ No newline at end of file diff --git a/tests/wpt/tests/content-security-policy/sandbox/support/sandboxed-last-directive-csp.headers b/tests/wpt/tests/content-security-policy/sandbox/support/sandboxed-last-directive-csp.headers new file mode 100644 index 00000000000..371abe3b936 --- /dev/null +++ b/tests/wpt/tests/content-security-policy/sandbox/support/sandboxed-last-directive-csp.headers @@ -0,0 +1 @@ +Content-Security-Policy: sandbox; sandbox allow-scripts \ No newline at end of file diff --git a/tests/wpt/tests/content-security-policy/sandbox/support/sandboxed-last-directive-csp.html b/tests/wpt/tests/content-security-policy/sandbox/support/sandboxed-last-directive-csp.html new file mode 100644 index 00000000000..9480e521de2 --- /dev/null +++ b/tests/wpt/tests/content-security-policy/sandbox/support/sandboxed-last-directive-csp.html @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/tests/wpt/tests/content-security-policy/sandbox/support/sandboxed-post-message-to-parent.headers b/tests/wpt/tests/content-security-policy/sandbox/support/sandboxed-post-message-to-parent.headers new file mode 100644 index 00000000000..0368ae01896 --- /dev/null +++ b/tests/wpt/tests/content-security-policy/sandbox/support/sandboxed-post-message-to-parent.headers @@ -0,0 +1 @@ +Content-Security-Policy: sandbox