Commit Graph

2 Commits

Author SHA1 Message Date
teknium1
50e9cd7bd5 fix(plugin-guard): two intake false positives — regex literal <script, allowlist "printenv"
Desktop lint: /<script[\s\S]*?<\/script>/gi in a feed sanitiser scored as
'script injection' and failed pinned-source-validate for rss-reader. Mask
JS regex literals for the markup-shaped rule only; <script in a string
literal (an innerHTML payload) and createElement('script') still fail.

Install scanner: "printenv" as a whole-string entry of a read-only
allowlist (frozenset({..., "printenv"})) fired dump_all_env high →
caution on hermes-jev. Extend the literal-token demotion: a token that is
the ENTIRE quoted literal on a line that executes nothing steps down like
an alternation member; "sudo" inside subprocess.run([...]) and
os.system("printenv") keep high.

A/B vs origin/main: attack probes identical (23 rows), in-tree sweep 319
entries 0 worse/0 changed; both new tests red on base. Bumps
PLUGIN_SCANNER_VERSION to v6 so cached caution verdicts refresh.

Signed-off-by: teknium1 <teknium1@users.noreply.github.com>
2026-09-19 14:30:36 -07:00
teknium1
5a0c2fb89e fix(plugins): install scanner scores inert context as context, not as plugin behaviour
A plugin repository is a codebase, and the threat regexes were written for a SKILL.md
the agent executes verbatim. The same text in a README uninstall step, a refusal list,
a test fixture, a JSON scenery data URI, a redaction regex or a `gh api | base64 -d |
grep` dev script was scored as the plugin's own runtime behaviour: crypto-prices
(#115353) was hard-blocked by `rm -rf "$HOME/.hermes/plugins/crypto-prices"` in its
README, and a dozen catalog pins sat at `caution` on fixtures and prose alone.

`tools/plugin_guard_context.py` recognises each class of inert context and only ever
lowers a finding; nothing is deleted and every finding stays in the report:

- documentation prose (`.md/.txt/.rst/.html`, not `SKILL.md`, `after-install.md` or a
  bundled `skills/` tree): command/path shapes step down once, so a doc line can never
  be `dangerous`; the plugin's own-install-dir `rm` is a note. Injection, Markdown
  exfil, agent-config edits, `curl | sh`, `authorized_keys` and leaked keys keep full
  severity.
- test trees / fixtures (root test dirs, `__tests__`/`__fixtures__` at any depth,
  `*.test.*`, `test_*.py`): quoted-only hostile strings and key-shaped corpora are
  notes; test code that executes on import steps down once (caution).
- whole-line comments and CHANGELOG.md score as prose.
- `encoded_exfil` on base64 whose decoded head is a media magic (PNG/JPEG/WOFF/PDF...)
  is informational.
- `sudo` / `env|` as an alternation member inside a regex or string literal is a note;
  the same word in a command string is not.
- `base64 -d` piped into a text filter is a note; into a shell/interpreter it is not.

Bumps PLUGIN_SCANNER_VERSION to v5 so cached verdicts re-evaluate.

Closes-blocker-for: #115353
2026-09-19 03:20:05 -07:00