Skip to content

Restrict the public CORS proxy to allowlisted calling sites - #118

Merged
jonocodes merged 1 commit into
mainfrom
feature/proxy-origin-allowlist
Oct 16, 2026
Merged

jonocodes merged 1 commit into
mainfrom
feature/proxy-origin-allowlist

Conversation

@jonocodes

Copy link
Copy Markdown
Owner

Summary

Stops other websites from spending the shared proxy's free-tier quota through their visitors' browsers.

  • New optional ALLOWED_ORIGINS setting in the proxy core: comma-separated origins, * within a host label (never crosses a .), :* for any port.
  • Missing / null / unlisted Origin → the same 404 as a bad token, checked before the edge cache and any upstream fetch. Refusals are recorded in the stats (404 / bypass / no host).
  • Allowed responses echo the caller's origin in Access-Control-Allow-Origin with Vary: Origin. OPTIONS and /health stay open. Composes with PROXY_TOKENS.
  • Restricts callers only — any public article host can still be fetched.
  • Public instance ([env.public.vars]): https://savr.link,https://*--savrlist.netlify.app,http://localhost:*,http://127.0.0.1:*. Unset (every self-hosted proxy) = unchanged behaviour.
  • ADR 0006, README / cors-worker README / env-var / telemetry / stats docs, CHANGELOG.

Caveats

Deploy

Takes effect after npx wrangler deploy --env public from infra/cors-worker.

Test plan

  • node --test "infra/cors-worker/*.test.mjs" "infra/cors-stats/*.test.mjs" — 61 pass (9 new: allowed origins incl. previews/localhost, refusals incl. dot-crossing and wrong scheme/port, targets unrestricted, cache ordering, token composition, unset = open, stats recording, pattern parsing)
  • After deploy: save an article on savr.link and a Netlify preview; curl without Origin gets 404

🤖 Generated with Claude Code

Add an optional ALLOWED_ORIGINS setting to the proxy core. When set, a
request whose Origin is missing, null or unlisted gets the same 404 as a
bad token, checked before the edge cache and any upstream fetch; allowed
responses echo the caller's origin with Vary: Origin. Targets are never
restricted. Refusals are recorded in the stats.

The public instance allows savr.link, Netlify preview/branch deploys and
localhost. Unset (every self-hosted proxy) behaves as before.

Rate limiting is tracked separately in #117. See ADR 0006.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@netlify

netlify Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for savrlist ready!

Name Link
🔨 Latest commit e44feb6
🔍 Latest deploy log https://app.netlify.com/projects/savrlist/deploys/6ad170195f392aef360903c0
😎 Deploy Preview https://deploy-preview-118--savrlist.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@jonocodes
jonocodes merged commit bba4f8e into main Oct 16, 2026
6 checks passed
jonocodes added a commit that referenced this pull request Oct 16, 2026
The public proxy now refuses unlisted calling sites (#118). The probe must
still read as "running" there: an allowed caller gets the CORS 400, a
refused one a 404 that still carries CORS headers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

1 participant