commit 34c0a0d469c8de823bc2303224605971ec0d15c0
parent f0f2484b3c777ee038b9f71083ff2384a447f8c5
Author: Mike Taylor <miketaylr@chromium.org>
Date: Thu, 6 Nov 2025 21:37:56 +0000
Bug 1998022 [wpt PR 55834] - Rewrite third-party-subframe-hsts-upgrade.tentative.sub.html, a=testonly
Automatic update from web-platform-tests
Rewrite third-party-subframe-hsts-upgrade.tentative.sub.html
Change-Id: If78d04aca7c28c18d731cb80129c29cb8c3a6a73
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7095887
Reviewed-by: Andrew Williams <awillia@chromium.org>
Commit-Queue: Mike Taylor <miketaylr@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1539623}
--
wpt-commits: b4387fcba6bf298440a5d6210877db8c0cab93ca
wpt-pr: 55834
Diffstat:
6 files changed, 74 insertions(+), 102 deletions(-)
diff --git a/testing/web-platform/tests/hsts/resources/hsts.html b/testing/web-platform/tests/hsts/resources/hsts.html
@@ -1,4 +0,0 @@
-<!DOCTYPE html>
-<script>
- top.postMessage("hsts", "*");
-</script>
-\ No newline at end of file
diff --git a/testing/web-platform/tests/hsts/resources/hsts.html.headers b/testing/web-platform/tests/hsts/resources/hsts.html.headers
@@ -1,2 +0,0 @@
-Strict-Transport-Security: max-age=60
-Access-Control-Allow-Origin: *
-\ No newline at end of file
diff --git a/testing/web-platform/tests/hsts/resources/hsts.py b/testing/web-platform/tests/hsts/resources/hsts.py
@@ -0,0 +1,12 @@
+headers = [
+ (b"Access-Control-Allow-Origin", b"*"),
+]
+
+def main(request, response):
+ if b"set" in request.GET:
+ headers.append((b"Strict-Transport-Security", b"max-age=60"))
+ return (200, headers, "HSTS max-age set to 60.")
+
+ if b"remove" in request.GET:
+ headers.append((b"Strict-Transport-Security", b"max-age=0"))
+ return (200, headers, "HSTS max-age set to 0.")
diff --git a/testing/web-platform/tests/hsts/resources/is-upgraded.html b/testing/web-platform/tests/hsts/resources/is-upgraded.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<body>
+<script>document.write(`<p>protocol? ${location.protocol}</p>`);</script>
+<script>
+ window.addEventListener('load', () => {
+ window.parent.postMessage(
+ {
+ name: 'iframe-protocol-check',
+ protocol: location.protocol
+ }, '*');
+ });
+</script>
+</body>
+\ No newline at end of file
diff --git a/testing/web-platform/tests/hsts/resources/post-origin-to-opener.html b/testing/web-platform/tests/hsts/resources/post-origin-to-opener.html
@@ -1,4 +0,0 @@
-<!DOCTYPE html>
-<script>
- opener.postMessage({ 'origin': self.origin }, '*');
-</script>
diff --git a/testing/web-platform/tests/hsts/third-party-subframe-hsts-upgrade.tentative.sub.html b/testing/web-platform/tests/hsts/third-party-subframe-hsts-upgrade.tentative.sub.html
@@ -1,99 +1,57 @@
<!DOCTYPE html>
<meta charset=utf-8>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/common/get-host-info.sub.js"></script>
+<title>HSTS upgrade for third-party iframe</title>
+<script src='/resources/testharness.js'></script>
+<script src='/resources/testharnessreport.js'></script>
+<script src='/common/get-host-info.sub.js'></script>
<body>
<script>
- // Check HSTS tracking prevention functionality that is common to all major
- // browsers. Note that this test must be run on an insecure origin because it
- // relies on insecure iframes being loadable. If it's instead run on a secure
- // origin then mixed content blocking will prevent HSTS from working.
-
- // 0) Confirm that insecure iframes can be loaded and that the page's
- // window.location.host corresponds to {{hosts[][]}}:{{ports[http][0]}}.
- // 1) Pin the alt hostname to the HSTS via hsts.html
- // 2) Attempt to load an iframe via http. This should fail because the WPT
- // server only accepts HTTPS requests on the specified HTTPS port in
- // http://{{hosts[alt][]}}:{{ports[https][0]}} *and*
- // HSTS should not upgrade the iframe navigation to https.
- // This is true for all major browsers as part of their tracking protection
- // mitigations such as not allowing third-party loads to set HSTS state
- // or not performing HSTS upgrades for anything but top-level navigations.
- // 3) Pin the hostname to the HSTS via hsts.html
- // 4) Open a new window and navigate it to the same http origin. This should
- // successfully be upgraded to https, load, and then postMessage its origin
- // since it is top level and also not third party it should pass for all
- // the browsers.
-
- const CURRENT_HOST_HTTP_PORT = get_host_info().ORIGINAL_HOST +
- get_host_info().HTTP_PORT_ELIDED;
- const CURRENT_HOST_HTTPS_PORT = get_host_info().ORIGINAL_HOST +
- get_host_info().HTTPS_PORT_ELIDED;
- const ALTERNATE_HOST_HTTPS_PORT = get_host_info().NOTSAMESITE_HOST +
- get_host_info().HTTPS_PORT_ELIDED;
-
- promise_test(async() => {
-
- function onMessageWithTimeout(name) {
- return new Promise((resolve, reject) => {
-
- const timeoutID = step_timeout(() => {
- reject(new Error("Timeout: Didn't receive message for " + name));
- onmessage = null;
- }, 3000);
-
- onmessage = (event) => {
- clearTimeout(timeoutID);
- resolve(event);
- };
- });
- };
-
- // Step 0.
- const iframeLoadable = document.createElement('iframe');
- const iframeLoadablePromise = onMessageWithTimeout("Step 0");
- assert_equals(window.location.host, CURRENT_HOST_HTTP_PORT,
- "this test assumes that the page's window.location.host corresponds to " +
- "hosts[][]");
-
- iframeLoadable.src = `http://${CURRENT_HOST_HTTP_PORT}/hsts/resources/hsts.html`;
- document.body.appendChild(iframeLoadable);
- await iframeLoadablePromise;
-
- // Step 1.
- // Add HSTS pin for domain.
- await fetch(`https://${ALTERNATE_HOST_HTTPS_PORT}/hsts/resources/hsts.html?as-fetch`);
-
- // Step 2.
- // Note: HTTP, not HTTPS:
- const hstsIframe = document.createElement('iframe');
- const hstsIframePromise = onMessageWithTimeout("Step 2")
- .then(resolve => assert_false(true, "HSTS iframe unexpectedly loaded"),
- reject => {/*frame didn't load, as expected */});
-
- hstsIframe.src = `http://${ALTERNATE_HOST_HTTPS_PORT}/hsts/resources/hsts.html`;
- document.body.appendChild(hstsIframe);
- await hstsIframePromise;
-
- // Step 3.
- // Add HSTS pin for current domain.
- await fetch(`https://${CURRENT_HOST_HTTPS_PORT}/hsts/resources/hsts.html?as-fetch`);
-
- // Step 4.
- const hstsWindowPromise = onMessageWithTimeout("Step 4")
- .then((event) =>
- assert_equals(event.data.origin,
- `https://${CURRENT_HOST_HTTPS_PORT}`));
-
- const w = window.open(`http://${CURRENT_HOST_HTTPS_PORT}/hsts/resources/post-origin-to-opener.html`, "_blank");
- if(!w) {
- assert_false(true, "Window didn't open. Is there a popup blocker?");
+ const isUpgraded = `${get_host_info().HTTP_NOTSAMESITE_ORIGIN}/hsts/resources/is-upgraded.html`
+ const removeAltHSTS = `${get_host_info().HTTPS_NOTSAMESITE_ORIGIN}/hsts/resources/hsts.py?remove`;
+ const setAltHSTS = `${get_host_info().HTTPS_NOTSAMESITE_ORIGIN}/hsts/resources/hsts.py?set`;
+ const iframe = document.createElement('iframe');
+ iframe.style = 'display: none';
+ iframe.src = isUpgraded;
+
+ async function tryFetch(uri) {
+ try {
+ await fetch(uri).then(response => {
+ if (!response.ok) {
+ return Promise.reject('Fetching hsts.py somehow failed.');
+ }
+ });
+ } catch (e) {
+ return Promise.reject(e);
}
+ }
+
+ // Step 1) Fetch and receive Strict-Transport-Security header from 3P host
+ promise_setup(() => tryFetch(setAltHSTS));
+
+ promise_test(t => {
+ t.add_cleanup(() => tryFetch(removeAltHSTS));
+
+ return new Promise((resolve, reject) => {
+ // Step 2) Embed iframe of 3P insecure alt host
+ document.body.appendChild(iframe);
+
+ // Step 3) Ensure that the 3P iframe wasn't upgraded via HSTS
+ window.addEventListener('message', e => {
+ if (e.source !== iframe.contentWindow) {
+ return;
+ }
+
+ if (e.data?.name === 'iframe-protocol-check') {
+ if (e.data.protocol === 'http:') {
+ resolve();
+ } else {
+ reject();
+ }
+ }
+ }, {once: true});
+ });
- await hstsWindowPromise;
-}, "Third-party subframe navigations don't result in HSTS upgrade");
-
+ }, 'Third-party HSTS upgrades should be prevented');
</script>
</body>
</html>
\ No newline at end of file