v5.15.1 - Security: ClaudeHookBridge & SandboxPolicy matcher bypass fixes
Fixes two high-severity vulnerabilities reported against the v5.14.0/v5.15.0 ecosystem-expansion and context-composer features shipped in the last two releases. Both are validator/executor representation mismatches (CWE-
v5.15.1 - Security Patch
Fixes two high-severity vulnerabilities reported against the v5.14.0/v5.15.0 ecosystem-expansion and context-composer features shipped in the last two releases. Both are validator/executor representation mismatches (CWE-436, CWE-863) - a security gate matched one string form while the actual executor ran a different, derived form.
GHSA-743h-jr5x-mpcr - ClaudeHookBridge deny-pattern bypass via truncation before the security decision (High)
extractTarget() truncated the string evaluated against denyPatterns/allowPatterns to 500 characters, while Claude Code always executes the complete, untruncated tool input. Dangerous content positioned past byte 500 (trivially achievable via leading padding) was invisible to the operator's hard-deny list yet still ran. In the default observe mode, denyPatterns is the sole hard block, so this was a complete bypass.
Fixed: deny/allow pattern matching now runs against the full, untruncated target (extractFullTarget()). A new maxTargetLength option (default 65,536 chars) denies oversized targets outright instead of matching against them, closing the bypass and bounding regex evaluation cost. Truncation (truncateForDisplay()) is applied only afterward, for audit-log/reason-text display.
GHSA-9v4f-j8cv-fhxw - SandboxPolicy blocklist/approval-gate bypass via quote/whitespace mismatch (High)
isCommandAllowed's blocklist/allowlist glob, requiresApproval, and assessRisk matched the raw, quote-and-whitespace-preserving command string, while the executor tokenizes the command (stripping quotes, collapsing whitespace) before spawn(..., { shell: false }). A compromised/constrained agent could quote a destructive command (rm -rf '/') to defeat the blocklist's flagship recursive-delete entry, or quote a gated command (git "push" origin main) to skip the human approval gate - both executing identically to their unquoted form. Same validator/executor mismatch class as GHSA-qw6v-5fcf-5666, on a distinct code path that fix did not cover.
Fixed: isCommandAllowed, requiresApproval, and assessRisk now all match against a canonicalized form (parseCommandLine -> argv.join(' ')) - the exact representation the executor runs - via a new shared canonicalize() helper. requiresApproval/assessRisk fail closed (require approval / assess high risk) when a command cannot be safely canonicalized.
Testing
- New
test-phase20.ts(35 assertions) reproduces both published PoCs verbatim, plus oversized-target fail-closed behavior, audit-display truncation, a whitespace-variant bypass check, and normal-command non-regression checks. - Full suite: 3,638 tests passing across 41 suites;
tsc --noEmitclean.
Docs
Version bump across all 17 tracked files, including two that had drifted stale across the last two releases (BENCHMARKS.md, AUDIT_LOG_SCHEMA.md). THREAT_MODEL.md Security Controls Summary table updated with both new mitigations.