v1.2.0: guard allows computation-only inline one-liners; blocks --eval/--input-type, child_process, string-keyed access, stdin-piped scripts, deno/bun/php

This commit is contained in:
Agent committed 2026-10-11 00:54:18 +00:00
1 parent 583aa9a10b
commit bcb7468686
3 files changed
+199 -2

No files matched your search

+10 -1
View File
@@ -77,7 +77,8 @@ A `tools/pre-execute` listener makes the agent use these tools instead of workin
| Denied | Use instead |
| --- | --- |
| `sed -i`, `perl -i`, `ed`/`ex`, `tee`, `>`/`>>` into files, heredocs, `truncate`/`dd`, `python -c`/`node -e`… | `edit` (hashline) |
| `sed -i`, `perl -i`, `ed`/`ex`, `tee`, `>`/`>>` into files, heredocs, `truncate`/`dd` | `edit` (hashline) |
| Inline scripts that can touch files, processes or the network (`node -e "require('fs')…"`, `node --input-type=module --eval "import …"`, `python3 -c "open(…)"`, `ruby -e "File.write…"`, `deno eval`, `bun -e`, `php -r`…), or scripts piped in through stdin (`… \| node`, `node - < f`) | `read`/`grep`/`edit` |
| `cat`/`head`/`tail`/`less`/`bat`/`nl FILE`, `sed -n`, `awk` | `read` (paged) |
| `grep`/`rg`/`ag`/`ack` over files | `grep` (paged, tagged) |
| `find`/`fd`/`locate`, `ls -R` | `glob` |
@@ -87,6 +88,14 @@ What stays allowed:
- Text inside quotes is ignored (`git commit -m "fix > bug"`).
- Redirection to `/dev/null` is fine.
- Filters on piped output keep working (`npm test 2>&1 | tail -5`, `ps aux | grep node`).
- Computation-only one-liners: `node -e "console.log(1+1)"`, `node -p "2**10"`, `python3 -c "print(sum(range(9)))"`, `ruby -e 'puts 1+1'`. Running a file is a normal command (`node --test test/`, `node build.mjs`).
How inline scripts are judged: the guard works out which interpreter runs (also through `env`, `sudo` and absolute paths) and pulls out its program from `-e`/`-p`/`--eval`/`--print`/`--eval=`/`-c`/`-r`/`eval`. The program is allowed only if it contains **none** of the identifiers that start any I/O path, for example:
- JavaScript: `require`, `import`, `process`, `globalThis`, `eval`, `Function`, `constructor`, `fetch`, `Deno`, `Bun`, or bracket access with a string (`x['y']`);
- Python: `import`, `__import__`, `open`, `os`, `subprocess`, dunder attributes;
- Ruby/Perl: `File`, `IO`, `system`, `open`, backticks.
Banning the identifiers that start an I/O path covers obfuscation too: `fs['write'+'File']` still needs `require` or `import` to get `fs`. A program the guard can't read (stdin, `-`) is denied.
If the guard can't check whether a path exists, `write` is denied rather than allowed (it fails closed).