-
Notifications
You must be signed in to change notification settings - Fork 251
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Add RFC 6761–compliant localhost loopback checks so secure cookies work on localhost (fixes: #382) #498
base: master
Are you sure you want to change the base?
feat: Add RFC 6761–compliant localhost loopback checks so secure cookies work on localhost (fixes: #382) #498
Conversation
@Chriss4123 thanks for this pull request! I try to review it by the end of the week. |
lib/cookie/cookieJar.ts
Outdated
const secure = | ||
context.protocol && | ||
(context.protocol == 'https:' || context.protocol == 'wss:') | ||
const secure = isPotentiallyTrustworthy(url); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since you're already editing this line, could you also rename const secure
to const secureConnection
to align with the suggested rename of the isPotentiallyTrustworthy
function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
secureConnection
would be misleading here as it can be interpreted as having established a connection and done a valid tls/ssl handshake when in fact we are only checking the scheme and/or localhost.
I think secure
is fine, however I could also do potentiallyTrustworthy
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we please consider potentiallyTrustworthy
or maybe even, potentiallyTrusted
here? I think secure
has the same issue as secureConnection
, that you've identified.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we please consider
potentiallyTrustworthy
or maybe even,potentiallyTrusted
here? I thinksecure
has the same issue assecureConnection
, that you've identified.
I like this solution. I'll also add a link to https://www.w3.org/TR/secure-contexts/#is-origin-trustworthy above the line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I had considered maybe leaving it as just secure
is fine but I think secureConnection
would help to disambiguate between the cookie's Secure
attribute and what the RFC is referring to here ("secure" connection
) in the Storage Model implementation details.
Let's put a pin on this for now though while we discuss the overall terminology in #498 (comment)
* @returns `true` if the URL is potentially trustworthy, otherwise `false`. | ||
* @see {@link https://w3c.github.io/webappsec-secure-contexts/#potentially-trustworthy-origin W3C Spec} | ||
*/ | ||
export function isPotentiallyTrustworthy(inputUrl: string | URL): boolean { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
export function isPotentiallyTrustworthy(inputUrl: string | URL): boolean { | |
export function isSecureConnection(inputUrl: string | URL): boolean { |
RFC6265bis-19 uses the terminology "secure" connection
when referring to the behaviour being outlined in this PR. E.g.;
If the request-uri does not denote a "secure" connection (as defined by the user agent), and the cookie's secure-only-flag is true, then abort these steps and ignore the cookie entirely.
NOTE: The notion of a "secure" connection is not defined by this document. Typically, user agents consider a connection secure if the connection makes use of transport-layer security, such as SSL or TLS, or if the host is trusted. For example, most user agents consider "https" to be a scheme that denotes a secure protocol and "localhost" to be trusted host.
This function should reflect that terminology and be renamed to isSecureConnection
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Secure Contexts uses the terminology 'potentially trustworthy'. What you described is an actual secure connection, i.e. if the web server has an SSL certificate installed.
When a browser (i.e. Chromium) decides to send Secure
cookies, it checks the scheme for https
, wss
, etc. If it then connects to the server and it doesn't have an SSL certificate the request will fail anyways thus the cookies won't get sent.
localhost
is an exception to this as it is considered potentially trustworthy.
A potentially trustworthy origin indicates that the scheme is of secure nature and/or we are on localhost. An actual "secure" connection means the web server has an SSL certificate which we can't check.
Therefore I believe isPotentiallyTrustworthy
is more suitable here as it would be misleading to label it as secure when we in fact don't know that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Understood @Chriss4123, though my intention here was to ground the naming in language referenced in RFC6265bis-19 which is deliberately vague about how it's defining this concept. Again, I'll point to the following:
NOTE: The notion of a "secure" connection is not defined by this document. Typically, user agents consider a connection secure if the connection makes use of transport-layer security, such as SSL or TLS, or if the host is trusted. For example, most user agents consider "https" to be a scheme that denotes a secure protocol and "localhost" to be trusted host.
Based on the examples given in the above text, the concept of a "secure connection" from this RFC can cover both the scheme and host.
You point out in your reply, that this is inaccurate and the terminology from Secure Contexts is more suitable. I don't disagree with you but I still prefer the terminology of "secure connection" to be used in the code because:
- In RFC6265bis-19 you will find the phrase
"secure" connection
referenced at multiple points in the implementation details in both the Retrieval Algorithm and the Storage Model where the code from your PR is called - The phrase
potentially trustworthy origin
can be found buried in Appendix A of RFC6265bis-19 but there's no mention of Secure Contexts in the list of references.
So I would ask you to consider this from the perspective of a maintainer. It's easier to compare the implementation to the RFC when the language used in both matches. Even if that language is vague and somewhat misleading (which the RFC explicitly calls out) 😅
Mind you, I'm not going to die on this hill. There's enough overlap in the terminology to backup both arguments (httpwg/http-extensions#2605, httpwg/http-extensions#2759). If we keep the naming of isPotentiallyTrustworthy
then some extra comments will need to be added to connect the dots between how Secure Contexts relates to the implementation details of RFC6265bis-19.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Understood @Chriss4123, though my intention here was to ground the naming in language referenced in RFC6265bis-19 which is deliberately vague about how it's defining this concept. Again, I'll point to the following:
NOTE: The notion of a "secure" connection is not defined by this document. Typically, user agents consider a connection secure if the connection makes use of transport-layer security, such as SSL or TLS, or if the host is trusted. For example, most user agents consider "https" to be a scheme that denotes a secure protocol and "localhost" to be trusted host.
Based on the examples given in the above text, the concept of a "secure connection" from this RFC can cover both the scheme and host.
You point out in your reply, that this is inaccurate and the terminology from Secure Contexts is more suitable. I don't disagree with you but I still prefer the terminology of "secure connection" to be used in the code because:
* In [RFC6265bis-19](https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-19) you will find the phrase `"secure" connection` referenced at multiple points in the implementation details in both the Retrieval Algorithm and the Storage Model where the code from your PR is called * The phrase `potentially trustworthy origin` can be found buried in [Appendix A of RFC6265bis-19](https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-19#appendix-A-1.7.1) but there's no mention of [Secure Contexts](https://www.w3.org/TR/secure-contexts/) in the list of references.
So I would ask you to consider this from the perspective of a maintainer. It's easier to compare the implementation to the RFC when the language used in both matches. Even if that language is vague and somewhat misleading (which the RFC explicitly calls out) 😅
Mind you, I'm not going to die on this hill. There's enough overlap in the terminology to backup both arguments (httpwg/http-extensions#2605, httpwg/http-extensions#2759). If we keep the naming of
isPotentiallyTrustworthy
then some extra comments will need to be added to connect the dots between how Secure Contexts relates to the implementation details of RFC6265bis-19.
RFC6265bis-19 deliberately avoids rigidly defining what constitutes a “secure” connection for cookies, instead deferring that decision to user agents. In the spec’s definition of the Secure
attribute, it explicitly notes that “’secure’ is defined by the user agent”. The cookie retrieval algorithm also requires that a Secure
cookie be sent only if the request’s URL is over a “secure” channel – again left to the UA’s definition. An informative note in the spec:
“NOTE: The notion of a ‘secure’ connection is not defined by this document. Typically, user agents consider a connection secure if the connection makes use of transport-layer security, such as SSL or TLS, or if the host is trusted. For example, most user agents consider ‘https’ to be a scheme that denotes a secure protocol and ‘localhost’ to be [a] trusted host.” (draft-ietf-httpbis-rfc6265bis-19)
This makes it clear the IETF spec intentionally refrains from hard-coding a definition of “secure connection.” Instead, it acknowledges common UA behavior (treating TLS-protected schemes as secure, and even treating certain trusted hosts like localhost
as secure-equivalent), but leaves the exact criteria up to implementations.
RFC6265bis-19 expects browsers to apply their own notion of what is secure. Modern browsers have, in practice, converged on the concept of “potentially trustworthy origins” to make this determination, rather than a naive check of scheme or transport alone.
Potentially Trustworthy Origins
Broadly, the phrase “secure connection” is less precisely defined, whereas “potentially trustworthy origin” (and the related concept of “secure contexts”) is the well-defined, normative standard used to gate security-sensitive behaviors. Multiple authoritative specifications define and use the concept of “potentially trustworthy” in place of ad-hoc notions of security:
-
W3C Secure Contexts Specification: This spec defines what it means for an origin to be potentially trustworthy. It provides an algorithm enumerating conditions under which an origin is considered secure enough. The Secure Contexts spec’s core definition is: “A potentially trustworthy origin is one which a user agent can generally trust as delivering data securely.” This formalizes the intuitive idea mentioned in RFC6265bis’s note that
https
andlocalhost
are considered secure into a normative algorithm. -
WHATWG HTML Standard: HTML integrates the secure contexts concept to determine when a browsing context is a “secure context.” The HTML spec states that “an environment is a secure context if the following algorithm returns true…”, and one of the key steps in that algorithm is: “If the result of Is URL potentially trustworthy? given environment’s top-level creation URL is ‘Potentially Trustworthy’, then return true.”. This defers to the Secure Contexts spec’s “Is origin potentially trustworthy?” check for the top-level page’s origin to decide if a context is secure.
-
WHATWG Fetch Standard: The Fetch spec similarly uses “potentially trustworthy” in defining network request behaviors. For example, the algorithms for handling Mixed Content use this terminology: “Upgrade a mixed content request to a potentially trustworthy URL, if appropriate.” (Fetch Standard - WhatWG).
Summarized: Secure Contexts, HTML, and Fetch (along with related specs like Mixed Content) all treat “potentially trustworthy origin” as the canonical definition of a secure environment. This covers HTTPS and WSS, but also explicitly includes other cases like localhost
, and excludes others (plain http
to remote hosts) – thus providing a precise security model. The term “secure connection” by itself has no formal definition in these specs and could be interpreted in narrower ways (e.g. “only TLS”).
Browser Implementations
Browser behavior has evolved to align with the “potentially trustworthy origin” model as it’s more accurate and future-proof than a simplistic “secure connection” check. Both Chromium and Firefox have made conscious changes to use the broader trustworthy origin concept for cookies marked Secure, rather than just checking for HTTPS:
-
Firefox: Firefox historically allowed Secure cookies on
https://
but not onhttp://
origins. However, as developers increasingly run local servers onhttp://localhost
and expect to use Secure cookies (or the__Host-
/__Secure-
name prefixes which require secure contexts), Mozilla updated Firefox’s implementation to treathttp://localhost
as secure for cookies. The Firefox bug report states the plan: “By RFC6265, the definition of ’secure’ [protocol] is defined by the user-agent. I propose to unify the implementations and usensMixedContentBlocker::IsPotentiallyTrustworthyOrigin()
instead of a simple ’https’ scheme check.” (1618113 - Allow ’secure’ cookies when set by localhost). The code for this can be found here. -
Chromium: Historically, Chrome did allow
Secure
cookies onhttp://localhost
(treating localhost as secure), but it initially did not allow the stricter__Host-
and__Secure-
cookie name prefixes on localhost. The Chromium team has broadened the definition of “secure” for cookies to include potentially trustworthy origins as well. A Chromium issue discussion notes that they consider support for__Host-
/__Secure-
on localhost “in scope”. The cookie handling code defines an enumeration of cookie source schemes with categories for cryptographic vs. non-cryptographic but trustworthy. Chrome’sCookieAccessScheme
includes:kCryptographic
(for HTTPS/WSS, implicitly trustworthy) andkTrustworthy
(for non-HTTPS schemes that are deemed potentially trustworthy). A comment in the source links directly to the W3C Secure Contexts definition of potentially trustworthy origin, showing that Chrome’s engineers explicitly built the Secure=“potentially trustworthy” logic into their implementation...
It’s clear that “secure connection” as a term is too simplistic to capture the real conditions under which cookies (and other features) should be considered secure. A strict reading might equate secure connection only with TLS however both Firefox and Chrome purposefully include “localhost” (no TLS) as secure based on the reasoning that it’s a trustworthy origin. The term potentially trustworthy origin precisely describes the broader notion of security – it includes both cryptographic transport and other trustworthy circumstances (like loopback interfaces, local files, or extension contexts).
Terminology and Maintainability
The phrase “secure connection” is ambiguous without an explicit definition. The RFC6265bis text itself had to add a clarifying note to hint at meaning. If our implementation simply says “if secure connection, then …” we’d likely need a similar comment explaining what “secure” entails. By using the term “potentially trustworthy origin” (or referring to a secure context), we immediately invoke a well-defined concept. It’s unambiguous to a web platform engineer that this means the origin satisfies the standard Secure Contexts criteria. I believe future contributors are more likely to be familiar with the Secure Contexts definition (since it’s used across many specs and APIs) than with the cookie spec’s isolated wording.
Most modern web platform code (both in specs and in browser source) has standardized on talking about “trustworthy” or “secure contexts.” Our cookie implementation logic should speak the same language, aligning itself conceptually with web platforms, and making the code self-documenting in a clearer way.
It’s important to note that using “potentially trustworthy origin” in our implementation detail is not actually contradicting RFC6265bis-19 – it’s clarifying it. The RFC’s intent was clearly that user agents decide what “secure” means. Today’s consensus is that secure = potentially trustworthy origin. Issue discussions in the IETF HTTP Working Group suggest exactly this alignment: to “consider reusing the notion of ‘Is origin potentially trustworthy?’ from the Secure Contexts spec, instead of [a] user-agent-dependent ‘secure protocol’ check”. So while our implementation detail might use a different phrasing than the raw RFC text, it actually reflects the RFC’s prescribed approach (deferring to UA judgment) more faithfully by naming the precise criterion we’ve chosen to follow.
Sticking slavishly to the term “secure connection” for the sake of mirroring the RFC introduces ambiguity and requires redundant explanatory comments.
Using “potentially trustworthy” in place of “secure connection” is a technically sound decision. It is a precisely defined algorithm, and is the best interpretation of the RFC6265bis-19 secure mandate.
I can make appropriate comments linking the two terms thus maintaining fidelity to RFC6265bis-19.
…tps and wss protocols.
@colincasey I've completed all the requested changes and also added a comment linking a potentially trustworthy origin and the notion of a "secure" connection in draft-ietf-httpbis-rfc6265bis-19. I'm ready for you to re-review the PR. |
fixes: #382
Description
This commit extends how cookies are treated in secure contexts by fully recognizing
localhost
and loopback IPs as trustworthy origins, matching the de facto behavior of all modern browsers and RFC 6761. Previously,tough-cookie
defaultedsecure
totrue
only forhttps:
andwss:
URLs, causing cookies withsecure
to not work withlocalhost
.What Changed
New
secureContext.ts
isPotentiallyTrustworthy(url)
by checking:https
orwss
127.0.0.1/8
and::1
localhost
and*.localhost
IsLocalhost
,IsLoopback
andHostNoBracketsPiece
, located at:IsLocalhost
IsLoopback
HostNoBracketsPiece
cookieJar.ts
Updatehttps
andwss
schemes:isPotentiallyTrustworthy
function which accounts for secure schemes,localhost
addresses and loopback addresses.No existing functionality is removed. Where the old check would return true, so does the new check. The only added functionality is treating
localhost
addresses and loopback addresses as secure contexts which was previously not present.All modern browsers (Chrome et. al) support secure cookies on localhost so it only makes sense
tough-cookie
supports this too.