SD-018 — settings.json Broad Allow with Protective Deny

SD-018 flags a settings.json deny entry that a wildcard allow entry already covers, which shows the allowlist is wider than the deny beside it suggests it was meant to be.

What it matches

In supported Claude settings, a Bash or PowerShell deny subcommand covered by a broader wildcard allow. Current Claude Code deny precedence still blocks it; the pair reveals an overbroad allow.

Why it matters

Current Claude Code applies deny over allow, so the deny still blocks the matched command; the pair is not a demonstrated bypass. It shows that the allow entry grants a wider command family and relies on version-sensitive deny handling to carve one member back out.

Example

json

{"permissions": {
  "allow": ["Bash(git *)"],
  "deny":  ["Bash(git push *)"]
}}

The allow grants every git subcommand; the deny names back only one of them.

How to fix it

Express the restriction in the allowlist: list the subcommands the agent may run instead of granting the whole command and denying one. Keep a deny only as defence in depth for something the allowlist already excludes — a deny that carves a hole out of a wildcard is hiding how wide that wildcard is.

Known false positives

A deny kept deliberately as defense in depth.

Standards mapping

OWASP ASI ASI03

CWE CWE-732

Agent Skills in the Wild PE1

Prevalence

highpermission_hygiene

Pattern SD-018 was detected in 0 of 16996 public skills scanned as of 27 October 2026.

current ruleset eb11e25d39bc2c81

Check your own skills

Scan a repository or a single skill against this rule and the rest of the catalogue, free.