fix(security): validate service URLs with URL constructor (CodeQL #196) - #867
Conversation
Replace regex URL validation with new URL() constructor + strict http:/https: protocol allowlist in chrome-extension options.js. Apply same validation to fetch() calls at test-individual and test-all buttons (CodeRabbit follow-up). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis change adds URL validation to the Chrome extension's options page. A new Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (2 warnings)
✅ 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 |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
pmoves/chrome-extension/options/options.js (2)
274-284: Correct security fix, but consider reusingvalidateServiceUrl.The inline validation correctly prevents XSS by only assigning
hreffor http/https URLs. However, this duplicates the logic fromvalidateServiceUrl().Two suggestions:
- Refactor to reuse the helper (the trailing slash difference is negligible for full URLs):
♻️ Suggested refactor
- // Validate URL via constructor to prevent XSS (CodeQL `#194`, `#196`) - try { - const parsed = new URL(vizUrl); - if (parsed.protocol === 'http:' || parsed.protocol === 'https:') { - link.href = parsed.href; - } - } catch { /* invalid URL — skip href assignment */ } + // Validate URL via constructor to prevent XSS (CodeQL `#194`, `#196`) + const validatedVizUrl = validateServiceUrl(vizUrl); + if (validatedVizUrl) { + link.href = validatedVizUrl; + }
- UX improvement: When the URL is invalid, the "View SVG" link renders but clicking it does nothing. Consider hiding or styling the link differently when
hrefis not set.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pmoves/chrome-extension/options/options.js` around lines 274 - 284, Refactor the inline URL validation to reuse the existing validateServiceUrl(vizUrl) helper instead of duplicating constructor/protocol checks: call validateServiceUrl(vizUrl) to determine validity and, if valid, set link.href = normalizedUrl (or vizUrl as returned); otherwise do not set href and alter the link (link.hidden = true or add a disabled CSS class) so the "View SVG" anchor is not shown or appears disabled when invalid; update references to vizUrl/link/div in that block accordingly.
209-218: Solid implementation of URL validation.The use of the
URLconstructor with a strict protocol allowlist is the correct approach to address CodeQL#196. The implementation correctly:
- Rejects invalid URLs via try/catch
- Restricts to http/https protocols only
- Returns a normalized, canonical URL
Scope consideration: Per the context snippets,
background.jsloads URLs from storage vialoadConfig()and passes them directly tosetServiceUrls()without validation. This means previously-stored malicious URLs (or URLs modified directly in storage) could still bypass this validation. The fix here is valuable for the options page UI path, but consider adding validation inpmoves-api.jsorbackground.jsas defense-in-depth.,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pmoves/chrome-extension/options/options.js` around lines 209 - 218, The options-only validation leaves previously stored or externally-modified URLs unvalidated; update the background loading and API call paths to validate again: in background.js modify loadConfig() to run each stored URL through validateServiceUrl() and only pass non-null results to setServiceUrls(), and add the same guard in pmoves-api.js where service URLs are consumed (validate before use and reject/ignore invalid entries), ensuring validateServiceUrl() is the single source of truth for canonicalization and rejection.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@pmoves/chrome-extension/options/options.js`:
- Around line 274-284: Refactor the inline URL validation to reuse the existing
validateServiceUrl(vizUrl) helper instead of duplicating constructor/protocol
checks: call validateServiceUrl(vizUrl) to determine validity and, if valid, set
link.href = normalizedUrl (or vizUrl as returned); otherwise do not set href and
alter the link (link.hidden = true or add a disabled CSS class) so the "View
SVG" anchor is not shown or appears disabled when invalid; update references to
vizUrl/link/div in that block accordingly.
- Around line 209-218: The options-only validation leaves previously stored or
externally-modified URLs unvalidated; update the background loading and API call
paths to validate again: in background.js modify loadConfig() to run each stored
URL through validateServiceUrl() and only pass non-null results to
setServiceUrls(), and add the same guard in pmoves-api.js where service URLs are
consumed (validate before use and reject/ignore invalid entries), ensuring
validateServiceUrl() is the single source of truth for canonicalization and
rejection.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 634a2096-7a02-4d52-b8c0-36c0b939d0ea
📒 Files selected for processing (1)
pmoves/chrome-extension/options/options.js
* docs(dashboard): refresh post-PRs #867-871 + branch sync Update Production Audit Dashboard with PRs #867-871 (port registry, smoke test remaps, CodeQL #196 fix, Jellyfin smoke codes). Sync main → Hardened (c6bc276). CodeQL #195 FP correctly suppressed, pending GitHub dismissal. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(healthcheck): replace wget with node for supabase-meta postgres-meta image lacks wget/curl — use built-in Node.js http module for the /health endpoint check. Verified healthy in local testing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Shaela Bello <slbello@uncg.edu> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Summary
new URL()constructor + stricthttp:/https:protocol allowlist inchrome-extension/options/options.js(CodeQL Codex/add cloudflared service with makefile targets #196)validateServiceUrl()helper applied to bothfetch()call sites — individual test button (line 121) and test-all button (line 162) (CodeRabbit follow-up)Test plan
javascript:URLshttp://localhost:8080URLs still work correctlySupersedes security portion of PR #866.
🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes