-
Notifications
You must be signed in to change notification settings - Fork 351
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
Add usage advice for Sec- #1818
base: main
Are you sure you want to change the base?
Conversation
There are a lot of examples where the `Sec-` prefix is used without a lot of consideration for why. This change is an attempt to articulate why you might want to use this prefix and deny a website the ability to set a value for a header. Examples of `Sec-` that make the platform worse include `Sec-CH-` prefixed headers, which all engage server content negotiation capabilities that sites might be able to use. I would include `Sec-Browsing-Topics` in this category also, but maybe for more reasons than one. Examples that are mostly just pointless include `Sec-GPC` and `Sec-Purpose`, which both have no security-relevant decision that might be made by a server. The `Sec-Fetch-Dest` and `Sec-Fetch-Mode` headers are good examples of things that would have security consequences if they weren't prefixed. We also have a bunch that are forbidden and not prefixed that make a bunch of sense, like `Connection`. I make an argument for `Sec-WebSocket-Key` in the text, which seems pretty solid to me. I can't make a similar argument for the other websocket headers. `Sec-WebSocket-Accept` is a response-only header, so the prefix makes no sense other than for naming consistency, which is a bad reason. Part of the reason for this is that we're seeing a bunch of cargo-culting in the definition of headers. Take device-bound session credentials (https://github.com/w3c/webappsec-dbsc), which defines a response header called `Sec-Session-Registration`. There, the reason appears to be consistency with request header naming, but it's not clear that the request headers themselves need a `Sec-` prefix either.
I am interested in your example
(To double-check, this is not an example of the advice directly above it about CORS preflights, right? It's just coincidentally right after that, as something else you don't agree with.) I think this falls into a general category where servers are better served by getting accurate information about the purpose of a request, but indeed getting inaccurate information isn't a security problem. (At least, not a security problem more serious than a DOS.) In such cases, I've advised spec writers that using A recent example is our design of
There's also somewhat of a self-reinforcing argument here, because it could be confusing for servers to receive a request with |
I thought that that would attract comment :)
Yeah, I struggled with the transition there. It's coincidental positioning only. I have heard a number of people who say that they received advice about the Your example of speculation is one where the harm isn't obvious. Why would an app want to trigger a fetch marked as prefetch? If you can't imagine a reason, there's a tendency to slap a (Of course, the need for a preflight could make the prefetch too slow to be useful, but that's a separate problem.) |
Martin, thanks for writing this up - Another reason that we liked using Sec- for Storage-Access Headers was that the Sec- namespace is automatically reserved by virtue of the entire prefix being forbidden, making conflicts with existing custom application headers impossible. Do you have any thoughts on that and should we consider this in advice we give to browser developers? |
I don't know what you mean by reserved here. If you mean reserved for this purpose (and not some other purpose), that is why we have IANA registries. The storage access headers appear to be registered, so that's probably not it... (That's not true for a few other headers that others have started to use. Including Reserving a header for the exclusive use of a user agent is somewhat appealing as a user agent developer. You say "mine" and that's the end of the story. No further thought. But adopting that position as a default denies sites the option to use the header. That's probably OK for |
I mean it's impossible to have prior usage of this header on the web, which avoids the pain of finding out whether you're going to break someone's site with it. |
My understanding is that - for new headers like this - HTTP archive is the benchmark. Are you talking about saving one query to that database? |
Co-authored-by: Mike West <[email protected]>
Co-authored-by: Mike West <[email protected]>
Co-authored-by: Simon Pieters <[email protected]>
HTTP Archive covers public traffic, i.e. non-logged in scenarios and non-enterprise. This is a great suggestion but I'm not sure it's sufficient, it's certainly not the same as "literally guaranteed to have no prior usage on the Web". Given that we have a simple mechanism that can make that guarantee for both browsers and servers, why not use it? |
Is avoiding breaking even a single site really a reasonable goal here, considering that a site can also change its private use if there is a clash? Many new headers have been introduced without a |
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.
If we are going to redefine what it means to extend the same-origin policy we should not do that here.
requests</a> include [:Access-Control-Request-Method:], which is [=forbidden | ||
request-headers|forbidden=]. Any <a for=/>headers</a> that a fetch caller sets will not be set on a | ||
<a>CORS-preflight request</a> made by an honest user agent; instead, these are listed in | ||
[:Access-Control-Request-Headers:]. |
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.
I'm not sure this is a compelling example as these were introduced prior to the introduction of the prefix.
<a for=/>request</a> is speculative. A server might choose to avoid triggering side-effects while | ||
processing such a request, such as suppressing the recording of page view metrics. Making this a | ||
<a>forbidden request-header</a> has no security-relevant purpose and the `<code>Sec-</code>` prefix | ||
is therefore unnecessary. |
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.
This is a redefinition of the threat model. See w3c/resource-hints#74 (comment) for a discussion of this header.
Sending new headers across origin without preflight and without a Sec-
prefix is an extension of the same-origin policy.
I agree with Anne's point about sending new headers across origins being an SOP issue and I like that this formulates a clear objective rule to follow here. I think it also makes it more clear to me what made me uneasy about this PR - it tries to impose a subjective decision upon browser developers to take their best guess on whether or not their header could be security relevant - with a bias towards not adding the @martinthomson it would be good if you could clearly formulate your reasons for wanting to stop people from "cargo-culting" on From a security standpoint, there should be clear rules though, and I support the threat model that Anne puts forward here. |
There are a lot of examples where the
Sec-
prefix is used without a lot of consideration for why.This change is an attempt to articulate why you might want to use this prefix and deny a website the ability to set a value for a header.
Examples of
Sec-
that make the platform worse includeSec-CH-
prefixed headers, which all engage server content negotiation capabilities that sites might be able to use. I would includeSec-Browsing-Topics
in this category also, but maybe for more reasons than one.Examples that are mostly just pointless include
Sec-GPC
andSec-Purpose
, which both have no security-relevant decision that might be made by a server.The
Sec-Fetch-Dest
andSec-Fetch-Mode
headers are good examples of things that would have security consequences if they weren't prefixed. We also have a bunch that are forbidden and not prefixed that make a bunch of sense, likeConnection
.I make an argument for
Sec-WebSocket-Key
in the text, which seems pretty solid to me. I can't make a similar argument for the other websocket headers.Sec-WebSocket-Accept
is a response-only header, so the prefix makes no sense other than for naming consistency, which is a bad reason.Part of the reason for this is that we're seeing a bunch of cargo-culting in the definition of headers. Take device-bound session credentials (https://github.com/w3c/webappsec-dbsc), which defines a response header called
Sec-Session-Registration
. There, the reason appears to be consistency with request header naming, but it's not clear that the request headers themselves need aSec-
prefix either.Preview | Diff