mirror of
https://github.com/cloudflare/vinext.git
synced 2026-05-09 08:25:34 +02:00
[PR #106] [MERGED] fix: close security gaps in init.ts shell exec and app-dev-server external proxy #313
Labels
No labels
enhancement
enhancement
good first issue
help wanted
nextjs-tracking
nextjs-tracking
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/vinext#313
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/cloudflare/vinext/pull/106
Author: @threepointone
Created: 2/26/2026
Status: ✅ Merged
Merged: 2/26/2026
Merged by: @threepointone
Base:
main← Head:fix/security-gaps-1-2📝 Commits (3)
c6d10c1fix: close security gaps in init.ts shell exec and app-dev-server external proxy4da89c5fix: unify isExternalUrl to detect all URL schemes and protocol-relative URLs858f165fix: add shell: true to execFileSync for Windows .cmd file compat📊 Changes
10 files changed (+4259 additions, -17 deletions)
View changed files
📝
packages/vinext/src/config/config-matchers.ts(+4 -3)📝
packages/vinext/src/init.ts(+3 -2)📝
packages/vinext/src/server/app-dev-server.ts(+15 -3)📝
packages/vinext/src/server/dev-server.ts(+4 -3)📝
packages/vinext/src/shims/navigation.ts(+2 -2)📝
packages/vinext/src/shims/router.ts(+2 -2)📝
tests/app-router.test.ts(+63 -0)📝
tests/fixtures/app-basic/next.config.ts(+5 -0)➕
tests/fixtures/pages-basic/dist/server/entry.js(+4140 -0)📝
tests/shims.test.ts(+21 -2)📄 Description
Summary
Closes two remaining security gaps identified during the vulnerability audit, fixes a missed backslash normalization path, and unifies
isExternalUrlacross all copies.Gap 1 — GHSA-w7vc-6jjg-498h (shell injection in init.ts)
init.ts:224usedexecSyncwith string concatenation. All inputs are hardcoded package names so practical risk is near zero, butdeploy.tsandcli.tswere already migrated toexecFileSync—init.tswas missed.Fix:
execSync→execFileSyncwithcmd.split(" ")argument array. The_exectest callback interface is unchanged.Gap 2 — GHSA-pf96-3m7r-pv3j (credential leak on external proxy)
app-dev-server.ts:1118-1137has an inline__proxyExternalRequestin the generated RSC entry that forwarded Cookie, Authorization, and x-api-key headers to external rewrite targets. The fixed version inconfig-matchers.tsstrips all of these plus adds a 30s timeout — the dev-server copy was not updated.Fix: Strip
cookie,authorization,x-api-key,proxy-authorization, and allx-middleware-*headers. Add 30-secondAbortSignal.timeout. Matches the hardenedproxyExternalRequestinconfig-matchers.ts.Bonus — GHSA-79rw-r8hc-qg8v (backslash bypass, missed GSP path)
The GSSP redirect path in
dev-server.tswas already fixed in PR #105, but the GSP redirect path (line ~520) was missed. Now both paths normalize backslashes.isExternalUrl unification (defense-in-depth)
Four copies of
isExternalUrlexisted with inconsistent checks:config-matchers.tsandapp-dev-server.tsonly checkedhttp://andhttps://(missing//)router.tsandnavigation.tscheckedhttp://,https://, and//but missed exotic schemesAll four now use the same RFC 3986 scheme regex:
This detects
data:,javascript:,blob:,ftp:, and any valid URL scheme, plus protocol-relative URLs.Tests
isExternalUrltests expanded: exotic schemes, protocol-relative, hash-only, bare stringsFiles changed
init.tsexecSync→execFileSyncapp-dev-server.ts__isExternalUrlunifieddev-server.tsconfig-matchers.tsisExternalUrl: add//+ exotic scheme detectionrouter.tsisExternalUrl: RFC 3986 regexnavigation.tsisExternalUrl: RFC 3986 regexapp-router.test.tsnext.config.ts(fixture)shims.test.tsisExternalUrlexotic scheme + protocol-relative testsdist/server/entry.js(fixture)All 1981 tests pass.
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.