forked from mirrors/gecko-dev
Bug 1892748 Part 1 - Reject control characters in cookie attributes. r=dveditz,cookie-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D208155
This commit is contained in:
parent
00aa7c9a70
commit
ec673d3054
6 changed files with 26 additions and 1010 deletions
|
|
@ -1524,10 +1524,9 @@ bool CookieService::CanSetCookie(
|
||||||
separators = ";" | "="
|
separators = ";" | "="
|
||||||
value-sep = ";"
|
value-sep = ";"
|
||||||
cookie-sep = CR | LF
|
cookie-sep = CR | LF
|
||||||
allowed-chars = <any OCTET except NUL or cookie-sep>
|
allowed-chars = <any OCTET except cookie-sep>
|
||||||
OCTET = <any 8-bit sequence of data>
|
OCTET = <any 8-bit sequence of data>
|
||||||
LWS = SP | HT
|
LWS = SP | HT
|
||||||
NUL = <US-ASCII NUL, null control character (0)>
|
|
||||||
CR = <US-ASCII CR, carriage return (13)>
|
CR = <US-ASCII CR, carriage return (13)>
|
||||||
LF = <US-ASCII LF, linefeed (10)>
|
LF = <US-ASCII LF, linefeed (10)>
|
||||||
SP = <US-ASCII SP, space (32)>
|
SP = <US-ASCII SP, space (32)>
|
||||||
|
|
@ -1547,6 +1546,8 @@ bool CookieService::CanSetCookie(
|
||||||
| "Max-Age" "=" value
|
| "Max-Age" "=" value
|
||||||
| "Comment" "=" value
|
| "Comment" "=" value
|
||||||
| "Version" "=" value
|
| "Version" "=" value
|
||||||
|
| "Partitioned"
|
||||||
|
| "SameSite"
|
||||||
| "Secure"
|
| "Secure"
|
||||||
| "HttpOnly"
|
| "HttpOnly"
|
||||||
|
|
||||||
|
|
@ -1554,7 +1555,6 @@ bool CookieService::CanSetCookie(
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
// helper functions for GetTokenValue
|
// helper functions for GetTokenValue
|
||||||
static inline bool isnull(char c) { return c == 0; }
|
|
||||||
static inline bool iswhitespace(char c) { return c == ' ' || c == '\t'; }
|
static inline bool iswhitespace(char c) { return c == ' ' || c == '\t'; }
|
||||||
static inline bool isterminator(char c) { return c == '\n' || c == '\r'; }
|
static inline bool isterminator(char c) { return c == '\n' || c == '\r'; }
|
||||||
static inline bool isvalueseparator(char c) {
|
static inline bool isvalueseparator(char c) {
|
||||||
|
|
@ -1582,7 +1582,7 @@ bool CookieService::GetTokenValue(nsACString::const_char_iterator& aIter,
|
||||||
++aIter;
|
++aIter;
|
||||||
}
|
}
|
||||||
start = aIter;
|
start = aIter;
|
||||||
while (aIter != aEndIter && !isnull(*aIter) && !istokenseparator(*aIter)) {
|
while (aIter != aEndIter && !istokenseparator(*aIter)) {
|
||||||
++aIter;
|
++aIter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1605,7 +1605,7 @@ bool CookieService::GetTokenValue(nsACString::const_char_iterator& aIter,
|
||||||
|
|
||||||
// process <token>
|
// process <token>
|
||||||
// just look for ';' to terminate ('=' allowed)
|
// just look for ';' to terminate ('=' allowed)
|
||||||
while (aIter != aEndIter && !isnull(*aIter) && !isvalueseparator(*aIter)) {
|
while (aIter != aEndIter && !isvalueseparator(*aIter)) {
|
||||||
++aIter;
|
++aIter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1645,6 +1645,17 @@ static inline void SetSameSiteAttribute(CookieStruct& aCookieData,
|
||||||
aCookieData.rawSameSite() = aValue;
|
aCookieData.rawSameSite() = aValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests for control characters, defined by RFC 5234 to be %x00-1F / %x7F.
|
||||||
|
// An exception is made for HTAB as the cookie spec treats that as whitespace.
|
||||||
|
static bool ContainsControlChars(const nsACString& aString) {
|
||||||
|
const auto* start = aString.BeginReading();
|
||||||
|
const auto* end = aString.EndReading();
|
||||||
|
|
||||||
|
return std::find_if(start, end, [](unsigned char c) {
|
||||||
|
return (c <= 0x1F && c != 0x09) || c == 0x7F;
|
||||||
|
}) != end;
|
||||||
|
}
|
||||||
|
|
||||||
// Parses attributes from cookie header. expires/max-age attributes aren't
|
// 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
|
// folded into the cookie struct here, because we don't know which one to use
|
||||||
// until we've parsed the header.
|
// until we've parsed the header.
|
||||||
|
|
@ -1702,6 +1713,14 @@ bool CookieService::ParseAttributes(nsIConsoleReportCollector* aCRC,
|
||||||
newCookie = GetTokenValue(cookieStart, cookieEnd, tokenString, tokenValue,
|
newCookie = GetTokenValue(cookieStart, cookieEnd, tokenString, tokenValue,
|
||||||
equalsFound);
|
equalsFound);
|
||||||
|
|
||||||
|
if (ContainsControlChars(tokenString) || ContainsControlChars(tokenValue)) {
|
||||||
|
CookieLogging::LogMessageToConsole(
|
||||||
|
aCRC, aHostURI, nsIScriptError::errorFlag, CONSOLE_REJECTION_CATEGORY,
|
||||||
|
"CookieRejectedInvalidCharAttributes"_ns,
|
||||||
|
AutoTArray<nsString, 1>{NS_ConvertUTF8toUTF16(aCookieData.name())});
|
||||||
|
return newCookie;
|
||||||
|
}
|
||||||
|
|
||||||
// decide which attribute we have, and copy the string
|
// decide which attribute we have, and copy the string
|
||||||
if (tokenString.LowerCaseEqualsLiteral(kPath)) {
|
if (tokenString.LowerCaseEqualsLiteral(kPath)) {
|
||||||
aCookieData.path() = tokenValue;
|
aCookieData.path() = tokenValue;
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,8 @@ CookiePathOversize=Cookie “%1$S” is invalid because its path size is too big
|
||||||
CookieRejectedByPermissionManager=Cookie “%1$S” has been rejected by user set permissions.
|
CookieRejectedByPermissionManager=Cookie “%1$S” has been rejected by user set permissions.
|
||||||
# LOCALIZATION NOTE (CookieRejectedInvalidCharName): %1$S is the cookie name.
|
# LOCALIZATION NOTE (CookieRejectedInvalidCharName): %1$S is the cookie name.
|
||||||
CookieRejectedInvalidCharName=Cookie “%1$S” has been rejected for invalid characters in the name.
|
CookieRejectedInvalidCharName=Cookie “%1$S” has been rejected for invalid characters in the name.
|
||||||
|
# LOCALIZATION NOTE (CookieRejectedInvalidCharAttributes): %1$S is the cookie name.
|
||||||
|
CookieRejectedInvalidCharAttributes=Cookie “%1$S” has been rejected for invalid characters in the attributes.
|
||||||
# LOCALIZATION NOTE (CookieRejectedInvalidDomain): %1$S is the cookie name.
|
# LOCALIZATION NOTE (CookieRejectedInvalidDomain): %1$S is the cookie name.
|
||||||
CookieRejectedInvalidDomain=Cookie “%1$S” has been rejected for invalid domain.
|
CookieRejectedInvalidDomain=Cookie “%1$S” has been rejected for invalid domain.
|
||||||
# LOCALIZATION NOTE (CookieRejectedInvalidPrefix): %1$S is the cookie name.
|
# LOCALIZATION NOTE (CookieRejectedInvalidPrefix): %1$S is the cookie name.
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,7 +1,4 @@
|
||||||
[name-ctl.html]
|
[name-ctl.html]
|
||||||
[Cookie with %x0 in name is rejected (DOM).]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Cookie with %x9 in name is accepted (DOM).]
|
[Cookie with %x9 in name is accepted (DOM).]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,4 @@
|
||||||
[value-ctl.html]
|
[value-ctl.html]
|
||||||
[Cookie with %x0 in value is rejected (DOM).]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Cookie with %xa in value is rejected (DOM).]
|
[Cookie with %xa in value is rejected (DOM).]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
[document-cookie.html]
|
|
||||||
expected:
|
|
||||||
if (os == "android") and fission: [OK, TIMEOUT]
|
|
||||||
[document.cookie 2]
|
|
||||||
expected: FAIL
|
|
||||||
Loading…
Reference in a new issue