Repository navigation
Commit ea45912
fix(config): reject protocol-relative rewrite/fallback destinations in schema (#225)
Editors now flag a protocol-relative
`routing.rewrites`/`routing.fallbacks` destination (e.g. `//evil.com/x`)
instead of silently accepting a config the build hard-rejects — closing
a cross-origin-proxy footgun at author time.
## The bug
The editor JSON schema validated rewrite/fallback destination values
with `^/[^?]*$` — "starts with `/`, no `?`". That permits a *second*
leading slash, so `"//evil.com/x"` matched. The runtime rejects it
(`assertNotProtocolRelative` in `config.ts`, called at the Rewrite and
Fallback sites) because `new URL("//host/x", base)` resolves to
`https://host/x`, silently turning an internal rewrite into a
cross-origin proxy. So an editor using `$schema` showed no warning for a
destination the build rejects.
## Expected-correct behavior
The schema should match the runtime: a rewrite/fallback destination must
start with a single `/` (internal path only), not `//`.
## The fix
Forbid the second leading slash in both dest patterns: `^/[^?]*$` →
`^/(?!/)[^?]*$`. Verified byte-for-byte equivalent to the runtime
predicate across the destination space (including correctly rejecting
external `https://` dests, which rewrites/fallbacks don't allow).
## Scope note
This is the only place the `^/[^?]*$` pattern appeared (rewrites +
fallbacks share it). `routing.redirects` is intentionally **not**
changed: its destination legitimately allows external `https://` URLs,
so it uses a different (looser) schema shape and never carried this
pattern; its `//` protection stays in the runtime (already tested).
## Tests
Added a parity test in `config.test.ts` (same style as the existing
`sourceDir` / `redirect-status-enum` parity tests): asserts the dest
pattern accepts `/en/docs`, `/`, `/index.html` and rejects
`//evil.com/x`, `//`, `///x`, `/x?a=1`, `en/docs` — failing on
`origin/main` and passing after. The runtime `//` rejection is itself
already covered (config.test.ts). Local gate: `config.test.ts` 159/159;
full `--project unit` zero-collateral; schema.json valid JSON; typecheck
+ lint + fmt clean. No existing `void.json` / doc example uses a
now-rejected destination.
Prepared with AI assistance.
Co-authored-by: LongYinan <lynweklm@gmail.com>1 parent 0287ae9 commit ea45912
2 files changed
Lines changed: 18 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
216 | 216 | | |
217 | 217 | | |
218 | 218 | | |
219 | | - | |
| 219 | + | |
220 | 220 | | |
221 | 221 | | |
222 | 222 | | |
223 | 223 | | |
224 | 224 | | |
225 | 225 | | |
226 | 226 | | |
227 | | - | |
| 227 | + | |
228 | 228 | | |
229 | 229 | | |
230 | 230 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
653 | 653 | | |
654 | 654 | | |
655 | 655 | | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
656 | 672 | | |
657 | 673 | | |
658 | 674 | | |
| |||
0 commit comments