Summary
The faucet and Index Supply API routes currently detect Vercel preview origins with substring matching:
src/pages/_api/api/faucet.ts
src/pages/_api/api/index-supply.ts
For example, an origin such as:
https://preview.vercel.app.attacker.example
contains vercel.app and may be reflected through Access-Control-Allow-Origin.
This does not appear to enable account compromise, but it weakens the CORS boundary and can allow unintended origins to invoke or read public API responses.
Existing behavior
The recent CORS fix in #612 improved exact allow-list matching, but preview-origin validation still uses origin.includes('vercel.app').
The feedback endpoint already uses URL parsing and hostname validation.
Proposed fix
Validate the origin with new URL(origin) and require:
https: protocol
- hostname ending with
.vercel.app
- existing Tempo and local-development origins remain unchanged
The scope can start with the faucet route if both API routes should not be changed together.
Regression coverage
Tests should:
- allow a valid Vercel preview origin
- reject
https://preview.vercel.app.attacker.example
- reject non-HTTPS preview origins
- preserve existing Tempo and development behavior
I would be happy to prepare a small PR after confirming whether this should cover both routes or start with the faucet route only.
Summary
The faucet and Index Supply API routes currently detect Vercel preview origins with substring matching:
src/pages/_api/api/faucet.tssrc/pages/_api/api/index-supply.tsFor example, an origin such as:
https://preview.vercel.app.attacker.examplecontains
vercel.appand may be reflected throughAccess-Control-Allow-Origin.This does not appear to enable account compromise, but it weakens the CORS boundary and can allow unintended origins to invoke or read public API responses.
Existing behavior
The recent CORS fix in #612 improved exact allow-list matching, but preview-origin validation still uses
origin.includes('vercel.app').The feedback endpoint already uses URL parsing and hostname validation.
Proposed fix
Validate the origin with
new URL(origin)and require:https:protocol.vercel.appThe scope can start with the faucet route if both API routes should not be changed together.
Regression coverage
Tests should:
https://preview.vercel.app.attacker.exampleI would be happy to prepare a small PR after confirming whether this should cover both routes or start with the faucet route only.