Skip to content

fix: implement URL normalization for Bun and Deno to prevent protocol-relative paths#8463

Merged
Varixo merged 1 commit into
mainfrom
bun-deno-prevent-origin-override
Mar 21, 2026
Merged

fix: implement URL normalization for Bun and Deno to prevent protocol-relative paths#8463
Varixo merged 1 commit into
mainfrom
bun-deno-prevent-origin-override

Conversation

@Varixo
Copy link
Copy Markdown
Member

@Varixo Varixo commented Mar 21, 2026

No description provided.

@Varixo Varixo self-assigned this Mar 21, 2026
@Varixo Varixo requested a review from a team as a code owner March 21, 2026 21:06
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Mar 21, 2026

🦋 Changeset detected

Latest commit: f96081f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 5 packages
Name Type
@builder.io/qwik-city Patch
eslint-plugin-qwik Patch
@builder.io/qwik Patch
create-qwik Patch
@builder.io/qwik-react Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@maiieul maiieul moved this from Backlog to Waiting For Review in Qwik Development Mar 21, 2026
@Varixo Varixo changed the title fix: implement URL normalization for Bun and Deno to prevent protocol… fix: implement URL normalization for Bun and Deno to prevent protocol-relative paths Mar 21, 2026
Copy link
Copy Markdown
Member

@thejackshelton thejackshelton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review: fix: implement URL normalization for Bun and Deno to prevent protocol-relative paths

Summary

This PR addresses a real security vulnerability — Bun and Deno middleware don't normalize URLs before constructing them with the configured origin, allowing protocol-relative URL attacks (e.g., //attacker.com being interpreted as https://attacker.com). The fix extracts the existing Node normalization logic into a shared normalizeRequestUrl() function and improves it with a two-step regex to handle the ///attacker.com edge case.

Critical Issue: Wrong Package Path

The PR modifies packages/qwik-city/ files, which don't exist on main (v2). The qwik-city package on main only contains a node_modules/ compatibility shim. The actual middleware code lives in packages/qwik-router/. This PR will not apply cleanly to the target branch.

The same vulnerability does exist in the v2 code at:

  • packages/qwik-router/src/middleware/bun/index.ts:25new URL(...) without normalization
  • packages/qwik-router/src/middleware/deno/index.ts:38 — same pattern

The fix needs to be rebased onto the current main branch structure with:

  • packages/qwik-city/packages/qwik-router/
  • @builder.io/qwik imports → @qwik.dev/core imports
  • Changeset: '@builder.io/qwik-city': patch'@qwik.dev/router': patch

Security Analysis: The Fix Itself

The two-step regex approach is an improvement over the original single-pass regex:

Original (single regex):

url.replace(/\/\/|\\\\/g, '/')

This fails on ///attacker.com → replaces first ////attacker.com still has a leading // (the global flag doesn't restart after replacement).

New (two-step):

url.replace(/^[\\/]{2,}/, '/').replace(/\/\/|\\\\/g, '/')

First strips all leading slashes/backslashes to one, then handles internal doubles. ///attacker.com/attacker.com → safe.

The approach correctly handles: //, \\\\, ///, \/, /\\, and arbitrary combinations of leading slashes/backslashes.

Minor Observations

  1. Regex allocation: Both LEADING_DOUBLE_SLASH_REG and DOUBLE_SLASH_REG are re-created on every call (declared inside the function). This is intentional for the /g regex (avoids lastIndex gotcha), but LEADING_DOUBLE_SLASH_REG doesn't use /g and could be a module-level constant. Very minor — not a blocker.

  2. Test coverage is good: Tests cover //, \\\\, internal //, and /// with query/hash. Consider also testing \/ (mixed slash-backslash) if being thorough.

  3. Other adapters are fine: Cloudflare, Netlify Edge, Vercel Edge, etc. don't have origin override functionality — they use new URL(request.url) directly, so they're not affected.

Verdict

The security fix is correct and the approach is sound. However, the PR needs to be rebased onto the current v2 codebase (packages/qwik-router/ with @qwik.dev/* imports) before it can be merged into main.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Mar 21, 2026

Open in StackBlitz

npm i https://pkg.pr.new/@builder.io/qwik@8463
npm i https://pkg.pr.new/@builder.io/qwik-city@8463
npm i https://pkg.pr.new/eslint-plugin-qwik@8463
npm i https://pkg.pr.new/create-qwik@8463

commit: b71ca14

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 21, 2026

built with Refined Cloudflare Pages Action

⚡ Cloudflare Pages Deployment

Name Status Preview Last Commit
qwik-docs ✅ Ready (View Log) Visit Preview b71ca14

@Varixo Varixo force-pushed the bun-deno-prevent-origin-override branch from b71ca14 to f96081f Compare March 21, 2026 21:27
@Varixo Varixo merged commit 15c5ad7 into main Mar 21, 2026
8 checks passed
@Varixo Varixo deleted the bun-deno-prevent-origin-override branch March 21, 2026 21:27
@github-project-automation github-project-automation Bot moved this from Waiting For Review to Done in Qwik Development Mar 21, 2026
@github-actions github-actions Bot mentioned this pull request May 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

3 participants