зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1682450 - Parse only the final SameSite attribute when mutliple are present; r=baku
Differential Revision: https://phabricator.services.mozilla.com/D99740
This commit is contained in:
Родитель
0555a907d0
Коммит
0ebdba6f2c
|
@ -1335,6 +1335,16 @@ bool CookieService::GetTokenValue(nsACString::const_char_iterator& aIter,
|
|||
return false;
|
||||
}
|
||||
|
||||
static inline void SetSameSiteDefaultAttribute(CookieStruct& aCookieData,
|
||||
bool laxByDefault) {
|
||||
aCookieData.rawSameSite() = nsICookie::SAMESITE_NONE;
|
||||
if (laxByDefault) {
|
||||
aCookieData.sameSite() = nsICookie::SAMESITE_LAX;
|
||||
} else {
|
||||
aCookieData.sameSite() = nsICookie::SAMESITE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
// Parses attributes from cookie header. expires/max-age attributes aren't
|
||||
// folded into the cookie struct here, because we don't know which one to use
|
||||
// until we've parsed the header.
|
||||
|
@ -1364,17 +1374,12 @@ bool CookieService::ParseAttributes(nsIConsoleReportCollector* aCRC,
|
|||
|
||||
aCookieData.isSecure() = false;
|
||||
aCookieData.isHttpOnly() = false;
|
||||
aCookieData.sameSite() = nsICookie::SAMESITE_NONE;
|
||||
aCookieData.rawSameSite() = nsICookie::SAMESITE_NONE;
|
||||
|
||||
bool laxByDefault =
|
||||
StaticPrefs::network_cookie_sameSite_laxByDefault() &&
|
||||
!nsContentUtils::IsURIInPrefList(
|
||||
aHostURI, "network.cookie.sameSite.laxByDefault.disabledHosts");
|
||||
|
||||
if (laxByDefault) {
|
||||
aCookieData.sameSite() = nsICookie::SAMESITE_LAX;
|
||||
}
|
||||
SetSameSiteDefaultAttribute(aCookieData, laxByDefault);
|
||||
|
||||
nsDependentCSubstring tokenString(cookieStart, cookieStart);
|
||||
nsDependentCSubstring tokenValue(cookieStart, cookieStart);
|
||||
|
@ -1438,6 +1443,9 @@ bool CookieService::ParseAttributes(nsIConsoleReportCollector* aCRC,
|
|||
aCookieData.rawSameSite() = nsICookie::SAMESITE_NONE;
|
||||
sameSiteSet = true;
|
||||
} else {
|
||||
// Reset to defaults if unknown token value (see Bug 1682450)
|
||||
SetSameSiteDefaultAttribute(aCookieData, laxByDefault);
|
||||
sameSiteSet = false;
|
||||
CookieLogging::LogMessageToConsole(
|
||||
aCRC, aHostURI, nsIScriptError::infoFlag, CONSOLE_SAMESITE_CATEGORY,
|
||||
"CookieSameSiteValueInvalid2"_ns,
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
[multiple-samesite-attributes.https.html]
|
||||
prefs: [network.cookie.sameSite.laxByDefault:true, network.cookie.sameSite.noneRequiresSecure:true]
|
||||
expected:
|
||||
if (os == "mac") and not debug: ["OK", "TIMEOUT"]
|
||||
[Cross-site redirecting to same-host images are strictly same-site]
|
||||
expected: FAIL
|
||||
|
||||
[Cross-site redirecting to subdomain images are strictly same-site]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[multiple-samesite-attributes.https.html?legacy-samesite]
|
||||
prefs: [network.cookie.sameSite.laxByDefault:false, network.cookie.sameSite.noneRequiresSecure:false]
|
||||
expected:
|
||||
if (os == "mac") and not debug: ["OK", "TIMEOUT"]
|
||||
[Cross-site redirecting to same-host images are strictly same-site]
|
||||
expected: FAIL
|
||||
|
||||
[Cross-site redirecting to subdomain images are strictly same-site]
|
||||
expected: FAIL
|
||||
|
|
@ -299,6 +299,28 @@ function resetSameSiteNoneCookies(origin, value) {
|
|||
})
|
||||
}
|
||||
|
||||
// Reset test cookies with multiple SameSite attributes on |origin|.
|
||||
// If |origin| matches `self.origin`, assert (via `document.cookie`)
|
||||
// that they were properly removed.
|
||||
function resetSameSiteMultiAttributeCookies(origin, value) {
|
||||
return credFetch(origin + "/cookies/resources/dropSameSiteMultiAttribute.py")
|
||||
.then(_ => {
|
||||
if (origin == self.origin) {
|
||||
assert_dom_cookie("samesite_unsupported", value, false);
|
||||
assert_dom_cookie("samesite_unsupported_none", value, false);
|
||||
assert_dom_cookie("samesite_unsupported_lax", value, false);
|
||||
assert_dom_cookie("samesite_unsupported_strict", value, false);
|
||||
assert_dom_cookie("samesite_none_unsupported", value, false);
|
||||
assert_dom_cookie("samesite_lax_unsupported", value, false);
|
||||
assert_dom_cookie("samesite_strict_unsupported", value, false);
|
||||
assert_dom_cookie("samesite_lax_none", value, false);
|
||||
}
|
||||
})
|
||||
.then(_ => {
|
||||
return credFetch(origin + "/cookies/resources/setSameSiteMultiAttribute.py?" + value);
|
||||
})
|
||||
}
|
||||
|
||||
//
|
||||
// DOM based cookie manipulation APIs
|
||||
//
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
from cookies.resources.helpers import makeDropCookie, setNoCacheAndCORSHeaders
|
||||
|
||||
def main(request, response):
|
||||
"""Respond to `/cookies/resources/dropSameSiteMultiAttribute.py by dropping
|
||||
the cookies set by setSameSiteMultiAttribute.py"""
|
||||
headers = setNoCacheAndCORSHeaders(request, response)
|
||||
|
||||
# Expire the cookies, and return a JSON-encoded success code.
|
||||
headers.append(makeDropCookie(b"samesite_unsupported", True))
|
||||
headers.append(makeDropCookie(b"samesite_unsupported_none", True))
|
||||
headers.append(makeDropCookie(b"samesite_unsupported_lax", False))
|
||||
headers.append(makeDropCookie(b"samesite_unsupported_strict", False))
|
||||
headers.append(makeDropCookie(b"samesite_none_unsupported", True))
|
||||
headers.append(makeDropCookie(b"samesite_lax_unsupported", True))
|
||||
headers.append(makeDropCookie(b"samesite_strict_unsupported", True))
|
||||
headers.append(makeDropCookie(b"samesite_lax_none", True))
|
||||
return headers, b'{"success": true}'
|
|
@ -0,0 +1,60 @@
|
|||
from cookies.resources.helpers import makeCookieHeader, setNoCacheAndCORSHeaders
|
||||
|
||||
from wptserve.utils import isomorphic_encode
|
||||
|
||||
def main(request, response):
|
||||
"""Respond to `/cookie/set/samesite?{value}` by setting the following combination of cookies:
|
||||
1. `samesite_unsupported={value};SameSite=Unsupported;path=/;Secure`
|
||||
2. `samesite_unsupported_none={value};SameSite=Unsupported;SameSite=None;path=/;Secure`
|
||||
3. `samesite_unsupported_lax={value};SameSite=Unsupported;SameSite=Lax;path=/`
|
||||
4. `samesite_unsupported_strict={value};SameSite=Unsupported;SameSite=Strict;path=/`
|
||||
5. `samesite_none_unsupported={value};SameSite=None;SameSite=Unsupported;path=/;Secure`
|
||||
6. `samesite_lax_unsupported={value};SameSite=Lax;SameSite=Unsupported;path=/;Secure`
|
||||
7. `samesite_strict_unsupported={value};SameSite=Strict;SameSite=Unsupported;path=/;Secure`
|
||||
8. `samesite_lax_none={value};SameSite=Lax;SameSite=None;path=/;Secure`
|
||||
9. `samesite_lax_strict={value};SameSite=Lax;SameSite=Strict;path=/`
|
||||
10. `samesite_strict_lax={value};SameSite=Strict;SameSite=Lax;path=/`
|
||||
Then navigate to a page that will post a message back to the opener with the set cookies"""
|
||||
headers = setNoCacheAndCORSHeaders(request, response)
|
||||
value = isomorphic_encode(request.url_parts.query)
|
||||
|
||||
headers.append((b"Content-Type", b"text/html; charset=utf-8"))
|
||||
# Unknown value; single attribute
|
||||
headers.append(makeCookieHeader(
|
||||
b"samesite_unsupported", value, {b"SameSite":b"Unsupported", b"path":b"/", b"Secure":b""}))
|
||||
|
||||
# Multiple attributes; first attribute unknown
|
||||
headers.append(makeCookieHeader(
|
||||
b"samesite_unsupported_none", value, {b"SameSite":b"Unsupported", b"SameSite":b"None", b"path":b"/", b"Secure":b""}))
|
||||
headers.append(makeCookieHeader(
|
||||
b"samesite_unsupported_lax", value, {b"SameSite":b"Unsupported", b"SameSite":b"Lax", b"path":b"/"}))
|
||||
headers.append(makeCookieHeader(
|
||||
b"samesite_unsupported_strict", value, {b"SameSite":b"Unsupported", b"SameSite":b"Strict", b"path":b"/"}))
|
||||
|
||||
# Multiple attributes; second attribute unknown
|
||||
headers.append(makeCookieHeader(
|
||||
b"samesite_none_unsupported", value, {b"SameSite":b"None", b"SameSite":b"Unsupported", b"path":b"/", b"Secure":b""}))
|
||||
headers.append(makeCookieHeader(
|
||||
b"samesite_lax_unsupported", value, {b"SameSite":b"Lax", b"SameSite":b"Unsupported", b"path":b"/", b"Secure":b""}))
|
||||
headers.append(makeCookieHeader(
|
||||
b"samesite_strict_unsupported", value, {b"SameSite":b"Strict", b"SameSite":b"Unsupported", b"path":b"/", b"Secure":b""}))
|
||||
|
||||
# Multiple attributes; both known
|
||||
headers.append(makeCookieHeader(
|
||||
b"samesite_lax_none", value, {b"SameSite":b"Lax", b"SameSite":b"None", b"path":b"/", b"Secure":b""}))
|
||||
headers.append(makeCookieHeader(
|
||||
b"samesite_lax_strict", value, {b"SameSite":b"Lax", b"SameSite":b"Strict", b"path":b"/"}))
|
||||
headers.append(makeCookieHeader(
|
||||
b"samesite_strict_lax", value, {b"SameSite":b"Strict", b"SameSite":b"Lax", b"path":b"/"}))
|
||||
|
||||
document = b"""
|
||||
<!DOCTYPE html>
|
||||
<script>
|
||||
// A same-site navigation, which should attach all cookies including SameSite ones.
|
||||
// This is necessary because this page may have been reached via a cross-site navigation, so
|
||||
// we might not have access to some SameSite cookies from here.
|
||||
window.location = "../samesite/resources/echo-cookies.html";
|
||||
</script>
|
||||
"""
|
||||
|
||||
return headers, document
|
|
@ -0,0 +1,103 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="timeout" content="long">
|
||||
<meta name="variant" content="">
|
||||
<meta name="variant" content="?legacy-samesite">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/cookies/resources/cookie-helper.sub.js"></script>
|
||||
<script>
|
||||
function assert_cookie_present(origin, name, value) {
|
||||
return new Promise((resolve, reject) => {
|
||||
var img = document.createElement("img");
|
||||
img.onload = _ => resolve("'" + name + "=" + value + "' present on " + origin);
|
||||
img.onerror = _ => reject("'" + name + "=" + value + "' not present on " + origin);
|
||||
|
||||
// We need to URL encode the destination path/query if we're redirecting:
|
||||
if (origin.match(/\/redir/))
|
||||
img.src = origin + encodeURIComponent("/cookies/resources/imgIfMatch.py?name=" + name + "&value=" + value);
|
||||
else
|
||||
img.src = origin + "/cookies/resources/imgIfMatch.py?name=" + name + "&value=" + value;
|
||||
});
|
||||
}
|
||||
|
||||
function assert_cookie_absent(origin, name, value) {
|
||||
return new Promise((resolve, reject) => {
|
||||
var img = document.createElement("img");
|
||||
img.onload = _ => reject("'" + name + "=" + value + "' present on " + origin);
|
||||
img.onerror = _ => resolve("'" + name + "=" + value + "' not present on " + origin);
|
||||
|
||||
// We need to URL encode the destination path/query if we're redirecting:
|
||||
if (origin.match(/\/redir/))
|
||||
img.src = origin + encodeURIComponent("/cookies/resources/imgIfMatch.py?name=" + name + "&value=" + value);
|
||||
else
|
||||
img.src = origin + "/cookies/resources/imgIfMatch.py?name=" + name + "&value=" + value;
|
||||
});
|
||||
}
|
||||
|
||||
function create_test(origin, target, expectedStatus, title) {
|
||||
promise_test(t => {
|
||||
var value = "" + Math.random();
|
||||
return resetSameSiteMultiAttributeCookies(origin, value)
|
||||
.then(_ => {
|
||||
var asserts = [
|
||||
assert_cookie_present(target, "samesite_unsupported_none", value),
|
||||
assert_cookie_present(target, "samesite_lax_none", value),
|
||||
expectedStatus == SameSiteStatus.STRICT ?
|
||||
assert_cookie_present(target, "samesite_unsupported_strict", value) :
|
||||
assert_cookie_absent(target, "samesite_unsupported_strict", value),
|
||||
expectedStatus == SameSiteStatus.STRICT ?
|
||||
assert_cookie_present(target, "samesite_lax_strict", value) :
|
||||
assert_cookie_absent(target, "samesite_lax_strict", value),
|
||||
expectedStatus == SameSiteStatus.CROSS_SITE ?
|
||||
assert_cookie_absent(target, "samesite_unsupported_lax", value) :
|
||||
assert_cookie_present(target, "samesite_unsupported_lax", value),
|
||||
expectedStatus == SameSiteStatus.CROSS_SITE ?
|
||||
assert_cookie_absent(target, "samesite_strict_lax", value) :
|
||||
assert_cookie_present(target, "samesite_strict_lax", value)
|
||||
];
|
||||
if (isLegacySameSite()) {
|
||||
// Legacy behavior: unsupported SameSite value acts like SameSite=None.
|
||||
asserts.push(assert_cookie_present(target, "samesite_none_unsupported", value));
|
||||
asserts.push(assert_cookie_present(target, "samesite_lax_unsupported", value));
|
||||
asserts.push(assert_cookie_present(target, "samesite_strict_unsupported", value));
|
||||
asserts.push(assert_cookie_present(target, "samesite_unsupported", value));
|
||||
} else {
|
||||
asserts.push(expectedStatus == SameSiteStatus.CROSS_SITE ?
|
||||
assert_cookie_absent(target, "samesite_none_unsupported", value) :
|
||||
assert_cookie_present(target, "samesite_none_unsupported", value));
|
||||
asserts.push(expectedStatus == SameSiteStatus.CROSS_SITE ?
|
||||
assert_cookie_absent(target, "samesite_lax_unsupported", value) :
|
||||
assert_cookie_present(target, "samesite_lax_unsupported", value));
|
||||
asserts.push(expectedStatus == SameSiteStatus.CROSS_SITE ?
|
||||
assert_cookie_absent(target, "samesite_strict_unsupported", value) :
|
||||
assert_cookie_present(target, "samesite_strict_unsupported", value));
|
||||
asserts.push(expectedStatus == SameSiteStatus.CROSS_SITE ?
|
||||
assert_cookie_absent(target, "samesite_unsupported", value) :
|
||||
assert_cookie_present(target, "samesite_unsupported", value));
|
||||
}
|
||||
return Promise.all(asserts);
|
||||
});
|
||||
}, title);
|
||||
}
|
||||
|
||||
// No redirect:
|
||||
create_test(SECURE_ORIGIN, SECURE_ORIGIN, SameSiteStatus.STRICT, "Same-host images are strictly same-site");
|
||||
create_test(SECURE_SUBDOMAIN_ORIGIN, SECURE_SUBDOMAIN_ORIGIN, SameSiteStatus.STRICT, "Subdomain images are strictly same-site");
|
||||
create_test(SECURE_CROSS_SITE_ORIGIN, SECURE_CROSS_SITE_ORIGIN, SameSiteStatus.CROSS_SITE, "Cross-site images are cross-site");
|
||||
|
||||
// Redirect from {same-host,subdomain,cross-site} to same-host:
|
||||
create_test(SECURE_ORIGIN, redirectTo(SECURE_ORIGIN, SECURE_ORIGIN), SameSiteStatus.STRICT, "Same-host redirecting to same-host images are strictly same-site");
|
||||
create_test(SECURE_ORIGIN, redirectTo(SECURE_SUBDOMAIN_ORIGIN, SECURE_ORIGIN), SameSiteStatus.STRICT, "Subdomain redirecting to same-host images are strictly same-site");
|
||||
create_test(SECURE_ORIGIN, redirectTo(SECURE_CROSS_SITE_ORIGIN, SECURE_ORIGIN), SameSiteStatus.STRICT, "Cross-site redirecting to same-host images are strictly same-site");
|
||||
|
||||
// Redirect from {same-host,subdomain,cross-site} to same-host:
|
||||
create_test(SECURE_SUBDOMAIN_ORIGIN, redirectTo(SECURE_ORIGIN, SECURE_SUBDOMAIN_ORIGIN), SameSiteStatus.STRICT, "Same-host redirecting to subdomain images are strictly same-site");
|
||||
create_test(SECURE_SUBDOMAIN_ORIGIN, redirectTo(SECURE_SUBDOMAIN_ORIGIN, SECURE_SUBDOMAIN_ORIGIN), SameSiteStatus.STRICT, "Subdomain redirecting to subdomain images are strictly same-site");
|
||||
create_test(SECURE_SUBDOMAIN_ORIGIN, redirectTo(SECURE_CROSS_SITE_ORIGIN, SECURE_SUBDOMAIN_ORIGIN), SameSiteStatus.STRICT, "Cross-site redirecting to subdomain images are strictly same-site");
|
||||
|
||||
// Redirect from {same-host,subdomain,cross-site} to cross-site:
|
||||
create_test(SECURE_CROSS_SITE_ORIGIN, redirectTo(SECURE_ORIGIN, SECURE_CROSS_SITE_ORIGIN), SameSiteStatus.CROSS_SITE, "Same-host redirecting to cross-site images are cross-site");
|
||||
create_test(SECURE_CROSS_SITE_ORIGIN, redirectTo(SECURE_SUBDOMAIN_ORIGIN, SECURE_CROSS_SITE_ORIGIN), SameSiteStatus.CROSS_SITE, "Subdomain redirecting to cross-site images are cross-site");
|
||||
create_test(SECURE_CROSS_SITE_ORIGIN, redirectTo(SECURE_CROSS_SITE_ORIGIN, SECURE_CROSS_SITE_ORIGIN), SameSiteStatus.CROSS_SITE, "Cross-site redirecting to cross-site images are cross-site");
|
||||
</script>
|
Загрузка…
Ссылка в новой задаче