Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test has a WPT meta file that expects 1 subtest issues.
 - This WPT test may be referenced by the following Test IDs:
            
- /trusted-types/block-text-node-insertion-into-svg-script-element.html - WPT Dashboard Interop Dashboard
 
 
<!DOCTYPE html>
<html>
<head>
  <script src="/resources/testharness.js"></script>
  <script src="/resources/testharnessreport.js"></script>
  <script src="resources/block-text-node-insertion.js"></script>
  <script src="support/csp-violations.js"></script>
  <script src="support/namespaces.js"></script>
  <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';">
  <meta http-equiv="Content-Security-Policy" content="connect-src 'none'">
</head>
<body>
<div id="container"></div>
<svg><script id="script1">"hello world!";</script></svg>
<script>
  var container = document.querySelector("#container");
  const policy_dict = {
    createScript: s => (s.includes("fail") ? null : s.replace("default", "count")),
    createHTML: s => s.replace(/2/g, "3"),
  };
  const policy = trustedTypes.createPolicy("policy", policy_dict);
  let seenSinks;
  function clearSeenSinks() { seenSinks = []; }
  clearSeenSinks();
  const policy_dict_default = {
    createScript: (s, _, sink) => {
      seenSinks.push(sink);
      return (s.includes("fail") ? null : s.replace("default", "count"));
    },
    createHTML: (s, _, sink) => {
      seenSinks.push(sink);
      return s.replace(/2/g, "3");
    },
  };
  function createScriptElement() { return document.createElementNS(NSURI_SVG, "script"); }
  // Like the "Original Report" test case above, but avoids use of the "text"
  // accessor that <svg:script> doesn't support.
  promise_test(async t => {
    let s = createScriptElement();
    // Sanity check: Element child content (<p>) doesn't count as source text.
    let p = document.createElement("p");
    p.textContent = "hello('world');";
    s.appendChild(p);
    container.appendChild(s);
    // Try to insertAdjacentText into the <script>, starting from the <p>
    await checkMessage(t, _ =>
      p.insertAdjacentText("beforebegin",
                           "postMessage('beforebegin should be blocked', '*');")
    );
    assert_true(s.textContent.includes("postMessage"));
    await checkMessage(t, _ =>
      p.insertAdjacentText("afterend",
                           "postMessage('afterend should be blocked', '*');")
    );
    assert_true(s.textContent.includes("after"));
  }, "Regression test: Bypass via insertAdjacentText, textContent. svg:script");
  // Variant: Create a <script> element and create & insert a text node. Then
  // insert it into the document container to make it live.
  promise_test(async t => {
    // Setup: Create a <script> element, and insert text via a text node.
    let s = createScriptElement();
    let text = document.createTextNode("postMessage('appendChild with a " +
                                       "text node should be blocked', '*');");
    s.appendChild(text);
    await checkMessage(t, _ => container.appendChild(s));
  }, "Regression test: Bypass via appendChild into off-document script element. svg:script");
  // Variant: Create a <script> element and insert it into the document. Then
  // create a text node and insert it into the live <script> element.
  promise_test(async t => {
    // Setup: Create a <script> element, insert it into the doc, and then create
    // and insert text via a text node.
    let s = createScriptElement();
    container.appendChild(s);
    let text = document.createTextNode("postMessage('appendChild with a live " +
                                       "text node should be blocked', '*');");
    await checkMessage(t, _ => s.appendChild(text));
  }, "Regression test: Bypass via appendChild into live script element. svg:script");
  promise_test(async t => {
    const inserted_script = document.getElementById("script1");
    await trusted_type_violation_for(TypeError, _ =>
      inserted_script.innerHTML = "2+2"
    );
    let new_script = createScriptElement();
    await trusted_type_violation_for(TypeError, _ =>
      new_script.innerHTML = "2+2"
    );
    container.appendChild(new_script);
    const trusted_html = policy.createHTML("2*4");
    assert_equals("" + trusted_html, "3*4");
    await no_trusted_type_violation_for(_ =>
      inserted_script.innerHTML = trusted_html
    );
    assert_equals(inserted_script.textContent, "3*4");
    new_script = createScriptElement();
    new_script.innerHTML = trusted_html;
    await trusted_type_violation_without_exception_for(_ =>
      container.appendChild(new_script)
    );
    assert_equals(inserted_script.textContent, "3*4");
  }, "Spot tests around script + innerHTML interaction.");
  // Create default policy. Wrapped in a promise_test to ensure it runs only
  // after the other tests.
  let default_policy;
  promise_test(t => {
    default_policy = trustedTypes.createPolicy("default", policy_dict_default);
    return Promise.resolve();
  }, "Prep for subsequent tests: Create default policy.");
  promise_test(async t => {
    t.add_cleanup(clearSeenSinks);
    let s = createScriptElement();
    let text = document.createTextNode("postMessage('default', '*');");
    s.appendChild(text);
    await no_trusted_type_violation_for(async _ =>
      await checkMessage(t, _ => container.appendChild(s), 1)
    );
    assert_array_equals(seenSinks, ["SVGScriptElement text"]);
  }, "Test that default policy applies. svg:script");
  promise_test(async t => {
    t.add_cleanup(clearSeenSinks);
    let s = createScriptElement();
    s.setAttribute("type", "module");
    let text = document.createTextNode("postMessage('default', '*');");
    s.appendChild(text);
    await no_trusted_type_violation_for(async _ =>
      await checkMessage(t, _ => container.appendChild(s), 1)
    );
    assert_array_equals(seenSinks, ["SVGScriptElement text"]);
  }, "Test that default policy applies with module script. svg:script");
  promise_test(async t => {
    t.add_cleanup(clearSeenSinks);
    let s = createScriptElement();
    let text = document.createTextNode("fail");
    s.appendChild(text);
    await trusted_type_violation_without_exception_for(async _ =>
      await checkMessage(t, _ => container.appendChild(s), 0)
    );
    assert_array_equals(seenSinks, ["SVGScriptElement text"]);
  }, "Test a failing default policy. svg:script");
  promise_test(async t => {
    t.add_cleanup(clearSeenSinks);
    const inserted_script = document.getElementById("script1");
    await no_trusted_type_violation_for(_ =>
      inserted_script.innerHTML = "2+2"
    );
    assert_array_equals(seenSinks, ["Element innerHTML"]);
    clearSeenSinks();
    assert_equals(inserted_script.textContent, "3+3");
    let new_script = createScriptElement();
    await no_trusted_type_violation_for(_ => {
      new_script.innerHTML = "2+2";
      container.appendChild(new_script);
    });
    assert_array_equals(seenSinks, ["Element innerHTML", "SVGScriptElement text"]);
    clearSeenSinks();
    assert_equals(inserted_script.textContent, "3+3");
    const trusted_html = default_policy.createHTML("2*4");
    assert_equals("" + trusted_html, "3*4");
    await no_trusted_type_violation_for(_ =>
      inserted_script.innerHTML = trusted_html
    );
    assert_array_equals(seenSinks, [undefined]);
    clearSeenSinks();
    assert_equals(inserted_script.textContent, "3*4");
    new_script = createScriptElement();
    await no_trusted_type_violation_for(_ => {
      new_script.innerHTML = trusted_html;
      container.appendChild(new_script);
    });
    assert_array_equals(seenSinks, ["SVGScriptElement text"]);
    clearSeenSinks();
    assert_equals(inserted_script.textContent, "3*4");
  }, "Spot tests around script + innerHTML interaction with default policy.");
</script>
</body>
</html>