Skip to content

fix(security): close CodeQL alert #11 (incomplete URL substring sanitization in sample mock-fetch)#100

Merged
voyvodka merged 1 commit into
mainfrom
fix/codeql-and-release-format
May 11, 2026
Merged

fix(security): close CodeQL alert #11 (incomplete URL substring sanitization in sample mock-fetch)#100
voyvodka merged 1 commit into
mainfrom
fix/codeql-and-release-format

Conversation

@voyvodka
Copy link
Copy Markdown
Owner

Summary

Closes CodeQL alert #11 (HIGH severity, js/incomplete-url-substring-sanitization) on samples/portal-host/src/mock-fetch.ts:117.

The previous shape:

if (!url.startsWith(BASE)) return originalFetch(input, init);

with BASE = "https://hooks.example.com". The startsWith check correctly catches paths like https://hooks.example.com/api/v1/portal/endpoints, but it ALSO matches https://hooks.example.com.attacker.com/api/v1/portal/endpoints — the BASE prefix can be followed by an arbitrary host suffix. Fine for the sample's mock semantics in isolation (the worst case is the mock answers a request that should have gone to the real network), but the kind of pattern that absolutely should not get copy-pasted into production code.

Fix

Parse the URL and compare protocol + host explicitly via WHATWG URL:

const BASE_URL = new URL(BASE);
// ...
let parsed: URL;
try {
  parsed = new URL(url);
} catch {
  return originalFetch(input, init);
}
if (parsed.protocol !== BASE_URL.protocol || parsed.host !== BASE_URL.host) {
  return originalFetch(input, init);
}

Same intent, no substring trap. Also flipped path = url.slice(BASE.length).split("?")[0]path = parsed.pathname which is the same value via a safer route. Route handlers downstream are unchanged.

Test plan

…le mock-fetch

CodeQL alert #11 (HIGH severity, js/incomplete-url-substring-sanitization) on samples/portal-host/src/mock-fetch.ts:117. The previous shape was:

  if (!url.startsWith(BASE)) return originalFetch(input, init);

with BASE = 'https://hooks.example.com'. The startsWith check correctly catches paths like https://hooks.example.com/api/v1/portal/endpoints, but it ALSO matches https://hooks.example.com.attacker.com/api/v1/portal/endpoints — the BASE prefix can be followed by an arbitrary host suffix. This is fine for the sample's mock semantics in isolation (the worst case is the mock answers a request that should have gone to the real network), but the kind of pattern that absolutely should not get copy-pasted into production code.

Fixed by parsing the URL and comparing protocol + host explicitly via WHATWG URL. Same intent, no substring trap. Also flipped path = url.slice(BASE.length).split('?')[0] to path = parsed.pathname which is the same value via a safer route. The route handlers downstream are unchanged.

Closes the CodeQL alert. No test changes required — the mock continues to serve the same routes for the same inputs the sample emits.
@voyvodka voyvodka added security Security-related issues bug Something is not working npm npm / Bun dependencies labels May 11, 2026
@voyvodka voyvodka merged commit da2674a into main May 11, 2026
5 checks passed
@voyvodka voyvodka deleted the fix/codeql-and-release-format branch May 11, 2026 06:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something is not working npm npm / Bun dependencies security Security-related issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant