fix(security): SecurityValidator schema mismatch + fail-closed#1014
Open
christauff wants to merge 1 commit intodanielmiessler:mainfrom
Open
fix(security): SecurityValidator schema mismatch + fail-closed#1014christauff wants to merge 1 commit intodanielmiessler:mainfrom
christauff wants to merge 1 commit intodanielmiessler:mainfrom
Conversation
…losed
Three security issues found via vulnerability analysis of the leaked Claude Code
source (instructkr/claude-code, 13.8k stars). The CC source revealed how hook
JSON output is validated, exposing a critical schema mismatch that silently
breaks all confirm-level security controls.
## Fixes
### 1. `decision: 'ask'` Zod schema mismatch (CRITICAL)
The hook outputs `{"decision": "ask"}` for confirm-level operations, but CC's
Zod schema (`types/hooks.ts:64`) only accepts `z.enum(['approve', 'block'])`.
The value 'ask' fails validation, CC treats it as a non-blocking error, and the
operation proceeds WITHOUT user confirmation.
**Every confirm-level protection was silently non-functional:**
- git push --force, git reset --hard
- rm -r (recursive deletion)
- All cloud/infra operations (AWS, GCP, Terraform, kubectl)
- All database operations (DROP, DELETE, TRUNCATE)
- All confirmWrite file protections (hooks, SSH config)
**Fix:** Use the correct CC schema path: `hookSpecificOutput` with
`hookEventName: 'PreToolUse'` and `permissionDecision: 'ask'`, which IS
supported by `z.enum(['allow', 'deny', 'ask'])` in `PermissionRule.ts:26`.
### 2. Fail-open → fail-closed on all error paths
Four error paths returned `{"continue": true}` (fail-open), allowing operations
to proceed when the security validator itself encountered errors:
- Missing patterns.yaml → was empty permissive config, now hardcoded deny rules
- YAML parse error → was empty permissive config, now hardcoded deny rules
- stdin JSON parse failure → was `{"continue": true}`, now `process.exit(2)`
- Unhandled exception in main() → was `{"continue": true}`, now `process.exit(2)`
- stdin 200ms timeout → was `{"continue": true}`, now `process.exit(2)`
### 3. Updated doc header to reflect fail-closed security model
## Discovery
These vulnerabilities were identified through static analysis of the Claude Code
source code that was accidentally published via npm source maps on 2026-03-31
(archived at github.com/instructkr/claude-code). Analysis of CC's hook execution
model in `utils/hooks.ts` revealed that exit code 2 = blocking, while all other
non-zero exit codes are treated as non-blocking errors that allow the operation.
This, combined with the Zod schema analysis in `types/hooks.ts`, confirmed the
`decision: 'ask'` mismatch.
Two prior CC CVEs (CVE-2025-59536, CVE-2026-21852) reported by Check Point
Research established precedent for this class of hook security analysis.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
justinkatz94-glitch
pushed a commit
to justinkatz94-glitch/Personal_AI_Infrastructure
that referenced
this pull request
Apr 3, 2026
…lmiessler#1014) Three security fixes: 1. decision:'ask' fails CC Zod validation (only accepts 'approve'|'block') - Changed to hookSpecificOutput with permissionDecision:'ask' - Every confirm-level control was silently non-functional 2. Five error paths fail-open (continue:true) instead of fail-closed - Now use process.exit(2) which CC treats as blocking denial 3. Added extractWritePathsFromBash() for deeper command analysis - Catches writeFileSync, shell redirections, tee, sed -i, cp/mv Closes danielmiessler#1014
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes three security vulnerabilities in
SecurityValidator.hook.tsdiscovered through vulnerability analysis of the leaked Claude Code source (instructkr/claude-code, 13.8k+ stars, accidentally published via npm source maps on 2026-03-31).1.
decision: 'ask'Zod Schema Mismatch (Critical)The hook outputs
{"decision": "ask"}for confirm-level operations (force push, recursive delete, cloud ops, database ops, confirmWrite paths). However, Claude Code's Zod validation schema attypes/hooks.ts:64only acceptsz.enum(['approve', 'block'])for the top-leveldecisionfield. The value'ask'fails schema validation, CC treats it as a non-blocking error, and the operation proceeds without user confirmation.Every confirm-level security control is silently non-functional -- force pushes, recursive deletions, cloud resource destruction, and database operations all pass through without prompting.
Fix: Use the correct CC schema path --
hookSpecificOutputwithhookEventName: 'PreToolUse'andpermissionDecision: 'ask'-- which IS supported byz.enum(['allow', 'deny', 'ask'])inPermissionRule.ts:26.2. Fail-Open to Fail-Closed on All Error Paths
Five error paths returned
{"continue": true}(fail-open), allowing operations to proceed when the security validator encountered errors:process.exit(2)process.exit(2)process.exit(2)CC's hook execution model treats exit code 2 as blocking (operation denied), while all other non-zero exit codes are non-blocking errors (operation allowed). This makes
process.exit(2)the correct fail-closed behavior.3. Updated Doc Header
Reflects the new fail-closed security model.
Discovery Context
These vulnerabilities were identified by analyzing how Claude Code processes hook output -- specifically the Zod schema validation in
types/hooks.tsand the exit code handling inutils/hooks.ts:2647-2697. Two prior CC CVEs (CVE-2025-59536 and CVE-2026-21852, both from Check Point Research) established precedent for this class of hook security analysis.Test Plan
ls,cat) still return{"continue": true}(allow)exit(2)(block)git push --force) now output validhookSpecificOutputJSONexit(2)(fail-closed) instead of{"continue": true}Generated with Claude Code