Skip to content
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

fix: miniflare now sets the "Host" header to match the upstream URL #4630

Merged
merged 7 commits into from
Jan 3, 2024

Conversation

petebacondarwin
Copy link
Contributor

@petebacondarwin petebacondarwin commented Dec 19, 2023

Fixes #4643
Fixes cloudflare/next-on-pages#588

It is good to review this PR commit by commit.

What this PR solves / how to test:

Some full-stack frameworks, such as Next.js, check that the Host header for a server
side action request matches the host where the application is expected to run.

In wrangler dev we have a Proxy Worker in between the browser and the actual User Worker.
This Proxy Worker is forwarding on the request from the browser, but then the actual User
Worker is running on a different host:port combination than that which the browser thinks
it should be on. This was causing the framework to think the request is malicious and blocking
it.

Now we update the request's Host header to that passed from the Proxy Worker in a custom MF-Original-Url
header, but only do this if the request also contains a shared secret between the Proxy Worker
and User Worker, which is passed via the MF-Proxy-Shared-Secret header. This last feature is to
prevent a malicious website from faking the Host header in a request directly to the User Worker.

The worker-app fixture has been updated to check that this is working as expected.

Author has addressed the following:

  • Tests
    • Included
    • Not necessary because:
  • Changeset (Changeset guidelines)
    • Included
    • Not necessary because:
  • Associated docs
    • [] Issue(s)/PR(s):
    • Not necessary because: internal changes requiring no documentation

@petebacondarwin petebacondarwin requested a review from a team as a code owner December 19, 2023 12:33
Copy link

changeset-bot bot commented Dec 19, 2023

🦋 Changeset detected

Latest commit: 66ea286

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
miniflare Patch
wrangler Patch
@cloudflare/pages-shared Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@petebacondarwin petebacondarwin added bug Something that isn't working miniflare Relating to Miniflare wrangler Relating to the Wrangler CLI tool e2e Run e2e tests on a PR labels Dec 19, 2023
Copy link
Contributor

github-actions bot commented Dec 19, 2023

A wrangler prerelease is available for testing. You can install this latest build in your project with:

npm install --save-dev https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/7396783059/npm-package-wrangler-4630

You can reference the automatically updated head of this PR with:

npm install --save-dev https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/prs/7396783059/npm-package-wrangler-4630

Or you can use npx with this latest build directly:

npx https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/7396783059/npm-package-wrangler-4630 dev path/to/script.js
Additional artifacts:
npm install https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/7396783059/npm-package-miniflare-4630
npm install https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/7396783059/npm-package-cloudflare-pages-shared-4630
npx https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/7396783059/npm-package-create-cloudflare-4630 --no-auto-update

Note that these links will no longer work once the GitHub Actions artifact expires.


wrangler@3.22.2 includes the following runtime dependencies:

Package Constraint Resolved
miniflare workspace:* 3.20231218.0
workerd 1.20231218.0 1.20231218.0
workerd --version 1.20231218.0 2023-12-18

|

Please ensure constraints are pinned, and miniflare/workerd minor versions match.

Copy link

codecov bot commented Dec 19, 2023

Codecov Report

All modified and coverable lines are covered by tests ✅

Comparison is base (9e03272) 75.58% compared to head (66ea286) 75.67%.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #4630      +/-   ##
==========================================
+ Coverage   75.58%   75.67%   +0.08%     
==========================================
  Files         243      243              
  Lines       13084    13087       +3     
  Branches     3368     3368              
==========================================
+ Hits         9890     9903      +13     
+ Misses       3194     3184      -10     
Files Coverage Δ
packages/wrangler/src/dev/local.tsx 25.92% <ø> (ø)
packages/wrangler/src/dev/miniflare.ts 63.30% <100.00%> (+2.37%) ⬆️
packages/wrangler/src/dev/start-server.ts 78.03% <ø> (ø)

... and 6 files with indirect coverage changes

@petebacondarwin petebacondarwin force-pushed the miniflare-upstream-host branch 6 times, most recently from 86029d3 to b3337e9 Compare December 20, 2023 14:44
Copy link
Contributor

@mrbbot mrbbot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! I've added some comments, but LGTM! 👍

@@ -33,15 +34,39 @@ function getUserRequest(
request: Request<unknown, IncomingRequestCfProperties>,
env: Env
) {
// The original URL is a header that is passed by Miniflare to the user worker
// in case the request was rewritten on its way to the user worker.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you update this comment to clarify that ORIGINAL_URL is also set when calling Miniflare#dispatchFetch(...) with the passed URL?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated the comment, but I am not 100% it is what you wanted.

CoreHeaders.PROXY_SHARED_SECRET
);
if (proxySharedSecret) {
if (proxySharedSecret === env[CoreBindings.TEXT_PROXY_SHARED_SECRET]) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unlikely to be a problem, but really this should be crypto.subtle.timingSafeEqual() to prevent timing attacks. This would require the shared secret to be an encoding of some uniformly distributed byte array (e.g. random hex string).

!crypto.subtle.timingSafeEqual(secretBuffer, expectedSecret)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to use this approach.

petebacondarwin and others added 5 commits January 3, 2024 11:23
…local mode

Some full-stack frameworks, such as Next.js, check that the Host header for a server
side action request matches the host where the application is expected to run.

In `wrangler dev` we have a Proxy Worker in between the browser and the actual User Worker.
This Proxy Worker is forwarding on the request from the browser, but then the actual User
Worker is running on a different host:port combination than that which the browser thinks
it should be on. This was causing the framework to think the request is malicious and blocking
it.

Now we update the request's Host header to that passed from the Proxy Worker in a custom `MF-Original-Url`
header, but only do this if the request also contains a shared secret between the Proxy Worker
and User Worker, which is passed via the `MF-Proxy-Shared-Secret` header. This last feature is to
prevent a malicious website from faking the Host header in a request directly to the User Worker.

Fixes cloudflare/next-on-pages#588
This helps to avoid an attacker guessing the secret via
the timing of the comparison.
@petebacondarwin petebacondarwin merged commit 037de5e into main Jan 3, 2024
19 checks passed
@petebacondarwin petebacondarwin deleted the miniflare-upstream-host branch January 3, 2024 12:28
@workers-devprod workers-devprod mentioned this pull request Jan 3, 2024
dario-piotrowicz added a commit to dario-piotrowicz/next-on-pages that referenced this pull request Jan 8, 2024
notes:
 - this is needed so that we can add e2e tests for server actions: cloudflare/workers-sdk#4630
 - we the commit also updates node from 18 to 20 in e2e github acitons testing, this is necessary for using the latest
wrangler release, see: cloudflare/workers-sdk#4563 (comment)
dario-piotrowicz added a commit to dario-piotrowicz/next-on-pages that referenced this pull request Jan 14, 2024
notes:
 - this is needed so that we can add e2e tests for server actions: cloudflare/workers-sdk#4630
 - we the commit also updates node from 18 to 20 in e2e github acitons testing, this is necessary for using the latest
wrangler release, see: cloudflare/workers-sdk#4563 (comment)
dario-piotrowicz added a commit to dario-piotrowicz/next-on-pages that referenced this pull request Jan 14, 2024
notes:
 - this is needed so that we can add e2e tests for server actions: cloudflare/workers-sdk#4630
 - we the commit also updates node from 18 to 20 in e2e github acitons testing, this is necessary for using the latest
wrangler release, see: cloudflare/workers-sdk#4563 (comment)
dario-piotrowicz added a commit to dario-piotrowicz/next-on-pages that referenced this pull request Jan 16, 2024
notes:
 - this is needed so that we can add e2e tests for server actions: cloudflare/workers-sdk#4630
 - we the commit also updates node from 18 to 20 in e2e github acitons testing, this is necessary for using the latest
wrangler release, see: cloudflare/workers-sdk#4563 (comment)
dario-piotrowicz added a commit to cloudflare/next-on-pages that referenced this pull request Jan 22, 2024
* add vitest.config.ts file with retry for better tests stability

* add new e2e features to test wasm

* avoid inconsistent kebab-case

* use latest wrangler release

notes:
 - this is needed so that we can add e2e tests for server actions: cloudflare/workers-sdk#4630
 - we the commit also updates node from 18 to 20 in e2e github acitons testing, this is necessary for using the latest
wrangler release, see: cloudflare/workers-sdk#4563 (comment)

* add app server-actions e2e test

* remove unnecessary existsSync assertion in processVercelOutput unit tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something that isn't working e2e Run e2e tests on a PR miniflare Relating to Miniflare wrangler Relating to the Wrangler CLI tool
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

🐛 BUG: --host flag not respected [🐛 Bug]: Server actions don't work with wrangler pages dev
3 participants