-
Notifications
You must be signed in to change notification settings - Fork 166
Add Sec- prefix to security considerations #776
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
Conversation
|
My opinion doesn't carry a lot of weight here, but I like both Ilya's suggestion also LGTM. |
|
Well, the discussion is in #716 - maybe this is a good topic for the WG meetings in Montreal? |
|
OK, I'll revive the discussion there |
66c12d7 to
50248e9
Compare
|
@igrigorik - integrated your suggestions and then suggestions from @sleevi. PTAL? |
igrigorik
left a comment
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.
Yep, this looks great!
Per Ryan's earlier comment.. I don't have a strong opinion on whether CH- bit is necessary. I'll defer to @mnot and @martinthomson's guidance here.
9c1b603 to
a2f6bab
Compare
|
mnot@ - Friendly ping :) Do you think the "CH-" bit is required? |
| ## Deployment and Security Risks | ||
| Deployment of new request headers requires several considerations: | ||
|
|
||
| - Potential conflicts due to existing use of field name |
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.
That's managed by registering the header field, and is well-documented in HTTP. Why is this important to call out here?
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.
The example I had in mind were the conflicts @mikewest ran into when deploying the initial version of upgrade-insecure-requests as https. I believe that resulted in some server side conflicts with some servers that already used that name internally, and read all incoming request headers to be global variables. (@mikewest - please correct me if I remember that wrong)
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.
Some versions of PHP do strange things with certain headers. https was one of them. I'm not sure that has much weight in either direction, except as an anecdote that gave me a very bad week a few years ago. :)
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.
Sure. I just don't know why we're doing this specifically here, rather than relying on the generic HTTP text (DRY and all that). Not a huge deal, just struck me as odd.
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.
So Yoav explained that the main reason here is that the reason for the Sec- prefix was to avoid problems like the one where header fields are turned into environment variables in a non-injective fashion by some frameworks. So you get the value of the "Foo" header field mixed in with the "foo" query parameter. That motivates a prefix, but it doesn't motivate the "Sec-" one.
I hadn't heard that reason properly before. It took me a while to internalize it.
And then it didn't make sense. The more I think about this, the more that I think that the "CH-" prefix is useful, but the "Sec-" one isn't. On the contrary, I see value in giving script the ability to query for different content using these header fields. For one, it might allow an app that is preparing for going offline in the browser the ability to request content based on anticipated rather than current needs.
For example, assuming for a moment that I thought Save-Data was useful (it's not), then the content could request the lightweight content that this targets, to avoid expending resources on the fetch or storage. At that point, I don't have to have an opinion on Save-Data from the browser perspective, it might as well be yet another proprietary header field.
yoavweiss
left a comment
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.
Thanks for reviewing! :)
| ## Deployment and Security Risks | ||
| Deployment of new request headers requires several considerations: | ||
|
|
||
| - Potential conflicts due to existing use of field name |
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.
The example I had in mind were the conflicts @mikewest ran into when deploying the initial version of upgrade-insecure-requests as https. I believe that resulted in some server side conflicts with some servers that already used that name internally, and read all incoming request headers to be global variables. (@mikewest - please correct me if I remember that wrong)
|
Friendly ping! :) |
igrigorik
left a comment
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.
Looks good on this end 👍
@mnot I'll defer to you for final once over and approve.
martinthomson
left a comment
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.
Originally, I was sure I didn't understand this. Then I thought that I might have understood. Now I'm closer to being sure that I think this is not the right answer.
draft-ietf-httpbis-client-hints.md
Outdated
| - Potential conflicts due to existing use of field name | ||
| - Properties of the data communicated in field value | ||
|
|
||
| Specifications and features relying on Client Hints are advised to carfully consider prefixing request header names with a "Sec-" prefix. User agents, such as web browsers, ensure such prefixed headers can only be emitted by the browser, and application content, such as scripts, are forbidden from emitting such headers {{FETCH}}. This provides assurance that, when transmitted by user agents, the type, format and value of data communicated in such request headers are enforced by the user agent. |
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.
carfully?
Also, the number, of, commas, here, is, starting to, get tiresome. Maybe there are two sentences in that second one.
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 think it's much more clear to say something like:
Authors of new Client Hints are advised to carefully consider whether they should be able to be added by client-side content (e.g., scripts), or whether they should be exclusively set by the user agent. In the latter case, the Sec- prefix on the header field name has the effect of preventing scripts and other application content from setting them in many user agents. See {{FETCH}} for more information.
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.
That is definitely better phrasing. Assuming that you still want to do this based on my earlier comments.
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.
Oops regarding "carfully"...
Otherwise, I like @mnot's proposed text, assuming we are fine with user-added Client-Hints. I need to give them some more thought.
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.
Yeah, Mark's text seems fine to me.
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.
Using the "Sec-" prefix signals to servers that the user agent - and not application content - generated the values.
| ## Deployment and Security Risks | ||
| Deployment of new request headers requires several considerations: | ||
|
|
||
| - Potential conflicts due to existing use of field name |
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.
So Yoav explained that the main reason here is that the reason for the Sec- prefix was to avoid problems like the one where header fields are turned into environment variables in a non-injective fashion by some frameworks. So you get the value of the "Foo" header field mixed in with the "foo" query parameter. That motivates a prefix, but it doesn't motivate the "Sec-" one.
I hadn't heard that reason properly before. It took me a while to internalize it.
And then it didn't make sense. The more I think about this, the more that I think that the "CH-" prefix is useful, but the "Sec-" one isn't. On the contrary, I see value in giving script the ability to query for different content using these header fields. For one, it might allow an app that is preparing for going offline in the browser the ability to request content based on anticipated rather than current needs.
For example, assuming for a moment that I thought Save-Data was useful (it's not), then the content could request the lightweight content that this targets, to avoid expending resources on the fetch or storage. At that point, I don't have to have an opinion on Save-Data from the browser perspective, it might as well be yet another proprietary header field.
|
The I don't feel very strongly about this particular case, but in general I'm worried about browsers sending new unprefixed headers by default for this reason. |
|
I believe @annevk had some comments about similar situations in the past. |
|
@arturjanc that basically means we can't define any new request HTTP headers, which is pretty demonstrably untrue. What we shouldn't do is choose especially generic names, like |
|
Also, the establishment of the convention to use a "CH-" prefix would seem to avoid that problem amply. But @mnot's point is the stronger one. I realize that having a standard bulldoze your established use of "My-Header" is an experience people are reluctant to be exposed to the possibility of, but they could always register header field names. |
|
Each new request header that a browser is to transmit cross-origin and is not prefixed with Furthermore, some new request headers are not supposed to be spoofable same-origin and for those the prefix is important too. We have not had to update https://fetch.spec.whatwg.org/#forbidden-header-name for about a decade now and it would be nice to keep it that way. (There's also a problem if an attacker can control these fields somehow. We've had to impose length restrictions on Referer and the CORS-safelisted request-headers. I suspect that's not applicable to client hints.) |
|
(OK, disclaimer: I'm not 100% clear on the model for cross-origin use of client hints then, but this is my operating model. If this model is incorrect somehow, I think that the fetch changes here are what needs adjusting...) Given that these aren't sent unless the server specifically requests them, I think that the cross-origin concern isn't that significant. Rather than insisting on a one-by-one exception, a systemic exception for client hints would be preferable. The way that this draft models CH header fields is that the site collects the information and injects the header field in every request as it leaves for the server (as if by service worker fetch interception). The browser is just helping out. If we are able to adhere to that model, then allowing insertion is different than header fields like If this model is correct, then it doesn't make sense for these to be forbidden or for them to require special processing for exemption. Note that this changes how the information needs to be generated (it can't access privileged information; that's already in this doc), and it means that these are treated like any other header field. As for concerns about interaction with ambient authority that a server might associate with the request, I think that I will point back at the bit where the server explicitly asked for the hint to be provided. I concede that cross-resource concerns might be a problem (resource A asks, resource B is unprepared), but the set of fields will be small, carefully groomed by browser makers, mostly prefixed with |
|
Agreed that if the server asks for the browser to set these headers on subsequent requests the cross-origin concern does not apply. However, that does assume these headers are not attacker-controlled and depending on when they are set (and the ask has been that they are set early to expose them to service workers as normal headers) they would also have to bypass CORS and we'd have to ensure they cannot be manipulated, etc. And writing that down I realize there's a security problem there as now A can figure out that B requested client hints (and see what hints B will get). Also, does the spoofing concern not apply? It's also not entirely clear if server opt-in is tenable as we've seen requests for client hint like data to be available on the first request. |
That is true for the same origin case, but not for the cross-origin one. For privacy purposes, we've limited the Client Hints opt-in to top-level documents, so a cross-origin resource cannot opt-in to client hints. And with Feature Policy, the top-level document can delegate hints to certain origins. That means that those origins will get the hints without opting into them, which increases the risk. At the same time, we want to avoid Client Hints request headers from triggering preflights, while being sure that it's indeed safe to do so. |
A seeing the values isn't an issue as it is A that put the hints there (and A sees the same values). I don't see A having influence over values (viewport width maybe...). B being unprepared for the hints does seem to be a problem. I know that avoiding preflight is appealing from a performance perspective, but that's how we've decided to operate for these things. Because A is essentially forcing the inclusion of header fields into cross-origin requests, I think that we have a few options:
FWIW, for the first reason, we can't remember that B was OK with hints when it was top-level or framed in C because that lets A observe that B has been visited elsewhere. |
I'm not sure we need to do a lot of pretending here ;-) We know that applications can't get |
|
@martinthomson - does @arturjanc's response answer concerns you had around option (4)? |
|
At IETF 106, we agreed that it might be better to modify this so that the infrastructure draft indicates that features need to make sure that adding new request headers would be safe for servers. Individual features would then be able to decide if they enforce |
d2882b8 to
30afe42
Compare
@martinthomson - looking at the current language, it seems to well-align with that decision without much modification. Can you take a look and let me know if you agree? |
|
@martinthomson - friendly ping! :) |
|
Post holidays ping! :) |
martinthomson
left a comment
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 seeing pretty strong encouragement to use "Sec-" here.
draft-ietf-httpbis-client-hints.md
Outdated
| - Potential conflicts due to existing use of field name | ||
| - Properties of the data communicated in field value | ||
|
|
||
| Specifications and features relying on Client Hints are advised to carfully consider prefixing request header names with a "Sec-" prefix. User agents, such as web browsers, ensure such prefixed headers can only be emitted by the browser, and application content, such as scripts, are forbidden from emitting such headers {{FETCH}}. This provides assurance that, when transmitted by user agents, the type, format and value of data communicated in such request headers are enforced by the user agent. |
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.
Using the "Sec-" prefix signals to servers that the user agent - and not application content - generated the values.
…xtensions into client_hints_sec_prefix
draft-ietf-httpbis-client-hints.md
Outdated
| Authors of new Client Hints are advised to carefully consider whether they should be able to be added by client-side content (e.g., scripts), or whether they should be exclusively set by the user agent. In the latter case, the Sec- prefix on the header field name has the effect of preventing scripts and other application content from setting them in user agents. | ||
| Using the "Sec-" prefix signals to servers that the user agent - and not application content - generated the values. See {{FETCH}} for more information. | ||
|
|
||
| By convention, request headers that are client hints are encouraged to use a CH- prefix, to make them easier to identify as using this framework; for example, Sec-CH-Foo. Doing so makes them easier to identify programmatically (e.g., for stripping unrecognised hints from requests by privacy filters). |
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.
By convention, request headers that are client hints are encouraged to use a CH- prefix, to make them easier to identify as using this framework; for example, CH-Foo or, with a "Sec-" prefix, Sec-CH-Foo. Doing so makes them easier to identify programmatically (e.g., for stripping unrecognised hints from requests by privacy filters).
As discussed in #716 and #775, this PR adds a recommended
Sec-prefix to Client Hints request header values.Open questions:
Sec-CH?MUST?/cc @igrigorik @reschke @mnot @mikewest @arturjanc