feat: lift shell read restrictions and page bash/read tool outputs to 200 lines
This commit is contained in:
1 parent
ee78e6d3a8
commit
de37af4b8c
7 files changed
+213
-32
No files matched your search
@@ -62,37 +62,33 @@ Every tagged `read`/`grep`/`edit` records a snapshot. When the file changed sinc
|
||||
|
||||
A tag that was never issued for that file (e.g. copied from another file) is rejected with a hint.
|
||||
|
||||
## Paging: read, grep and glob
|
||||
## Paging: read, grep, glob and bash
|
||||
|
||||
Like oh-my-pi, outputs are cut into pages so the model never pulls a whole file or huge search into context at once:
|
||||
- **`read`**: at most **200 lines** per call (`limit` above 200 is capped); the footer gives the `offset` to continue.
|
||||
Outputs are cut into pages so the model never pulls a whole file, huge search, or giant shell stream into context at once:
|
||||
- **`read`**: at most **200 lines** per call (`limit` above 200 is capped); the footer gives the `offset` to continue. The UI row indicates the line range being read (`Read lines A–B`).
|
||||
- **`grep`**: at most **200 matches** per call, grouped under `[PATH#TAG]` headers. Pass `offset` for the next page (`… call grep again with offset=200`).
|
||||
- **`glob`**: at most **200 paths** per call, with the same `offset` cursor.
|
||||
- **`bash`**: output is capped at **200 lines** per stream (`stdout` / `stderr`). The complete, uncut output is saved to a temporary file (`/tmp/omp-edit-output/...txt`), and the footer instructs the model how to continue reading with `read` (`read file_path="..." offset=201`).
|
||||
|
||||
Change the page size with `pageLines`.
|
||||
|
||||
## Guard rule
|
||||
|
||||
A `tools/pre-execute` listener makes the agent use these tools instead of working around them through the shell. Denied calls get a short reason that names the right tool.
|
||||
A `tools/pre-execute` listener ensures file modifications go through appropriate tools while lifting restrictions on reading files via shell. Writing through shell is blocked.
|
||||
|
||||
| Denied | Use instead |
|
||||
| --- | --- |
|
||||
| `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` |
|
||||
| Inline scripts that write files (`node -e "require('fs').writeFileSync…"`, `python3 -c "open(…,'w')"`, `ruby -e "File.write…"`, `awk` writes) | `edit` / `write` |
|
||||
| `find -delete`, `find -fprint` | `edit` / file tools |
|
||||
| `str_replace_editor`, `apply_patch` tools; `write` on an **existing** file | `edit` (`write` stays allowed for brand-new files) |
|
||||
|
||||
What stays allowed:
|
||||
- **Reading files and searching via shell:** `cat`, `head`, `tail`, `less`, `more`, `bat`, `nl`, `sed -n`, `grep`, `rg`, `ag`, `find`, `ls -R`, read-only `awk` are all permitted. Their output is automatically paged to 200 lines by the `bash` wrapper.
|
||||
- Text inside quotes is ignored (`git commit -m "fix > bug"`).
|
||||
- Redirection to `/dev/null` is fine.
|
||||
- Redirection to `/dev/null`, `/dev/stderr`, `/dev/stdout` 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;
|
||||
- Computation-only one-liners: `node -e "console.log(1+1)"`, `node -p "2**10"`, `python3 -c "print(sum(range(9)))"`.
|
||||
- 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.
|
||||
|
||||
Reference in new issue
Block a user