fix(security): validate selector parameter before DOM.querySelector - #32
Conversation
) Add validateSelector() to upload-validator.ts enforcing a 500-character length cap and a CSS-grammar character allowlist. Call it in uploadFile() and uploadFiles() in cdp-client.ts before the CDP DOM.querySelector call, and at the comet_upload tool-handler boundary in index.ts for defense-in-depth. Error messages do not echo the raw selector value (avoids reflected-value injection if the MCP client ever renders responses as HTML).
Security Review — PR #32Reviewed commit: Automated Checks
Finding 1: CONFIRMED — http-bridge.ts missing selector validation at handler boundaryFile: Code: const result = await cometClient.uploadFile(resolvedPath, args.selector);Evidence (full code path):
Assessment: The However, Verdict on severity: Since the inner guard fully covers the attack path, this is NOT a functional security gap. It is a missed defense-in-depth opportunity on a second exposed surface. The PR correctly addresses the CDP-layer vulnerability. The Confidence: CONFIRMED (code path traced) — the inner guard fires; the outer layer is just missing consistent hardening. Finding 2: POSSIBLE — validateSelector allowlist permits raw newlines via \sFile: Code: Evidence: Positive Findings
SummaryThe core fix is correct and sufficient. The inner guard in
Verdict: APPROVED. The PR addresses the stated issue. SEC-1 should be tracked as a follow-up finding issue. |
RapierCraft
left a comment
There was a problem hiding this comment.
APPROVED: commit 5707217 after security review (1 agent: General Security). 2 findings created as issues (#33, #34) — both LOW severity, neither blocking.
Key points:
- Core fix is correct:
validateSelector()incdp-client.tsprotects all callers includinghttp-bridge.ts - Defense-in-depth in
index.tsis properly placed - Build passes, formatting clean, no secrets
- Issue #33 (SEC-1, LOW):
http-bridge.tsmissing outer handler validation — inner guard covers it - Issue #34 (SEC-2, LOW/POSSIBLE):
\sin allowlist permits newlines — advisory only
Safe to merge.
PR Review Summary: #32 - fix(security): validate selector parameter before DOM.querySelectorReview IntegrityReviewed commit: Verdict: APPROVED ✅Context-Aware ReviewDomains: Security (Validation) | Agents: 1 (General Security) Integration Checks (Phase 2.5)Scope gap found: Risk Matrix
Findings
Automated Checks
RecommendationMerged. Follow-up: fix #33 (http-bridge.ts outer guard) in a separate PR to complete the defense-in-depth parity. Security review complete. 1 agent + integration checks. 2 findings triaged. PR merged to |
Summary
Adds
validateSelector()tosrc/upload-validator.tsand calls it before theDOM.querySelectorCDP invocation incdp-client.ts, plus defense-in-depth validation at thecomet_uploadtool-handler boundary inindex.ts.A pathologically long or deeply nested selector can cause the Comet renderer to spend significant CPU time parsing — denial-of-service against the browser process. This PR caps selectors at 500 characters and enforces a CSS-grammar character allowlist.
Changes
src/upload-validator.ts: NewvalidateSelector(selector: string): stringexport — max 500 chars, CSS character allowlist, error does not echo raw valuesrc/cdp-client.ts: ImportvalidateSelector; call it inuploadFile()anduploadFiles()beforeDOM.querySelectorsrc/index.ts: ImportvalidateSelector; call it incomet_uploadhandler for defense-in-depthTesting
comet_uploadwith a valid selector (e.g.input[type="file"]) still works [type:manual]comet_uploadwith a 501-character selector returns an error without crashing [type:manual]comet_uploadwith a selector containing<script>characters is rejected [type:manual]comet_uploadwithselectoromitted (auto-detect) still works [type:manual]npm run buildpasses [type:unit]Closes #27
Implementation branch:
fix/validate-selector-27Base:
main