Skip to content

Commit

Permalink
Don't permit setting SameSite cookies from cross-site contexts.
Browse files Browse the repository at this point in the history
This is almost entirely based on Mike West's preliminary version:
https://chromium-review.googlesource.com/c/chromium/src/+/1528244

The new enforcement blocks the setup portion of some existing WPT tests,
which verified read behavior, so the helper they use was changed to always
set them in a same-site context by PostMessage'ing to a helper window.

Bug: 837412
Change-Id: Iba95d65ec4d0916fb4dfa581efaede50654792d3
  • Loading branch information
Maks Orlovich authored and chromium-wpt-export-bot committed Apr 19, 2019
1 parent 4657e10 commit d0b993e
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 23 deletions.
59 changes: 36 additions & 23 deletions cookies/resources/cookie-helper.sub.js
Expand Up @@ -20,10 +20,6 @@

// Set the global cookie name.
window.HTTP_COOKIE = "cookie_via_http";

// If we're not on |HOST|, move ourselves there:
if (window.location.hostname != HOST)
window.location.hostname = HOST;
})();

// A tiny helper which returns the result of fetching |url| with credentials.
Expand Down Expand Up @@ -120,27 +116,44 @@ window.SameSiteStatus = {
STRICT: "strict"
};

const wait_for_message = (type, origin) => {
return new Promise((resolve, reject) => {
window.addEventListener('message', e => {
if (e.origin != origin) {
reject("Message from unexpected origin in wait_for_message:" + e.origin);
return;
}

if (e.data.type && e.data.type === type)
resolve(e);
}, { once: true });
});
};

// Reset SameSite test cookies on |origin|. If |origin| matches `self.origin`, assert
// (via `document.cookie`) that they were properly removed and reset.
function resetSameSiteCookies(origin, value) {
return credFetch(origin + "/cookies/resources/dropSameSite.py")
.then(_ => {
if (origin == self.origin) {
assert_dom_cookie("samesite_strict", value, false);
assert_dom_cookie("samesite_lax", value, false);
assert_dom_cookie("samesite_none", value, false);
}
})
.then(_ => {
return credFetch(origin + "/cookies/resources/setSameSite.py?" + value)
.then(_ => {
if (origin == self.origin) {
assert_dom_cookie("samesite_strict", value, true);
assert_dom_cookie("samesite_lax", value, true);
assert_dom_cookie("samesite_none", value, true);
}
})
})
async function resetSameSiteCookies(origin, value) {
let w = window.open(origin + "/cookies/samesite/resources/puppet.html");
try {
await wait_for_message("READY", origin);
w.postMessage({type: "drop", useOwnOrigin: true}, "*");
await wait_for_message("drop-complete", origin);
if (origin == self.origin) {
assert_dom_cookie("samesite_strict", value, false);
assert_dom_cookie("samesite_lax", value, false);
assert_dom_cookie("samesite_none", value, false);
}

w.postMessage({type: "set", value: value, useOwnOrigin: true}, "*");
await wait_for_message("set-complete", origin);
if (origin == self.origin) {
assert_dom_cookie("samesite_strict", value, true);
assert_dom_cookie("samesite_lax", value, true);
assert_dom_cookie("samesite_none", value, true);
}
} finally {
w.close();
}
}

// Given an |expectedStatus| and |expectedValue|, assert the |cookies| contains the
Expand Down
32 changes: 32 additions & 0 deletions cookies/samesite/resources/puppet.html
@@ -0,0 +1,32 @@
<!DOCTYPE html>
<script src="/cookies/resources/cookie-helper.sub.js"></script>
<script>
// Helper to either set or clear some cookies on its own origin, or
// (potentially) cross-site on ORIGIN.
window.onmessage = e => {
var originToUse = ORIGIN;
if (e.data.useOwnOrigin)
originToUse = self.origin;

if (e.data.type === "set") {
credFetch(originToUse + "/cookies/resources/setSameSite.py?" + e.data.value)
.then(_ => {
e.source.postMessage({
type: "set-complete",
value: e.data.value
}, "*");
});
}

if (e.data.type === "drop") {
credFetch(originToUse + "/cookies/resources/dropSameSite.py")
.then(_ => {
e.source.postMessage({type: "drop-complete"}, "*");
});
}
};

window.opener.postMessage({
type: "READY"
}, "*");
</script>
30 changes: 30 additions & 0 deletions cookies/samesite/setcookie-lax.html
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<meta charset="utf-8"/>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/cookies/resources/cookie-helper.sub.js"></script>
<script>
promise_test(async function(t) {
let w = window.open(ORIGIN + "/cookies/samesite/resources/puppet.html");
await wait_for_message("READY", ORIGIN);
let random = "" + Math.random();
w.postMessage({type: "set", value: random}, "*");
let e = await wait_for_message("set-complete", ORIGIN)
assert_dom_cookie("samesite_strict", e.data.value, true);
assert_dom_cookie("samesite_lax", e.data.value, true);
assert_dom_cookie("samesite_none", e.data.value, true);
w.close();
}, "Same-site window should be able to set `SameSite=Lax` or `SameSite=Strict` cookies.");

promise_test(async function(t) {
let w = window.open(CROSS_SITE_ORIGIN + "/cookies/samesite/resources/puppet.html");
await wait_for_message("READY", CROSS_SITE_ORIGIN);
let random = "" + Math.random();
w.postMessage({type: "set", value: random}, "*");
let e = await wait_for_message("set-complete", CROSS_SITE_ORIGIN);
assert_dom_cookie("samesite_strict", e.data.value, false);
assert_dom_cookie("samesite_lax", e.data.value, false);
assert_dom_cookie("samesite_none", e.data.value, true);
w.close();
}, "Cross-site window shouldn't be able to set `SameSite=Lax` or `SameSite=Strict` cookies.");
</script>

0 comments on commit d0b993e

Please sign in to comment.