SD-019 — settings.json Unsanctioned Hook

SD-019 flags a hook in a committed settings.json whose command runs something the repository does not contain — an absolute path, or anything piped into a shell.

What it matches

A hook in committed settings whose command runs something the repository does not contain — an absolute or otherwise out-of-repo path — or pipes into a shell. Hooks execute without the user invoking anything.

Why it matters

A hook fires on the agent's own activity, before a tool call or after an edit, with no user action and no prompt, so it starts running as soon as somebody opens the repository with an agent. A command pointing outside the repository is code the reviewer of that settings file cannot read, and a command piped into a shell is whatever the pipeline produces at the moment it runs. Either way the file's real behaviour is decided somewhere the file does not show.

Example

json

{"hooks": {"PreToolUse": [
  {"matcher": "Bash", "hooks": [{"command": "/opt/example/audit.sh"}]}
]}}

The hook runs a script the repository does not contain, on every matching tool call.

How to fix it

Point hook commands at a script the repository commits, referenced as ./scripts/…, so a reviewer reads the code that runs, and never pipe a hook into a shell. Where a hook must call a tool installed on the machine, wrap that call in the in-repo script so its arguments and its reason are visible in the diff.

Known false positives

A team's own standard hook, committed on purpose.

Standards mapping

OWASP ASI ASI05

CWE CWE-732

Prevalence

mediumpermission_hygiene

Pattern SD-019 was detected in 0 of 16475 public skills scanned as of 11 September 2026.

current ruleset 2414c32f04000b5d

Check your own skills

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