-
Notifications
You must be signed in to change notification settings - Fork 333
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
π Bug Report β Strange header issue with fetch
URLs that redirect
#2223
Comments
Seems CF has the same issue |
You can repro this with curl with the
|
FWIW this was a CVE https://curl.se/docs/CVE-2018-1000007.html and it's expected to not pass auth headers to a redirection if the origins are not the same. and in node it makes sure not to send it in a redirection to a cross origin call. They delete it here: |
The whatwg spec for fetch, specifically item 13 is what is at play here: https://fetch.spec.whatwg.org/#http-redirect-fetch It appears that it is mostly handled but a few items from the spec have been missed here: workerd/src/workerd/api/http.c++ Lines 1935 to 2034 in 21b7aba
Happy to throw my hat in the ring to fix if I get some time. |
"Thinking aloud": main...nickhudkins:workerd:fix/fetch-redirect-spec |
[EDIT: They changed the spec. π€¦ See comments below.] This is functioning according to spec. The behavior is exactly the same as what is implemented in browsers. To understand this, it is important to understand the difference between ambient and explicit credentials. Ambient credentials are credentials which a browser automatically adds to all requests based on the hostname to which they are addressed. This includes cookies and HTTP basic auth (old browser-builtin username/password authentication that no one uses anymore). Explicit credentials are credentials which the application explicitly passes to fetch(), such as when writing code like:
Note that HTTP basic auth uses the Only ambient credentials are required to be dropped on a redirect. Explicit header values are never dropped. This is the behavior in Chrome and other browsers. Chrome WILL keep the Cloudflare Workers does not implement any ambient credentials. The This is not a security vulnerability in In fact, this behavior is desirable. Say you are serving an API from some hostname, and you decide to move to the API to a different hostname using a redirect. Say your API client authenticate via an OAuth access token. If redirects dropped authorization headers, then all your clients would break -- the redirect would be useless. You therefore cannot move your API to a new hostname. I do realize that some HTTP client libraries have nevertheless decided to implement this behavior of dropping the |
I think I may have miscommunicated because I am not talking about the difference between ambient and explicit credentials, which, thank you for the thorough explanation, but.... This is about the whatwg spec, Step 13. Which explicitly calls out dropping certain headers when origins do not match during the redirection process. Is there some different spec that Workers follows? |
@nickhudkins yeah I see it here as well described in 4.4. HTTP-redirect fetch -> step 13. |
I agree that that line appears to contradict what I'm saying, which is weird because this issue came up in the past and we investigated it pretty carefully at the time. I specifically tested in Chrome and verified that the Authorization header wasn't dropped. Did the spec change? |
Interesting! Not sure if the spec changed, and I understand how seriously this could break A LOT of folks if introduced without gating it behind a flag or something, really just surprising behavior due to the behavior of NodeJS, and (my) maybe incorrect? assumption that |
It appears the spec was indeed changed, several months after I reviewed this last. Changed November 2022: whatwg/fetch@9004f4e That time when Node changed this and I argued they were breaking spec, Jan 2022: node-fetch/node-fetch#1449 (comment) Ugh. |
Just for a differential... I tested quickly in Node.js, Deno, and Bun... Node.js and Bun both remove the |
Nope! When Node implemented this, it was against spec. The spec changed later on to match Node! |
Well, that was |
@jasnell beat me to it :) |
Oh... sorry, I didn't realize node-fetch isn't node's fetch implementation. |
Either way... I guess we need to decide how to handle this as it is technically a breaking change. Our options are:
|
No worries lol... you're not the first and won't be the last. It's caused quite a bit of confusion over the years. Node.js implementation is provided by https://github.com/nodejs/undici |
I am surprised they made this spec change as it is backwards-incompatible. There could be API servers out there that were relying on the ability to redirect to a new hostname. I thought I heard of at least one person broken by the node-fetch change in the wild. So on one hand I feel like this needs a compat flag. But on the other hand it's weird to use a compat flag on what could arguably be a security bug? I think this is only a security problem in the presence of other security problems. For example, in whatwg/fetch#944 they give the example of an attacker setting their username to Of course, many APIs use other header names for authorization and so aren't defended by this rule. So again... it can't be a security flaw in itself, it's more of a defensive measure. So probably a compat flag is the right way to go? |
That's where I'm leaning also. |
While I do not have deciding powers, a compat flag makes most sense to me as well. Thanks for getting through that. @Hacksore and I spent an unreasonable amount of time digging around to see where the divergence showed up across different runtimes, and then found the |
I am happy for anything the CF team decides to solve this. Glad @nickhudkins and I were able to discover the root cause cause it was driving me insane. |
Here's a thread where people complained about the spec change breaking things: whatwg/fetch#1631 So seems pretty clear this should be a compat flag. |
"In non-server environments you could not rely on this behavior so there it is not considered a breaking change..." The WHATWG's philosophy of not caring about anything but browsers bites again. Fun. |
@Hacksore @nickhudkins thanks for reporting! Not yet sure when we'll get the fix in but will get it scheduled. |
Closing as this as it is on your radar now. Feel free to reply here when it has been patched if possible π. |
We should keep this open so we don't forget it. |
Warning
WIP issue please be patient
I have a worker where I am attempting to fetch artifacts from the github api.
This API returns a 302 to a signed download URL. So what I think is happening is the
Authentication
header is also being sent to the signed url server which results in an error.Repro that I'm working on:
https://github.com/Hacksore/fetch-with-github-artifacts
Same issue exists in prod:
https://fetch-with-github-artifacts.hacksore.workers.dev
I was able to figure out that it has to be the auth token making it down stream.
Note workaround:
We just have to fetch without redirect and then do another fetch to omit sending the
Authenticated
header.The text was updated successfully, but these errors were encountered: