Tests: Add previously crashing TrustedTypes tests

Some of these fail, but we think it is due to a discrepancy between
what the spec says and what the WPT test.

Ref: https://github.com/w3c/trusted-types/issues/595
This commit is contained in:
Tete17 2025-10-28 13:58:31 +01:00 committed by Sam Atkins
parent 676171bccd
commit b0e02af040
10 changed files with 656 additions and 0 deletions

View File

@ -0,0 +1,294 @@
Harness status: OK
Found 72 tests
68 Pass
4 Fail
Pass TT disabled: script.src
= TrustedScript on a
connected element
Pass TT disabled: script.src
= TrustedScript on a
non-connected element
Pass TT disabled: script.src
= String on a
connected element
Pass TT disabled: script.src
= String on a
non-connected element
Pass TT disabled: div.innerHTML
= TrustedHTML on a
connected element
Pass TT disabled: div.innerHTML
= TrustedHTML on a
non-connected element
Pass TT disabled: div.innerHTML
= String on a
connected element
Pass TT disabled: div.innerHTML
= String on a
non-connected element
Pass TT disabled: iframe.srcdoc
= TrustedHTML on a
connected element
Pass TT disabled: iframe.srcdoc
= TrustedHTML on a
non-connected element
Pass TT disabled: iframe.srcdoc
= String on a
connected element
Pass TT disabled: iframe.srcdoc
= String on a
non-connected element
Pass TT disabled: script.text
= TrustedScript on a
connected element
Pass TT disabled: script.text
= TrustedScript on a
non-connected element
Pass TT disabled: script.text
= String on a
connected element
Pass TT disabled: script.text
= String on a
non-connected element
Pass TT disabled: script.innerText
= TrustedScript on a
connected element
Pass TT disabled: script.innerText
= TrustedScript on a
non-connected element
Pass TT disabled: script.innerText
= String on a
connected element
Pass TT disabled: script.innerText
= String on a
non-connected element
Pass TT disabled: script.textContent
= TrustedScript on a
connected element
Pass TT disabled: script.textContent
= TrustedScript on a
non-connected element
Pass TT disabled: script.textContent
= String on a
connected element
Pass TT disabled: script.textContent
= String on a
non-connected element
Pass TT enabled: script.src
= TrustedScript on a
connected element
Pass TT enabled: script.src
= TrustedScript on a
non-connected element
Pass TT enabled: script.src
= String on a
connected element
Pass TT enabled: script.src
= String on a
non-connected element
Pass TT enabled: div.innerHTML
= TrustedHTML on a
connected element
Pass TT enabled: div.innerHTML
= TrustedHTML on a
non-connected element
Pass TT enabled: div.innerHTML
= String on a
connected element
Pass TT enabled: div.innerHTML
= String on a
non-connected element
Fail TT enabled: iframe.srcdoc
= TrustedHTML on a
connected element
Fail TT enabled: iframe.srcdoc
= TrustedHTML on a
non-connected element
Pass TT enabled: iframe.srcdoc
= String on a
connected element
Pass TT enabled: iframe.srcdoc
= String on a
non-connected element
Pass TT enabled: script.text
= TrustedScript on a
connected element
Pass TT enabled: script.text
= TrustedScript on a
non-connected element
Pass TT enabled: script.text
= String on a
connected element
Pass TT enabled: script.text
= String on a
non-connected element
Pass TT enabled: script.innerText
= TrustedScript on a
connected element
Pass TT enabled: script.innerText
= TrustedScript on a
non-connected element
Pass TT enabled: script.innerText
= String on a
connected element
Pass TT enabled: script.innerText
= String on a
non-connected element
Pass TT enabled: script.textContent
= TrustedScript on a
connected element
Pass TT enabled: script.textContent
= TrustedScript on a
non-connected element
Pass TT enabled: script.textContent
= String on a
connected element
Pass TT enabled: script.textContent
= String on a
non-connected element
Pass TT enabled: script.src
= TrustedScript on a
connected element
after removing the "require-trusted-types-for 'script' directive
Pass TT enabled: script.src
= TrustedScript on a
non-connected element
after removing the "require-trusted-types-for 'script' directive
Pass TT enabled: script.src
= String on a
connected element
after removing the "require-trusted-types-for 'script' directive
Pass TT enabled: script.src
= String on a
non-connected element
after removing the "require-trusted-types-for 'script' directive
Pass TT enabled: div.innerHTML
= TrustedHTML on a
connected element
after removing the "require-trusted-types-for 'script' directive
Pass TT enabled: div.innerHTML
= TrustedHTML on a
non-connected element
after removing the "require-trusted-types-for 'script' directive
Pass TT enabled: div.innerHTML
= String on a
connected element
after removing the "require-trusted-types-for 'script' directive
Pass TT enabled: div.innerHTML
= String on a
non-connected element
after removing the "require-trusted-types-for 'script' directive
Fail TT enabled: iframe.srcdoc
= TrustedHTML on a
connected element
after removing the "require-trusted-types-for 'script' directive
Fail TT enabled: iframe.srcdoc
= TrustedHTML on a
non-connected element
after removing the "require-trusted-types-for 'script' directive
Pass TT enabled: iframe.srcdoc
= String on a
connected element
after removing the "require-trusted-types-for 'script' directive
Pass TT enabled: iframe.srcdoc
= String on a
non-connected element
after removing the "require-trusted-types-for 'script' directive
Pass TT enabled: script.text
= TrustedScript on a
connected element
after removing the "require-trusted-types-for 'script' directive
Pass TT enabled: script.text
= TrustedScript on a
non-connected element
after removing the "require-trusted-types-for 'script' directive
Pass TT enabled: script.text
= String on a
connected element
after removing the "require-trusted-types-for 'script' directive
Pass TT enabled: script.text
= String on a
non-connected element
after removing the "require-trusted-types-for 'script' directive
Pass TT enabled: script.innerText
= TrustedScript on a
connected element
after removing the "require-trusted-types-for 'script' directive
Pass TT enabled: script.innerText
= TrustedScript on a
non-connected element
after removing the "require-trusted-types-for 'script' directive
Pass TT enabled: script.innerText
= String on a
connected element
after removing the "require-trusted-types-for 'script' directive
Pass TT enabled: script.innerText
= String on a
non-connected element
after removing the "require-trusted-types-for 'script' directive
Pass TT enabled: script.textContent
= TrustedScript on a
connected element
after removing the "require-trusted-types-for 'script' directive
Pass TT enabled: script.textContent
= TrustedScript on a
non-connected element
after removing the "require-trusted-types-for 'script' directive
Pass TT enabled: script.textContent
= String on a
connected element
after removing the "require-trusted-types-for 'script' directive
Pass TT enabled: script.textContent
= String on a
non-connected element
after removing the "require-trusted-types-for 'script' directive

View File

@ -0,0 +1,15 @@
Harness status: OK
Found 9 tests
6 Pass
3 Fail
Fail script.src accepts only TrustedScriptURL
Pass div.innerHTML accepts only TrustedHTML
Fail iframe.srcdoc accepts only TrustedHTML
Pass script.src accepts string and null after default policy was created
Fail div.innerHTML accepts string and null after default policy was created
Pass iframe.srcdoc accepts string and null after default policy was created
Pass script.text accepts only TrustedScript
Pass script.innerText accepts only TrustedScript
Pass script.textContent accepts only TrustedScript

View File

@ -0,0 +1,11 @@
Harness status: OK
Found 5 tests
4 Pass
1 Fail
Fail iframe.srcdoc assigned via policy (successful HTML transformation).
Pass `iframe.srcdoc = string` throws.
Pass `iframe.srcdoc = null` throws.
Pass `iframe.srcdoc = string` assigned via default policy (successful HTML transformation).
Pass `iframe.srcdoc = null` assigned via default policy does not throw

View File

@ -0,0 +1,10 @@
Harness status: OK
Found 4 tests
1 Pass
3 Fail
Fail createHTML with a policy that returns undefined DOMParser
Fail createHTML with a policy that returns undefined iframe.srcdoc
Pass createScript with a policy that returns undefined <div onload>
Fail createScriptURL with a policy that returns undefined script.src

View File

@ -0,0 +1,8 @@
Harness status: OK
Found 2 tests
1 Pass
1 Fail
Pass Setting innerHTML on a node inserted by the parser.
Fail Setting innerHTML on a node adopted from a subframe.

View File

@ -0,0 +1,93 @@
<!DOCTYPE html>
<head>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script src="support/helper.sub.js"></script>
</head>
<body>
<script>
const policy = trustedTypes.createPolicy("testpolicy", {
createScript: s => s,
createHTML: s => s,
createScriptURL: s => s,
});
function getTrusted(element, attr) {
const type = trustedTypes.getPropertyType(element, attr);
if (type == "TrustedScript") {
return policy.createScript("2+2");
} else if (type == "TrustedScriptURL") {
return policy.createScript("https://example.test/");
} else if (type == "TrustedHTML") {
return policy.createHTML("<b>hello</b>");
} else {
return "a simple string";
}
}
// This test will run a simple, TT-relevant assignment, in a number of
// circumstances. We've had issues where subtle difference in DOM behaviour -
// for example a connected element or a non-connected element - produce
// different results, and no test catching it because the tests were written
// to do it one particular way. So this test does one thing, but in all the
// different ways we can think of.
//
// - With TT disabled or enabled,
// - with any of the trusted types,
// - with a string or a TT value,
// - with a element that's connected to the DOM (or not).
//
// Run the set of tests, assuming that is_tt_enabled reflects whether Trusted
// Types is currently enabled (& enforced) or not.
function runTests(is_tt_enabled, description_suffix) {
for (const [element, attr] of [
[ 'script', 'src' ],
[ 'div', 'innerHTML' ],
[ 'iframe', 'srcdoc' ],
[ 'script', 'text' ],
[ 'script', 'innerText' ],
[ 'script', 'textContent' ],
]) {
const trusted = getTrusted(element, attr);
for (const value of [trusted, trusted.toString()]) {
for (const connected of [true, false]) {
const expect_exception = is_tt_enabled &&
value.constructor.name != trustedTypes.getPropertyType(element, attr);
test(t => {
const elem = document.createElement(element);
if (connected) document.body.appendChild(elem);
if (expect_exception) {
assert_throws_js(TypeError, _ => { elem[attr] = value; });
} else {
elem[attr] = value;
}
}, `${is_tt_enabled ? "TT enabled" : "TT disabled"}: ${element}.${attr}
= ${value.constructor.name} on a
${connected ? "connected" : "non-connected"} element
${description_suffix}`);
}
}
}
}
// Run the tests without TT first.
runTests(false, "");
// Now run the tests a second time, with TT enabled. To accomplish this, insert
// a suitable <meta> element.
const meta = document.createElement("meta");
meta.setAttribute("http-equiv", "Content-Security-Policy");
meta.setAttribute("content", "require-trusted-types-for 'script';");
document.head.appendChild(meta);
runTests(true, "");
// Remove the meta element and re-run the tests, expecting exceptions.
// That is, trusted types are still enforced. That behavior is required by
// <https://www.w3.org/TR/CSP3/#meta-element> 's note
// "Modifications to the content attribute of a meta element after the element
// has been parsed will be ignored.".
meta.remove();
runTests(true,
`after removing the "require-trusted-types-for 'script' directive`);
</script>

View File

@ -0,0 +1,75 @@
<!DOCTYPE html>
<html>
<head>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script src="support/helper.sub.js"></script>
<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';">
</head>
<body>
<script>
var testnb = 0;
// TrustedScriptURL Assignments
const scriptURLTestCases = [
[ 'script', 'src' ]
];
testnb = 0;
scriptURLTestCases.forEach(c => {
test(t => {
assert_element_accepts_trusted_script_url(window, ++testnb, t, c[0], c[1], RESULTS.SCRIPTURL);
assert_throws_no_trusted_type(c[0], c[1], 'A string');
assert_throws_no_trusted_type(c[0], c[1], null);
}, c[0] + "." + c[1] + " accepts only TrustedScriptURL");
});
// TrustedHTML Assignments
const HTMLTestCases = [
[ 'div', 'innerHTML' ],
[ 'iframe', 'srcdoc' ]
];
testnb = 0;
HTMLTestCases.forEach(c => {
test(t => {
assert_element_accepts_trusted_html(window, ++testnb, t, c[0], c[1], RESULTS.HTML);
assert_throws_no_trusted_type(c[0], c[1], 'A string');
assert_throws_no_trusted_type(c[0], c[1], null);
}, c[0] + "." + c[1] + " accepts only TrustedHTML");
});
// After default policy creation string and null assignments implicitly call createHTML
let p = window.trustedTypes.createPolicy("default", { createScriptURL: createScriptURLJS, createHTML: createHTMLJS });
scriptURLTestCases.forEach(c => {
test(t => {
assert_element_accepts_trusted_type(c[0], c[1], INPUTS.SCRIPTURL, RESULTS.SCRIPTURL);
assert_element_accepts_trusted_type(c[0], c[1], null, window.location.toString().replace(/[^\/]*$/, "null"));
}, c[0] + "." + c[1] + " accepts string and null after default policy was created");
});
HTMLTestCases.forEach(c => {
test(t => {
assert_element_accepts_trusted_type(c[0], c[1], INPUTS.HTML, RESULTS.HTML);
assert_element_accepts_trusted_type(c[0], c[1], null, c[1] === 'innerHTML'? "" : "null");
}, c[0] + "." + c[1] + " accepts string and null after default policy was created");
});
// TrustedScript Assignments
const scriptTestCases = [
[ 'script', 'text' ],
[ 'script', 'innerText' ],
[ 'script', 'textContent' ]
];
testnb = 0;
scriptTestCases.forEach(c => {
test(t => {
assert_element_accepts_trusted_script(window, ++testnb, t, c[0], c[1], RESULTS.SCRIPT);
assert_throws_no_trusted_type(c[0], c[1], 'A string');
assert_throws_no_trusted_type(c[0], c[1], null);
}, c[0] + "." + c[1] + " accepts only TrustedScript");
});
</script>

View File

@ -0,0 +1,54 @@
<!DOCTYPE html>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script src="support/helper.sub.js"></script>
<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';">
<body>
<script>
// TrustedHTML assignments do not throw.
test(t => {
let p = createHTML_policy(window, 1);
let html = p.createHTML(INPUTS.HTML);
let iframe = document.createElement("iframe");
iframe.srcdoc = html;
assert_equals(iframe.srcdoc, RESULTS.HTML);
}, "iframe.srcdoc assigned via policy (successful HTML transformation).");
// String assignments throw.
test(t => {
let iframe = document.createElement("iframe");
assert_throws_js(TypeError, _ => {
iframe.srcdoc = "A string";
});
}, "`iframe.srcdoc = string` throws.");
// Null assignment throws.
test(t => {
let iframe = document.createElement("iframe");
assert_throws_js(TypeError, _ => {
iframe.srcdoc = null;
});
}, "`iframe.srcdoc = null` throws.");
// After default policy creation string assignment implicitly calls createHTML
test(t => {
let p = window.trustedTypes.createPolicy("default", { createHTML:
(value, _, sink) => {
assert_equals(sink, "HTMLIFrameElement srcdoc");
return createHTMLJS(value);
}
});
let iframe = document.createElement("iframe");
iframe.srcdoc = INPUTS.HTML;
assert_equals(iframe.srcdoc, RESULTS.HTML);
}, "`iframe.srcdoc = string` assigned via default policy (successful HTML transformation).");
// After default policy creation null assignment implicitly calls createHTML.
test(t => {
let iframe = document.createElement("iframe");
iframe.srcdoc = null;
assert_equals(iframe.srcdoc, "null");
}, "`iframe.srcdoc = null` assigned via default policy does not throw");
</script>

View File

@ -0,0 +1,59 @@
<!DOCTYPE html>
<head>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<meta http-equiv="Content-Security-Policy"
content="require-trusted-types-for 'script'">
</head>
<body>
<script>
/* This is chiefly a regression test for crbug.com/430335244, but should apply
to any TT implementation:
Per https://www.w3.org/TR/trusted-types/#create-a-trusted-type-algorithm
step 4: If a policy function does not return a value, the empty string should
be used.
*/
test(t => {
const policy = trustedTypes.createPolicy("emptyCreateHTML", {
"createHTML": _ => {},
});
const doc = new DOMParser().parseFromString(
policy.createHTML("bla"), "text/html");
assert_equals(doc.body.textContent, "");
}, "createHTML with a policy that returns undefined DOMParser");
test(t => {
const policy = trustedTypes.createPolicy("emptyCreateHTML", {
"createHTML": _ => {},
});
const iframe = document.createElement("iframe");
iframe.srcdoc = policy.createHTML("bla");
assert_equals(iframe.srcdoc, "");
assert_true(iframe.hasAttribute('srcdoc'), "srcdoc attribute exists");
}, "createHTML with a policy that returns undefined iframe.srcdoc");
test(t => {
const policy = trustedTypes.createPolicy("emptyCreateScript", {
"createScript": _ => {},
});
const div = document.createElement("div");
div.setAttribute('onload', policy.createScript("bla"));
assert_true(div.hasAttribute("onload"), "onload attribute exists");
}, "createScript with a policy that returns undefined <div onload>");
test(t => {
const policy = trustedTypes.createPolicy("emptyCreateScriptURL", {
"createScriptURL": _ => {},
});
const script = document.createElement("script");
script.src = policy.createScriptURL("bla");
assert_equals(script.src, document.location.href);
assert_true(script.hasAttribute("src"), "src attribute exists");
}, "createScriptURL with a policy that returns undefined script.src");
</script>
</body>

View File

@ -0,0 +1,37 @@
<!DOCTYPE html>
<meta http-equiv="Content-Security-Policy"
content="require-trusted-types-for 'script';"/>
<link rel="help" href="https://github.com/web-platform-tests/wpt/issues/45405">
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<div id="divInsertedByParser"></div>
<script>
test( _ => {
assert_throws_js(TypeError, _ => divInsertedByParser.innerHTML = 'unsafe');
}, "Setting innerHTML on a node inserted by the parser.");
promise_test(async t => {
const iframe = document.createElement("iframe");
const passThroughPolicy =
trustedTypes.createPolicy("passThrough", { createHTML: s => s,
createScript: s => s });
iframe.srcdoc = passThroughPolicy.createHTML("<!DOCTYPE html><div></div>");
await new Promise(resolve => {
iframe.addEventListener("load", resolve);
document.body.appendChild(iframe);
});
const divAdoptedFromIframe =
document.adoptNode(iframe.contentDocument.body.firstElementChild);
// There are cross-browser differences about which realm a node returned
// by Document.adoptNode belongs to. Here, we expect that Trusted Types will
// throw an exception from divAdoptedFromIframe's realm, but without
// taking a stance about whether this should be the window's or the iframe's
// realm.
// Discussion at: https://github.com/web-platform-tests/wpt/issues/45405
assert_throws_js(
divAdoptedFromIframe.constructor.constructor(
passThroughPolicy.createScript("return TypeError"))(),
_ => divAdoptedFromIframe.innerHTML = 'unsafe');
}, "Setting innerHTML on a node adopted from a subframe.");
</script>