Skip to content

fix(security): close procfs credential read + wire MCP/ToolSearch into the injection scan - #1654

Open
elhoim wants to merge 2 commits into
danielmiessler:mainfrom
elhoim:security/harden-classifier-and-scan-wiring
Open

fix(security): close procfs credential read + wire MCP/ToolSearch into the injection scan#1654
elhoim wants to merge 2 commits into
danielmiessler:mainfrom
elhoim:security/harden-classifier-and-scan-wiring

Conversation

@elhoim

@elhoim elhoim commented Jul 26, 2026

Copy link
Copy Markdown

Two fixes to the same subsystem: both close a gap between what the security layer says it does and what it actually covers.

cat /proc/self/environ auto-allowed

CREDENTIAL_PATHS guards ~/.ssh keys, ~/.aws/credentials, GPG keyrings and .env files. procfs reaches the same secrets by another route — environ is the process environment (API keys, tokens), mem/maps are its address space.

Because cat is in SEARCH_TOOLS, classifyCommand() reached the read-only-command allow branch and returned allow, printing the whole environment with no prompt. The credential check runs before that branch, so a procfs entry in CREDENTIAL_PATHS closes it cleanly — these reads now return neutral and defer to the native permission prompt.

Covers literal pids, self, and the shell forms ($$, $PID, ${PID}) that reach the same file.

Verified — 16 cases through the real classifyCommand():

  • now neutral: /proc/self/environ, /proc/1234/environ, /proc/$$/environ, /proc/${PID}/environ, /proc/self/mem, /proc/self/cmdline, /proc/self/maps, grep -a TOKEN /proc/self/environ
  • still allow: /proc/cpuinfo, /proc/meminfo, /proc/loadavg, /proc/sys/vm/swappiness, ls /proc, cat README.md, rg TODO src/

No regression on ordinary procfs reads.

MCP and ToolSearch results were never injection-scanned

Safety.hook.ts documents the intended wiring in isAttackerWritableSource:

The settings.json PostToolUse matcher only routes WebFetch/WebSearch + the qualifying mcp__ names here; this gate is the defensive in-code backstop so a broad future matcher can't silently widen it.

The matcher only ever carried the WebFetch/WebSearch half. The ToolSearch and mcp mail/drive/calendar branches of that predicate were unreachable, so third-party-authored text arriving over those tools never got the data-not-instructions framing or the injection-shape scan.

Merges the two matcher entries into one alternation covering all four classes. The in-code gate still does the precise filtering, so unrelated MCP servers cost one neutral passthrough.

Also adds dropbox to the gate: file content pulled from a sync service is attacker-writable for the same reason drive already is — shared folders and file requests let a stranger put text there.

Verified — matcher compiled and asserted against real tool names. Routes WebFetch, WebSearch, ToolSearch, mcp__claude_ai_Gmail__*, mcp__claude_ai_Google_Drive__*, mcp__claude_ai_Google_Calendar__*, mcp__claude_ai_Dropbox__*. Skips Bash, Read, Edit, Agent, Skill, mcp__claude_ai_Indeed__*, mcp__claude_ai_Kiwi_com__*. Matcher and in-code gate agree on every case tested.

elhoim added 2 commits July 26, 2026 17:27
CREDENTIAL_PATHS guards ~/.ssh keys, ~/.aws/credentials, GPG keyrings and
.env files, but procfs reaches the same secrets by another route: a
process's environ holds its API keys and tokens, and mem/maps expose its
address space.

Because `cat` is in SEARCH_TOOLS, classifyCommand() took the
read-only-command allow branch for `cat /proc/self/environ` and returned
`allow` — printing every secret in the environment with no prompt.

Add a procfs entry to CREDENTIAL_PATHS so those reads return `neutral`
and defer to the native permission prompt. Covers literal pids, `self`
and the shell forms ($$, $PID, ${PID}) that reach the same file.
Ordinary procfs reads (cpuinfo, meminfo, loadavg, /proc/sys/*) are
unaffected and still auto-allow.

(cherry picked from commit d1f7df7)
… scan

Safety.hook.ts documents the intended wiring at isAttackerWritableSource:
"the settings.json PostToolUse matcher only routes WebFetch/WebSearch +
the qualifying mcp__ names here", with the in-code gate as the defensive
backstop.

The matcher only ever carried the WebFetch/WebSearch half. The ToolSearch
and mcp mail/drive/calendar branches of that predicate were unreachable,
so third-party-authored text arriving over those tools was never given the
data-not-instructions framing or the injection-shape scan.

Merge the two matcher entries into one alternation covering all four
classes. The in-code gate still does the precise filtering, so unrelated
MCP servers cost one neutral passthrough and nothing more.

Also add dropbox to the gate: file content pulled from a sync service is
attacker-writable for the same reason drive already is (shared folders,
file requests).

(cherry picked from commit da74472)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant