fix: allow vercel preview builds to access the local connector#1794
fix: allow vercel preview builds to access the local connector#1794neutrino2211 wants to merge 1 commit intonpmx-dev:mainfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
2 Skipped Deployments
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
📝 WalkthroughWalkthroughThe pull request extends the CORS origin allowlist in the CLI server configuration to include a regex pattern permitting any Vercel app domain matching Possibly related issues
🚥 Pre-merge checks | ✅ 1✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
| 'https://npmx.dev', | ||
| /^http:\/\/localhost:\d+$/, | ||
| /^http:\/\/127.0.0.1:\d+$/, | ||
| /^https:\/\/(.*)\.vercel\.app$/, |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
head -120 cli/src/server.ts | tail -40Repository: npmx-dev/npmx.dev
Length of output: 1044
🏁 Script executed:
find . -name "vercel.json" -o -name ".vercelignore" | head -5Repository: npmx-dev/npmx.dev
Length of output: 74
🏁 Script executed:
grep -n "vercel" package.json | head -10Repository: npmx-dev/npmx.dev
Length of output: 43
🌐 Web query:
Vercel preview deployment URL pattern subdomain structure and how to scope CORS to specific projects or teams
💡 Result:
Vercel preview deployment URL patterns (default .vercel.app)
Vercel “generated URLs” are built from these components: <project-name>, <scope-slug> (team/account slug), optional <branch-name>, and optional <unique-hash>. (vercel.com)
Common preview URL structures from Git: (vercel.com)
- Commit-specific preview (changes for one commit):
https://<project-name>-<unique-hash>-<scope-slug>.vercel.app - Branch preview (always latest for that branch):
https://<project-name>-git-<branch-name>-<scope-slug>.vercel.app
(There are also CLI-generated forms like https://<project-name>-<scope-slug>.vercel.app and sometimes ...-<author-name>-... for team deployments.) (vercel.com)
Making preview URLs predictable (best for CORS allowlists)
If you need a stable domain pattern, use Preview Deployment Suffix to replace .vercel.app with a domain you control (configured at the team level, and the domain must exist/be active in that team). (vercel.com)
Example outcome: previews become something like https://<project>...<team>.<your-preview-suffix-domain> instead of ...vercel.app. (vercel.com)
If you want wildcard-style origins (e.g. https://*.preview.example.com), you typically pair this with Vercel-managed DNS / wildcard domain handling so subdomains resolve cleanly. (vercel.com)
How to scope CORS to specific Vercel projects/teams
CORS itself doesn’t understand “Vercel project/team”—it only sees the request Origin (scheme + host + port). So you scope by matching the Origin host to the project/team patterns you allow.
Option A (works with default .vercel.app): validate origin by suffix + project prefix
Use a dynamic origin check on your API:
- Require host ends with:
-<scope-slug>.vercel.app(scopes to one team/account) - Also require host starts with:
<project-name>-(scopes to one project) - Optionally allow only the
-git-(branch) form and/or the-<unique-hash>-(commit) form. (vercel.com)
Example (Node/Next API-style logic):
const allowedScope = "my-team-slug";
const allowedProject = "my-project";
function isAllowedVercelPreviewOrigin(origin) {
try {
const { protocol, hostname } = new URL(origin);
if (protocol !== "https:") return false;
// team/account scope
if (!hostname.endsWith(`-${allowedScope}.vercel.app`)) return false;
// project scope
if (!hostname.startsWith(`${allowedProject}-`)) return false;
// optional: ensure it matches either branch or commit style
const ok =
hostname.includes(`-git-`) || /-[0-9a-z]{9}-/.test(hostname); // "unique-hash" is 9 chars
return ok;
} catch {
return false;
}
}(That 9-character “unique-hash” length is documented.) (vercel.com)
Option B (recommended for strict allowlists): use a custom Preview Deployment Suffix domain per team
With a suffix like preview.example.com, you can allow:
https://*.preview.example.com(broad to that team’s preview domain), orhttps://<project-pattern>.preview.example.com(narrower), depending on how your generated hostnames look after the suffix change. (vercel.com)
Option C: if Deployment Protection breaks CORS preflights
If your previews are protected (Vercel Authentication / Password / Trusted IPs), browser OPTIONS preflights can be blocked. Vercel documents using OPTIONS Allowlist so preflights can succeed (commonly for /api/*) while keeping real requests protected. (vercel.com)
If you tell me your team slug, project name, and whether you’re using default .vercel.app vs Preview Deployment Suffix, I can give you an exact regex/implementation (and for which environments: preview only vs preview+prod).
Citations:
- 1: https://vercel.com/docs/concepts/deployments/generated-urls?utm_source=openai
- 2: https://vercel.com/docs/concepts/deployments/generated-urls?utm_source=openai
- 3: https://vercel.com/docs/concepts/deployments/generated-urls?utm_source=openai
- 4: https://vercel.com/docs/deployments/preview-deployment-suffix?utm_source=openai
- 5: https://vercel.com/docs/deployments/preview-deployment-suffix?utm_source=openai
- 6: https://vercel.com/platforms/docs/multi-tenant-platforms/configuring-domains?utm_source=openai
- 7: https://vercel.com/docs/concepts/deployments/generated-urls?utm_source=openai
- 8: https://vercel.com/docs/concepts/deployments/generated-urls?utm_source=openai
- 9: https://vercel.com/docs/deployments/preview-deployment-suffix?utm_source=openai
- 10: https://vercel.com/guides/how-to-enable-cors?utm_source=openai
🏁 Script executed:
cat vercel.json | jq . 2>/dev/null || cat vercel.jsonRepository: npmx-dev/npmx.dev
Length of output: 2099
🏁 Script executed:
rg -i "team|scope|slug" --type json --type ts -C 2 | head -30Repository: npmx-dev/npmx.dev
Length of output: 1796
Scope the Vercel CORS origin pattern to your team's deployments.
The regex /^https:\/\/(.*)\.vercel\.app$/ allows CORS requests from any Vercel deployment (across all users and teams). Whilst token validation provides secondary protection, CORS should still follow the defence-in-depth principle.
Vercel preview URLs include the team/account scope slug. Scope your pattern to match your deployments only:
/^https:\/\/npmx-dev-.*-<your-team-slug>\.vercel\.app$/
Replace <your-team-slug> with your Vercel team's slug (visible in your team settings or Vercel preview URLs). This ensures only your team's deployments can request CORS access, not arbitrary Vercel apps from other users or organisations.
|
I deliberately did not do this as it allows any person to create a spoof of npmx that can access the connector (in other words, we might as well not even have CORS origins). having a reviewer run the preview build locally is an acceptable tradeoff for the better security. |
|
Okay, that makes sense. Should have waited for clarification before opening PR, my apologies. |
🔗 Linked issue
#1793
🧭 Context
The CLI connector uses CORS headers to secure access to it, the headers however do not allow access from vercel preview deployments.
📚 Description
This PR adds the following regex to allowed origins
Regex itself might need some work 😬