Skip to content

feat: add allowedOrigins option - #5770

Merged
alexander-akait merged 13 commits into
mainfrom
fix/allowed-origins
Oct 20, 2026
Merged

alexander-akait merged 13 commits into
mainfrom
fix/allowed-origins

Conversation

@bjohansebas

@bjohansebas bjohansebas commented Oct 17, 2026 •

Copy link
Copy Markdown
Member

Add devServer.allowedOrigins to say which pages may use the dev server: its HTTP endpoints, hot module replacement (WebSocket or Server-Sent Events), proxied WebSockets and the internal endpoints. It is separate from allowedHosts, which checks the Host header (DNS rebinding).

Non-breaking. Nothing changes until the option is set.

  • "auto" (default): the rules derived from allowedHosts, exactly as before. main's own security tests (allowed-hosts, cross-origin-request, event-source, options-middleware, proxy-web-socket-origin, web-socket-server-url, proxy-option) are left unchanged and pass. Under "auto", two settings still open every origin, as they always have: allowedHosts: "all", and an Access-Control-Allow-Origin: * entry in headers (which turns off Cross-Origin-Resource-Policy). Both now print a deprecation warning.
  • A list: the page's own hostname (any port, with loopback names counted as one, as before) plus the listed origins, whatever allowedHosts says.
    • Listed origins get Access-Control-Allow-Origin, Access-Control-Allow-Credentials and Vary: Origin, and their preflight requests get the method, headers and Private Network Access they ask for.
    • A plain <script> or <img> without crossorigin is allowed by the page's Referer, and gets Cross-Origin-Resource-Policy: cross-origin.
    • A cross-site no-cors load from any other page, and a request with any other Origin, gets 403.
  • "all": every origin, with Access-Control-Allow-Origin: *; the Host check stays on.

One internal rule now serves ordinary requests, proxied WebSocket upgrades, hot clients and the open-editor/invalidate endpoints.

Hot token (as in Vite). Once allowedOrigins is set, the injected client is handed a per-run token. A hot client that carries it may connect from an origin the server does not otherwise know, such as a proxy's or a tunnel's. It never replaces the Host check. This uses hot.token: { required: false } from webpack-dev-middleware 8.5.0 (webpack/webpack-dev-middleware#2486), which is now the minimum (^8.5.0). Under "auto" there is no token, so the socket URL and who it lets in are exactly as before. A TODO makes it unconditional in the next major.

static.deny. Off by default.

  • true refuses .env, .env.*, *.{crt,pem,key,p12,pfx,cer,der}, .npmrc, .yarnrc.yml and .git in a static directory with 403, and leaves them out of directory listings.
  • A list of patterns (*, ?, {a,b}) refuses those instead.
  • Matching is per path segment and case-insensitive, after decoding. On Windows it also catches : (alternate data streams) and trailing dots and spaces.

Next major (TODOs in code).

  • Drop "auto" and default allowedOrigins to [].
  • allowedHosts and headers stop granting origins, and the deprecations and legacy checks are removed.
  • client.webSocketURL.hostname stops being an allowed host.
  • static.deny defaults to true.

Docs: a README "Security" section (allowedOrigins, static.deny), the rewritten examples/allowed-origins, and a minor changeset.

Tests:

  • New: test/server/allowed-origins.test.js, test/server/allowed-origins-deprecation.test.js, test/e2e/allowed-origins.test.js (HTTP, HMR, endpoints, a real browser loading a plain script from a listed and an unlisted page, the token), test/e2e/static-deny.test.js.
  • Updated: validation and CLI cases and snapshots.
  • Full suite, compared with main in the same sandbox: no new failures; the remaining 51 are the same set as main (IPv6, proxy 403, a non-local IP).

https://claude.ai/code/session_01UjuMAuk9o6UazjHzcAQCTA


Generated by Claude Code

Summary by CodeRabbit

  • New Features
    • Added allowedOrigins settings to control website access, including existing host rules, specified origins, or all origins while retaining Host checks.
    • Added static.deny to block sensitive files with 403 responses, exclude them from directory listings, and support custom patterns.
  • Documentation
    • Added configuration guidance, CLI options, security details, and examples for origin access and static-file protection.
  • Bug Fixes
    • Improved cross-origin requests and hot-reload connections for permitted origins.

@changeset-bot

changeset-bot Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: e610267

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

This PR includes changesets to release 1 package
Name Type
webpack-dev-server Minor

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

@coderabbitai

coderabbitai Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 46fa2dd4-a55f-4f08-8660-8e29c6841828
📥 Commits

Reviewing files that changed from the base of the PR and between 3d3355d and e610267.

⛔ Files ignored due to path filters: 1
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing: 2
  • lib/Server.js
  • test/ports-map.js

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review.

Walkthrough

The server adds allowedOrigins, defaulting to "auto", and applies origin checks to requests, endpoints, hot clients, and proxied WebSocket upgrades. Explicit origin settings add CORS and resource-policy handling, while a middleware token can authorize injected hot clients. Static options add deny patterns that return 403 for matching GET and HEAD requests and omit denied names from directory listings. The change also adds option validation, CLI support, tests, documentation, and an example, and updates the webpack-dev-middleware version range.

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to e6102

The new allowedOrigins option keeps the default behavior unchanged and applies its permissive "all" mode only on explicit opt-in, as documented. No outstanding defects were found in this change, and it appears ready to merge.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 28 functions across 24 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely identifies the primary change: adding the allowedOrigins option.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Some tools did not complete. Review the errors below.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed: one or more packages not found in the registry.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: a770a2e0-d86a-4f33-90f4-0fa076fe7c75
📥 Commits

Reviewing files that changed from the base of the PR and between 9915359 and 390f797.

📒 Files selected for processing: 27
  • .changeset/independent-origin-authorization.md
  • README.md
  • examples/allowed-origins/README.md
  • examples/allowed-origins/app.js
  • examples/allowed-origins/webpack.config.js
  • lib/Server.js
  • lib/options.check.js
  • lib/options.json
  • test/__snapshots__/normalize-options.test.js.snap.webpack5
  • test/__snapshots__/validate-options.test.js.snap.webpack5
  • test/cli/__snapshots__/basic.test.js.snap.webpack5
  • test/cli/allowedOrigins-option.test.js
  • test/e2e/__snapshots__/allowed-hosts.test.js.snap.webpack5
  • test/e2e/allowed-hosts.test.js
  • test/e2e/allowed-origins.test.js
  • test/e2e/cross-origin-request.test.js
  • test/e2e/event-source.test.js
  • test/e2e/options-middleware.test.js
  • test/e2e/proxy-web-socket-origin.test.js
  • test/e2e/web-socket-server-url.test.js
  • test/normalize-options.test.js
  • test/ports-map.js
  • test/schema-check.test.js
  • test/server/allowed-origins.test.js
  • test/server/proxy-option.test.js
  • test/validate-options.test.js
  • types/lib/Server.d.ts

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review.

Comment thread lib/Server.js Outdated
Comment thread lib/Server.js Outdated
@codecov

codecov Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.79%. Comparing base (1bf456a) to head (e610267).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5770      +/-   ##
==========================================
+ Coverage   95.36%   95.79%   +0.42%     
==========================================
  Files           6        6              
  Lines        5029     5539     +510     
==========================================
+ Hits         4796     5306     +510     
  Misses        233      233              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 35fd4aa8-3b41-48b8-9409-38c2ebfee855
📥 Commits

Reviewing files that changed from the base of the PR and between c6467d1 and a13c785.

📒 Files selected for processing: 20
  • .changeset/independent-origin-authorization.md
  • .cspell.json
  • README.md
  • examples/allowed-origins/README.md
  • examples/allowed-origins/webpack.config.js
  • lib/Server.js
  • lib/hotOptions.js
  • lib/options.check.js
  • lib/options.json
  • test/__snapshots__/normalize-options.test.js.snap.webpack5
  • test/__snapshots__/validate-options.test.js.snap.webpack5
  • test/cli/__snapshots__/basic.test.js.snap.webpack5
  • test/e2e/allowed-origins.test.js
  • test/e2e/static-deny.test.js
  • test/hot-options.test.js
  • test/ports-map.js
  • test/server/allowed-origins-deprecation.test.js
  • test/server/allowed-origins.test.js
  • test/validate-options.test.js
  • types/lib/Server.d.ts
🚧 Files skipped from review as they are similar to previous changes: 2
  • .changeset/independent-origin-authorization.md
  • test/cli/snapshots/basic.test.js.snap.webpack5

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review.

Comment thread examples/allowed-origins/README.md Outdated
Comment thread README.md Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 39a7947f-74d3-4927-a3f1-0bce7d63078a
📥 Commits

Reviewing files that changed from the base of the PR and between cfaa21c and 0396299.

📒 Files selected for processing: 4
  • README.md
  • examples/allowed-origins/README.md
  • lib/Server.js
  • test/e2e/allowed-origins.test.js
🚧 Files skipped from review as they are similar to previous changes: 1
  • examples/allowed-origins/README.md

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 6 remain after this review.

Comment thread lib/Server.js Outdated

Copy link
Copy Markdown
Member

@coderabbitai review


Generated by Claude Code

@coderabbitai

coderabbitai Bot commented Oct 18, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@socket-security

socket-security Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedwebpack-dev-middleware@​8.4.0 ⏵ 8.5.099 +110010097 +5100

View full report

Copy link
Copy Markdown
Member

@coderabbitai review


Generated by Claude Code

@coderabbitai

coderabbitai Bot commented Oct 18, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

bjohansebas and others added 13 commits October 20, 2026 09:30
…t the hot token

`allowedOrigins: "auto"` (the default) now keeps the origin rules derived
from `allowedHosts` exactly, so nothing changes until the option is set;
`allowedHosts: "all"` and an `Access-Control-Allow-Origin: *` header still
open every origin under it, with a deprecation warning. A list allows the
page's own hostname plus the listed origins, answers them with CORS
headers and allows a plain script they load by its `Referer`; "all" allows
every origin and keeps the `Host` check. One rule now serves ordinary
requests, proxied WebSocket upgrades, hot clients and the internal
endpoints.

The injected hot client is handed a per-run token the endpoint does not
require (webpack-dev-middleware#2486), and a client carrying it may connect
from an origin the server does not know; skipped with an older middleware.

`static.deny` refuses secrets (`.env*`, keys and certificates, `.npmrc`,
`.yarnrc.yml`, `.git`) or patterns of your own in a static directory, and
hides them from listings; off by default until the next major.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UjuMAuk9o6UazjHzcAQCTA
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UjuMAuk9o6UazjHzcAQCTA
With allowedOrigins set, a listed origin gets Access-Control-Allow-Credentials,
and an allowed origin's preflight gets the method, headers and Private
Network Access it asks for, so a fetch with custom headers, another method
or cookies works from it. "auto" is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UjuMAuk9o6UazjHzcAQCTA
…a Host

The hot-token tests now give the middleware a token when it has none, so
this server's own check runs on any webpack-dev-middleware rather than
being skipped; the optional-token detection takes a schema and is tested
on its own. static.deny gets the `?` glob, an undecodable path and the
Windows rules. The allowedOrigins entry check the schema already makes is
gone, and the token is read off the query without a try that cannot fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UjuMAuk9o6UazjHzcAQCTA
A list also allows the page's own hostname on any port, and cookies do not
tell ports apart, so Access-Control-Allow-Credentials went to any other
local page with it. It now goes only to an origin listed by name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UjuMAuk9o6UazjHzcAQCTA
…th allowedOrigins

8.5.0 takes `hot.token: { required: false }` (webpack/webpack-dev-middleware#2486),
so the check for it, the tests' stand-in token and the README notes on older
versions go, as their TODOs said. The token is handed to the injected client
only once `allowedOrigins` is set: under "auto" the socket's url and who it
lets in stay exactly as before, with a TODO to always hand it over in the
next major release.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UjuMAuk9o6UazjHzcAQCTA

Copy link
Copy Markdown
Member

@coderabbitai review


Generated by Claude Code

@coderabbitai

coderabbitai Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Member

Test - windows-latest - Node v22.x failed on e610267 in one test, history-api-fallback.test.js › "should handle GET request to directory": Puppeteer's page.goto(..., { waitUntil: "networkidle0" }) hit its 120 s navigation timeout (the test ran 225 s). It isn't this PR's as far as I can tell: the test uses the default options, where allowedOrigins is "auto" and no static.deny is set, so every code path it touches is main's; the same test passed on this commit on Windows Node 24 and 26, on main's Windows Node 22 job (1bf456a), on this PR's previous head, and 3/3 locally. No fix to port. Re-running the failed jobs once; a second failure gets treated as real.


Generated by Claude Code

@alexander-akait
alexander-akait merged commit f62b534 into main Oct 20, 2026
24 of 28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants