Skip to content

chore: triage CodeQL findings (fix prototype-pollution risk + length caps)#20

Merged
andresdefi merged 2 commits into
mainfrom
chore/codeql-triage
May 22, 2026
Merged

chore: triage CodeQL findings (fix prototype-pollution risk + length caps)#20
andresdefi merged 2 commits into
mainfrom
chore/codeql-triage

Conversation

@andresdefi
Copy link
Copy Markdown
Owner

Summary

Triage of the 61 open CodeQL alerts on the Security tab. Result: 4 alerts will remain after this PR merges (and they auto-close on next CodeQL re-scan since the code fixes are in this PR).

Real bugs fixed

js/remote-property-injection — prototype-pollution risk in locale endpoints (8 alerts)

The locale-add / remove / set-active / patch-screen endpoints used the user-supplied code as a computed object key ({ ...localeScreens, [code]: ... }). Spread + computed key is safe from Object.prototype pollution per spec, but a key like toString or __proto__ would still shadow built-ins on later reads.

Added an isSafeObjectKey helper that rejects __proto__, constructor, prototype, toString, valueOf, hasOwnProperty, and the legacy __define*Getter/Setter__ family. Applied at all 4 locale entry points. Integration test added.

js/polynomial-redos — adversarial-input regex backtracking (2 alerts)

  • packages/core/src/color/p3.tsparseDisplayP3() regex with repeated digit groups. Capped input at 200 chars (legitimate strings are ~70).
  • packages/mcp/src/client.tsbaseUrl.replace(/\/+$/, '') could backtrack on thousands of trailing slashes. Capped at 2048 chars (RFC 3986 URL recommendation).

js/unused-local-variable — dead imports (2 alerts)

  • e2e/ux-audit.spec.ts — removed sidebar, preview, modeToggle
  • e2e/functional.spec.ts — removed modeToggle

False positives dismissed (49 alerts)

Rule Count Reason
js/path-injection 33 Project slugs validated via PROJECT_SLUG_RE; resolved paths checked with isPathInside (utils/pathSafety.ts). CodeQL doesn't recognise these sanitisers.
js/missing-rate-limiting 8 Local-only dev server (127.0.0.1, CORS rejects cross-origin). Rate limiting would be theatre.
js/http-to-file-access 5 4 are dev-time build scripts fetching from known content-addressed asset URLs; 1 is sharp writing a resized buffer from on-disk input.
js/reflected-xss 2 Local-only preview server (127.0.0.1, cross-origin blocked). Text fields go through sanitizeRichHtml or Nunjucks auto-escape.
js/file-access-to-http 1 Intentional — upload_screenshot MCP tool's job is to send a file as a request body.

All dismissals include the justification visible on the alert. If new CodeQL scans flag the same patterns, they'll auto-link back to the dismissal reason.

Test plan

  • pnpm typecheck clean
  • pnpm test — 535 / 535 passing (1 new integration test for prototype-pollution defense)
  • pnpm lint clean
  • pnpm build succeeds

🤖 Generated with Claude Code

andresdefi and others added 2 commits May 22, 2026 16:53
…ports

CodeQL flagged 9 `js/remote-property-injection` warnings on the
project envelope's locale endpoints. The pattern was:

  { ...localeScreens, [code]: ... }

where `code` was only validated for `typeof === 'string'` and
non-empty. Spread + computed key on a fresh object is safe from
Object.prototype pollution (the result has the key as an own
property, not on the prototype), but a key like `toString` or
`__proto__` would still shadow built-ins on later reads and
silently break the editor state.

Adds an `isSafeObjectKey` helper that rejects `__proto__`,
`constructor`, `prototype`, `toString`, `valueOf`, `hasOwnProperty`,
and the legacy `__define*Getter/Setter__` family. Applied at every
locale-code entry point:

  - POST /api/projects/:project/locales/add
  - POST /api/projects/:project/locales/remove
  - POST /api/projects/:project/locales/set-active
  - POST /api/projects/:project/locales/:code/patch-screen

Plus an integration test that POSTs each dangerous key and asserts
the endpoint returns 400 with a clear error message.

Also drops unused imports in two e2e specs that CodeQL flagged:
- e2e/ux-audit.spec.ts: removed `sidebar`, `preview`, `modeToggle`
- e2e/functional.spec.ts: removed `modeToggle`

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…king

CodeQL js/polynomial-redos flagged two regex sites where adversarial
input could trigger non-linear backtracking:

- packages/core/src/color/p3.ts parseDisplayP3() regex has
  `\d*\.?\d+(?:e[+-]?\d+)?` repeated for r/g/b. Many '9's could
  trigger polynomial behavior. Cap input at 200 chars before matching
  (longest legitimate string is ~70).
- packages/mcp/src/client.ts constructor calls .replace(/\/+$/, '')
  on the baseUrl. Many trailing slashes could backtrack. Cap baseUrl
  at 2048 chars (RFC 3986 URL guidance).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@andresdefi andresdefi merged commit e633efb into main May 22, 2026
4 checks passed
@andresdefi andresdefi deleted the chore/codeql-triage branch May 22, 2026 15:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant