fix(skills-guard): stop flagging sudo.request/sudo.respond event names as sudo usage

`sudo.request` and `sudo.respond` are gateway wire events: the masked
sudo-password prompt the terminal tool raises, which every client surface
(desktop, TUI, any plugin that relays secure prompts to another device)
has to name to forward it. The `sudo_usage` rule matched the bare word,
so any plugin listing those events scored `high` and every install of it
landed on `caution`, which Hermes Desktop cannot confirm past.

A dotted event name is never a shell `sudo` invocation. Exclude exactly
those two names with a negative lookahead; a real `sudo cmd` still fires.

(cherry picked from commit a7a3a31126de8057c2dbb9b7048724aa9d55a7fd)
This commit is contained in:
unsupportedpastels
2026-09-14 20:16:25 +00:00
committed by Teknium
parent 63395922bf
commit 4f00c456f0
2 changed files with 21 additions and 1 deletions

View File

@@ -192,6 +192,22 @@ class TestScanFile:
assert any(fi.category == "injection" for fi in findings)
def test_sudo_event_names_are_not_sudo_usage(self, tmp_path):
"""`sudo.request` / `sudo.respond` are the gateway's secure-prompt wire events (the masked sudo
password ask). A client plugin that relays those prompts must spell them out, and they are not
a privilege escalation — only a real `sudo` invocation is."""
events = tmp_path / "events.py"
events.write_text(
'INPUT_EVENTS = ("approval.request", "secret.request", "sudo.request")\n'
'RESPONSES = {"sudo.respond": "value"}\n',
encoding="utf-8",
)
assert not any(fi.pattern_id == "sudo_usage" for fi in scan_file(events, "events.py"))
setup = tmp_path / "setup.sh"
setup.write_text("sudo apt-get install -y jq\nsudo ./install.sh\n", encoding="utf-8")
assert [fi.line for fi in scan_file(setup, "setup.sh") if fi.pattern_id == "sudo_usage"] == [1, 2]
def test_deduplication_per_pattern_per_line(self, tmp_path):
f = tmp_path / "dup.sh"
f.write_text("rm -rf / && rm -rf /home\n", encoding="utf-8")

View File

@@ -304,7 +304,11 @@ THREAT_PATTERNS = [
# `allowed-tools:` is REQUIRED frontmatter per the agent-skill spec — informational (low) only.
(r'^allowed-tools\s*:',
"allowed_tools_field", "low", "privilege_escalation", "skill declares allowed-tools (standard frontmatter; informational)"),
(r'\bsudo\b', "sudo_usage", "high", "privilege_escalation", "uses sudo (privilege escalation)"),
# `sudo.request` / `sudo.respond` are gateway wire events (the masked sudo-password prompt), not an
# invocation: any client plugin that relays Hermes' secure prompts has to name them, and a bare
# `\bsudo\b` made every such plugin `caution`. A dotted event name is never a shell `sudo`.
(r'\bsudo\b(?!\.(?:request|respond)\b)',
"sudo_usage", "high", "privilege_escalation", "uses sudo (privilege escalation)"),
(r'setuid|setgid|cap_setuid',
"setuid_setgid", "critical", "privilege_escalation", "setuid/setgid (privilege escalation mechanism)"),
(r'NOPASSWD',