Skip to content

Commit 442757a

Browse files
VergeAchromium-wpt-export-bot
authored andcommitted
[Connection-Allowlist] Implement "redirects=" param for navigations.
Previously, we blocked all redirects for navigations when a Connection Allowlist header was enforced. We decided to use a global header param called `redirects=` instead. When the value of the param is "allow", navigations for redirects will be allowed regardless of destination. When the value is "block", redirects will be blocked regardless of the destination. A follow-up CL will implement this same logic for subresource fetch redirects. Bug: 492439215 Change-Id: I2f9de6c9a8f9746b2f7f5206e9476709145b77d5 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7667118 Commit-Queue: Andrew Verge <averge@chromium.org> Reviewed-by: Shivani Sharma <shivanisha@chromium.org> Reviewed-by: Alex Moshchuk <alexmos@chromium.org> Cr-Commit-Position: refs/heads/main@{#1602209}
1 parent 0005aea commit 442757a

8 files changed

Lines changed: 137 additions & 65 deletions
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// META: script=/common/get-host-info.sub.js
2+
// META: script=resources/navigation_redirect_test.js
3+
4+
// We're loading this page from `http://{{hosts[][]}}`.
5+
// The connection allowlist header is `Connection-Allowlist:
6+
// (response-origin);redirects=allow`. Thus, all redirects should succeed.
7+
8+
// Redirect from an allowlisted origin (same-origin):
9+
// origin: http://{{hosts[][]}} (allowed by allowlist)
10+
// target: http://{{hosts[][]}} (also allowed)
11+
// This should SUCCEED, because of the redirects=allow portion of the header.
12+
navigation_redirect_test(
13+
'http://{{hosts[][]}}' + port, 'http://{{hosts[][]}}' + port, SUCCESS);
14+
15+
// Redirect from an allowlisted origin to a different origin:
16+
// origin: http://{{hosts[][]}} (allowed by allowlist)
17+
// target: http://{{hosts[alt][]}} (not allowed)
18+
// This should SUCCEED, because of the redirects=allow portion of the header,
19+
// regardless of what the target origin is.
20+
navigation_redirect_test(
21+
'http://{{hosts[][]}}' + port, 'http://{{hosts[alt][]}}' + port, SUCCESS);
22+
23+
// Initial navigation to a non-allowlisted origin:
24+
// origin: http://{{hosts[alt][]}} (not allowed)
25+
// This is blocked before the redirect even happens.
26+
navigation_redirect_test(
27+
'http://{{hosts[alt][]}}' + port, 'http://{{hosts[][]}}' + port, FAILURE);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Connection-Allowlist: (response-origin);redirects=allow
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// META: script=/common/get-host-info.sub.js
2+
// META: script=resources/navigation_redirect_test.js
3+
4+
// We're loading this page from `http://{{hosts[][]}}`.
5+
// The connection allowlist header is `Connection-Allowlist:
6+
// (response-origin);redirects=block`. Thus, all redirects should fail.
7+
8+
// Redirect from an allowlisted origin (same-origin):
9+
// origin: http://{{hosts[][]}} (allowed by allowlist)
10+
// target: http://{{hosts[][]}} (also allowed)
11+
// This should FAIL, because of the redirects=block portion of the header.
12+
navigation_redirect_test(
13+
'http://{{hosts[][]}}' + port, 'http://{{hosts[][]}}' + port, FAILURE);
14+
15+
// Redirect from an allowlisted origin to a different origin:
16+
// origin: http://{{hosts[][]}} (allowed by allowlist)
17+
// target: http://{{hosts[alt][]}} (not allowed)
18+
// This should FAIL, because of the redirects=block portion of the header.
19+
navigation_redirect_test(
20+
'http://{{hosts[][]}}' + port, 'http://{{hosts[alt][]}}' + port, FAILURE);
21+
22+
// Initial navigation to a non-allowlisted origin:
23+
// origin: http://{{hosts[alt][]}} (not allowed)
24+
// This is blocked before the redirect even happens.
25+
navigation_redirect_test(
26+
'http://{{hosts[alt][]}}' + port, 'http://{{hosts[][]}}' + port, FAILURE);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Connection-Allowlist: (response-origin);redirects=block
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// META: script=/common/get-host-info.sub.js
2+
// META: script=resources/navigation_redirect_test.js
3+
// The following tests assume the policy `Connection-Allowlist:
4+
// (response-origin)` has been set. Redirects from a connection-allowlisted URL
5+
// should be blocked by default.
6+
7+
// We're loading this page from `http://{{hosts[][]}}`.
8+
// The connection allowlist header is `Connection-Allowlist: (response-origin)`.
9+
// Thus, only `http://{{hosts[][]}}` is allowlisted for navigations, and no
10+
// redirects are allowed.
11+
12+
// Redirect from an allowlisted origin (same-origin):
13+
// origin: http://{{hosts[][]}} (allowed by allowlist)
14+
// target: http://{{hosts[][]}} (also allowed)
15+
// This should FAIL because redirects are default-blocked for allowlisted
16+
// navigations.
17+
navigation_redirect_test(
18+
'http://{{hosts[][]}}' + port, 'http://{{hosts[][]}}' + port, FAILURE);
19+
20+
// Redirect from an allowlisted origin to a different origin:
21+
// origin: http://{{hosts[][]}} (allowed by allowlist)
22+
// target: http://{{hosts[alt][]}} (not allowed)
23+
// This should FAIL.
24+
navigation_redirect_test(
25+
'http://{{hosts[][]}}' + port, 'http://{{hosts[alt][]}}' + port, FAILURE);
26+
27+
// Initial navigation to a non-allowlisted origin:
28+
// origin: http://{{hosts[alt][]}} (not allowed)
29+
// This is blocked before the redirect even happens.
30+
navigation_redirect_test(
31+
'http://{{hosts[alt][]}}' + port, 'http://{{hosts[][]}}' + port, FAILURE);

connection-allowlist/tentative/navigation-redirect.sub.window.js.headers renamed to connection-allowlist/tentative/navigation-redirect-default.sub.window.js.headers

File renamed without changes.

connection-allowlist/tentative/navigation-redirect.sub.window.js

Lines changed: 0 additions & 65 deletions
This file was deleted.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// META: script=/common/get-host-info.sub.js
2+
3+
const port = get_host_info().HTTP_PORT_ELIDED;
4+
const SUCCESS = true;
5+
const FAILURE = false;
6+
7+
function navigation_redirect_test(origin, target_origin, expectation) {
8+
promise_test(
9+
async t => {
10+
const iframe = document.createElement('iframe');
11+
let received_message = false;
12+
const handler = (e) => {
13+
if (e.data === 'loaded') {
14+
received_message = true;
15+
}
16+
};
17+
window.addEventListener('message', handler);
18+
t.add_cleanup(() => window.removeEventListener('message', handler));
19+
20+
const p = new Promise((resolve) => {
21+
iframe.onload = () => {
22+
// If onload fires, it might be the success page or an error page.
23+
// We wait a short bit to ensure any postMessage has time to arrive.
24+
step_timeout(() => resolve(), 50);
25+
};
26+
iframe.onerror = () => resolve();
27+
});
28+
29+
const target_url = target_origin +
30+
'/connection-allowlist/tentative/resources/post-message.html';
31+
iframe.src = origin + '/common/redirect.py?status=302&location=' +
32+
encodeURIComponent(target_url);
33+
document.body.appendChild(iframe);
34+
await p;
35+
document.body.removeChild(iframe);
36+
37+
if (expectation === SUCCESS) {
38+
assert_true(
39+
received_message,
40+
`Redirect from ${origin} to ${
41+
target_origin} should have succeeded.`);
42+
} else {
43+
assert_false(
44+
received_message,
45+
`Redirect from ${origin} to ${
46+
target_origin} should have failed.`);
47+
}
48+
},
49+
`Redirect from ${origin} to ${target_origin} should ${
50+
expectation === SUCCESS ? 'succeed' : 'fail'}.`);
51+
}

0 commit comments

Comments
 (0)