feat(detectors): broaden Claude grant/deny coverage and harden instruction scan#51
Merged
Conversation
…ction scan Claude permissions (parsers/claude.ts): - Treat a bare `Bash`, `Read`, `Write`, or `Edit` allow as broad. In Claude Code a bare tool name matches every use of the tool, so it grants unrestricted shell / filesystem access — previously only bare WebFetch / WebSearch / Task and wildcard/broad-root forms were flagged. Filesystem verbs keep narrow semantics for scoped subtree globs (Read(src/**) stays narrow); only bare or broad-root forms (Read(/), Write(C:\), Read(~/**)) are broad. Bash/Web/Task remain broad on any wildcard scope. - Expand isSensitiveDeny beyond .env/secret/credential/.pem to cover SSH and signing keys, tokens, .npmrc/.pypirc/.netrc, kubeconfig, cloud credential stores, and .p12/.pfx/.key. The posture-gap and overlap detectors depend on recognising strict denies, so the list errs toward inclusion. Instruction scan (parsers/instructions.ts): - Scan the legacy single-file `.cursorrules` alongside the modern surfaces. - Track Markdown fenced code blocks (``` / ~~~) and skip their contents, so a documentation example showing a "bad" instruction is no longer flagged as a live directive. Tests cover bare vs scoped grants, the expanded sensitive-deny list, .cursorrules scanning, and fenced-code skipping (real directive outside the fence still fires). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
Addresses review findings #5, #6, #7.
Claude permissions (
parsers/claude.ts)#5 — bare tool grants.
isBroadAllowflagged bareWebFetch/WebSearch/Taskand wildcard/broad-root forms, but not a bareBash,Read,Write, orEdit. In Claude Code a bare tool name matches every use of the tool, so those grant unrestricted shell / filesystem access and are now treated as broad.Filesystem verbs get correct scope semantics: a scoped subtree glob like
Read(src/**)stays narrow (it's not a broad grant); only bare (Read) or broad-root (Read(/),Write(C:\),Read(~/**),Read(**)) forms are broad. Bash/Web/Task remain broad on any wildcard scope (Bash(npm *)).#6 — sensitive denies. Expanded
isSensitiveDenybeyond.env/secret/credential/.pemto also cover SSH & signing keys (.ssh,id_rsa,id_ed25519,.key,.p12,.pfx),token,.npmrc/.pypirc/.netrc,kubeconfig, and cloud credential stores (.gcp,.azure;.aws/credentialsalready matchedcredential). The posture-gap and deny/allow-overlap detectors depend on recognising strict denies, so the list errs toward inclusion (a deny is the protective side).Instruction scan (
parsers/instructions.ts)#7 — legacy
.cursorrulesis now scanned alongsideAGENTS.md,CLAUDE.md, Copilot instructions, and.cursor/rules/*.#7 — fenced code. The scanner now tracks Markdown code fences (
```/~~~) and skips their contents, so a documentation example showing a "bad" instruction (Ignore all safety checks…inside a fence) is no longer flagged as a live directive. A real directive outside the fence still fires.Tests
Unit tests for bare-vs-scoped grants (incl.
Read(src/**)stays narrow) and the expanded sensitive-deny list; CLI tests for.cursorrulesscanning and fenced-code skipping. The previously-cleanalignedfixture stays atnonerating (caught a regression whereRead(src/**)was briefly mis-flagged). All 122 tests pass;dist/rebuilt and committed.🤖 Generated with Claude Code