fix(approval): gate perl -i and awk -i inplace edits of Hermes config/env - #37107
fix(approval): gate perl -i and awk -i inplace edits of Hermes config/env#37107briandevans wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR expands dangerous-command detection to block additional in-place editors (Perl and Awk) from directly mutating Hermes config/env files, closing a bypass similar to the existing sed -i protection.
Changes:
- Add dangerous-command patterns for
perl -i*andawk/gawk -i inplacetargeting Hermes config/env paths. - Add test coverage for the new Perl/Awk in-place patterns, including positive and negative cases.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| tools/approval.py | Adds regex detections for Perl/Awk in-place edits to Hermes config/env files. |
| tests/tools/test_approval.py | Adds tests validating the new in-place editor detections and no-regression negatives. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # mutates ~/.hermes/config.yaml (or .env) directly, and the mtime-keyed | ||
| # config cache reloads it mid-session — so gating only `sed` leaves the | ||
| # write_file/patch deny unpaired. Sibling follow-up to #14639. | ||
| (rf'\bperl\s+-[^\s]*i.*(?:{_HERMES_CONFIG_PATH}|{_HERMES_ENV_PATH})', "in-place edit of Hermes config/env (perl -i)"), |
|
Hermes Agent auto-review — approval gate hardening: ✅ clean. Sibling follow-up to the |
|
@copilot All findings addressed in commit 78ddc36ab:
|
1a8dceb to
105a7fd
Compare
…/env The terminal-side pairing for ~/.hermes/config.yaml and .env (NousResearch#14639) gated `sed -i` / `sed --in-place` but not the other standard in-place editors that reach the same security file: `perl -i` (also `-pi`, `-i.bak`) and `awk -i inplace` / `gawk -i inplace`. Each mutates the file directly, bypassing the redirection/tee/cp patterns, and the mtime-keyed config cache reloads it mid-session — so the agent can flip approvals.mode=off and bypass the gate. Gating only sed left the write_file/patch deny unpaired theater for these verbs. Add two DANGEROUS_PATTERNS entries reusing the audited _HERMES_CONFIG_PATH / _HERMES_ENV_PATH fragments (no new path fragment; only the editor verb is widened). Regression tests cover perl -i / -pi / -i.bak, awk/gawk -i inplace, the $HERMES_HOME override form, and no-regression negatives (read-only awk, scratch-path in-place edit, cat).
… not gated The perl in-place pattern used a loose `-[^\s]*i` match that fired on any 'i' in a flag bundle. Detection lowercases input and runs under re.IGNORECASE, so perl's include-path flag `-I` (uppercase, takes a directory arg) collapses to `-i` and `perl -Ilib script.pl ~/.hermes/config.yaml` was wrongly flagged as an in-place edit. Require `-i` to be a genuine in-place flag: an optional bundle of perl's boolean prefix flags, then 'i', then a flag boundary (whitespace) or a backup suffix start (.bak / ~ / quote / *). `-Ilib` no longer matches because 'i' is followed by include-path letters. Real in-place edits, including when an include path precedes `-i`, still gate.
105a7fd to
86b26ed
Compare
This is a sibling follow-up to commit
4e9d886d9(fix(approval): pair terminal-side gate for ~/.hermes/config.yaml writes)sed -i/sed --in-placeof~/.hermes/config.yamland.env(added_HERMES_CONFIG_PATH, folded into_SENSITIVE_WRITE_TARGET+ sedDANGEROUS_PATTERNS).perl -i(also-pi,-i.bak) andawk -i inplace/gawk -i inplace. Same in-place-mutation pattern, different editor verb, reaches the same security file.perl -iandawk -i inplaceagainst~/.hermes/config.yamland.env, reusing the existing_HERMES_CONFIG_PATH/_HERMES_ENV_PATHfragments.What does this PR do?
Pairs the remaining terminal-side in-place editors with the existing write_file/patch deny on
~/.hermes/config.yaml/.env.sed -iis already gated (#14639 / 4e9d886);perl -i -pe 's/.../approvals.mode: off/' ~/.hermes/config.yamlandawk -i inplacewere not. Because the config cache is mtime-keyed, such an in-place write takes effect mid-session and the agent can flipapprovals.mode=offto bypass the approval gate — so the sed-only pairing is incomplete ("theater" per SECURITY.md, the same argument the parent made for sed).Issue lists 1 escalation vector at this code site (in-place edit of the Hermes security config). The parent closed it for
sed; this PR closes the remaining editor verbs (perl -i,awk -i inplace) at the same site. No new path fragment — only the editor verb is widened.Related Issue
Sibling follow-up to 4e9d886 / #14639 (no separate issue).
Type of Change
Changes Made
tools/approval.py: two newDANGEROUS_PATTERNSentries —perl -[..]iand(g)awk -i inplacetargeting_HERMES_CONFIG_PATH/_HERMES_ENV_PATH.tests/tools/test_approval.py: positive cases (perl -i/-pi/-i.bak,awk/gawk -i inplace,$HERMES_HOMEform) + no-regression negatives (perl --version, in-place edit of/tmp, read-onlyawk,catofconfig.yaml).How to Test
Regression guard verified both directions: with the prod hunk stashed, all 6 positive cases fail (
perl -i/-pi/-i.bak,awk/gawk -i inplace,$HERMES_HOME); restored, the full file passes 207/207.Checklist
Code
fix(scope):)tests/tools/test_approval.py)Documentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/Asedpairing — or N/A