Skip to content

security: remove leaked API key + harden operator-API auth & path containment#64

Draft
ConWan30 wants to merge 1 commit into
mainfrom
claude/repo-vulnerability-analysis-wvwmow
Draft

security: remove leaked API key + harden operator-API auth & path containment#64
ConWan30 wants to merge 1 commit into
mainfrom
claude/repo-vulnerability-analysis-wvwmow

Conversation

@ConWan30

Copy link
Copy Markdown
Owner

Summary

Full-repo vulnerability review. This PR fixes the safe, code-level findings; deployed/FROZEN
Solidity findings and one dev-only fail-open are reported for operator review rather than
patched (changing live, PV-CI-pinned bytecode is out of the safe-change envelope for an audit
branch). Full write-up: audits/security-review-2026-06-27.md.

Fixed in this PR

  • CRITICAL — leaked credential. The live QuickSilver API key sk-el_… was hardcoded as a
    fallback in bridge/vapi_bridge/vapi_llm_client.py and frontend/src/views/LlmChatView.jsx
    in this public repo (the frontend also shipped it to every browser). Removed both
    fallbacks; the code now fails closed when the env var is unset. Working tree is git grep
    clean.
  • HIGH — auth bypass + timing oracle. POST /operator/evaluate-agent-action used
    api_key != cfg.operator_api_key. Under the default empty OPERATOR_API_KEY, an empty
    api_key passed ("" != "" → False) on a state-mutating endpoint. Now fails closed (503
    when unconfigured) and uses hmac.compare_digest.
  • MEDIUM — timing-unsafe compares. Five plain != operator-key checks in
    transports/http.py (PATCH /config, passport endpoints, +2) replaced with
    hmac.compare_digest.
  • MEDIUM — path traversal. read_file in operator_api/agent_misc.py confined paths with
    startswith(), which admits sibling dirs whose name extends the repo root
    (../QorTroller-secret/…). Replaced with os.path.commonpath().

⚠️ Operator action required (cannot be done in code)

  1. Rotate/revoke the QuickSilver key now — it has been public and remains in git history.
    History purge would require a force-push to a public repo (left to explicit operator decision);
    rotation is the load-bearing mitigation.

Reported for follow-up (not changed here)

  • Bridge read-key fails open when OPERATOR_API_KEY is unset (default) — recommend a startup
    assertion or explicit ALLOW_UNAUTH_READS opt-in.
  • Solidity (deployed/FROZEN, need redeploy): VAPIQuickSilverCollateral.claimExcessYield cross-
    operator collateral drain; permissionless BountyMarket.aggregateSwarmReport; un-timelocked
    VAPIGovernanceTimelock.setCoSigner/transferOperator; PoACVerifier/TieredDeviceRegistry/
    ZKSepProofVerifier signature replay (missing domain separation / caller binding). Details and
    fixes in the audit report.

Verification

Edited modules syntax-check clean; path-containment fix validated against in-repo / ../../../passwd
/ /etc/passwd / sibling-prefix cases; test_local_host_tools_endpoint.py 5/6 (the 1 failure is a
pre-existing checkout fixture that fails identically on main); operator-initiative o3 tests pass.

Confirmed clean

Parameterized SQL (no injection), no os.system/shell-injection on HTTP paths, no insecure
deserialization, no SSRF, CORS correctly scoped, no other committed secrets.

🤖 Generated with Claude Code


Generated by Claude Code

…ntainment

Full-repo vulnerability review (report: audits/security-review-2026-06-27.md).
Fixes the safe, code-level findings; deployed/FROZEN Solidity findings are
reported for operator review + redeploy, not patched here.

- CRITICAL: remove hardcoded QuickSilver API key fallback baked into a public
  repo in bridge/vapi_bridge/vapi_llm_client.py and frontend LlmChatView.jsx.
  Both now fail closed when the env var is unset. (Key must be ROTATED at the
  provider — it is in git history and has been world-readable.)
- HIGH: POST /operator/evaluate-agent-action allowed an empty-key bypass under
  the default empty OPERATOR_API_KEY and used a timing-unsafe compare. Now fails
  closed (503) when unconfigured and uses hmac.compare_digest.
- MEDIUM: replace five plain `!=` operator-key comparisons in transports/http.py
  with hmac.compare_digest (timing-oracle hardening).
- MEDIUM: fix read_file path containment in operator_api/agent_misc.py — replace
  startswith() prefix test (admits sibling dirs like ../QorTroller-secret) with
  os.path.commonpath().

Verified: edited modules syntax-check clean; path-containment fix validated
against in-repo/escape/sibling cases; local-host tools tests pass 5/6 (the one
failure is a pre-existing checkout fixture, fails identically on origin);
operator-initiative o3 tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016miH3NCWew5RMRwWtfHBdA
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.

2 participants