galaxyproject / galaxyproject/loom
exec-guard bash classifier: more safe-allowlist commands read/exec outside the workspace
- Dominant language
- TypeScript
- Stars
- 14
- Forks
- 12
- Avg merge
- 6d 5h
- Merged PRs (30d)
- 17
Description
Follow-up to #224 / #250. While hardening the bash enumeration jail in #250, an adversarial review of `extensions/loom/exec-guard/bash-risk.ts` surfaced several *other* ways a safe-allowlisted bash command still reaches outside the workspace without prompting. #250 closes the bare `ls/find/stat/du/wc/file ` gap plus quote-stripping and `df`; these are separate and predate it. Listed roughly worst-first.
### 1. `git diff --no-index` dumps arbitrary external file content
`git diff`, `git show`, `git log` are auto-safe via `SAFE_PREFIXES`, but the classifier's `cmd` stays `git` (not in `PATH_READING`), so no path operands are collected and the command is allowed outright:
```
git diff --no-index /etc/passwd /etc/hosts # prints both files' full contents as a diff
git show HEAD:/etc/passwd # (within a repo) arbitrary blob read
git log /some/external/path
```
This is arbitrary file-content exfiltration through an auto-safe prefix -- strictly worse than the metadata leak #224 reported. Options: drop the `git` prefixes from the auto-safe set, or parse them conservatively (treat any non-flag operand as a read path, and reject `--no-index`).
### 2. `find`/`fd` `-exec`/`-x` is arbitrary execution classified as safe
`find` and `fd` are in `SAFE_COMMANDS`, and `-exec ... {} +` / `-x ...` contain no `SHELL_META`, so they classify `safe`:
```
find ~/.ssh -type f -exec cat {} + # dumps key contents; sensitiveReadPaths is empty (find isn't READ_LIKE)
fd -x cat ~/.ssh/id_rsa
```
These get at most a `read:escape` ask (not the credential-store hard-deny), and auto-allow outright if the target sits inside a configured workspace root. `-exec`/`-x` is really arbitrary command execution wearing a safe verb -- the guard should force any `find`/`fd` carrying `-exec`/`-execdir`/`-ok`/`-x`/`-X` to `unknown` (ask).
### 3. Unexpanded shell variables bypass the jail
`SHELL_META` catches `$(` and `${...}` but not bare `$VAR`, and the path resolver only expands `~`/home forms:
```
ls $PWD/.. # guard resolves literal "$PWD/.." under cwd (inside); shell reads the parent at runtime
cat $PWD/../.ssh/config # can walk out of the workspace AND past the credential-store hard-deny
```
The guard reasons over the literal string while the shell expands `$PWD`/`$HOME`/`$OLDPWD` at exec time. Either expand the common read-only vars before resolving, or treat a `$`-containing operand as untrusted (ask).
### 4. Attached path-valued options are dropped
The `!t.startsWith("-")` filter discards `--opt=value`, so options whose value is an external file slip through with no path collected:
```
grep --file=/etc/passwd needle . # reads patterns FROM /etc/passwd
rg --file=/etc/passwd needle .
wc --files0-from=/etc/passwd
du --files0-from=/etc/passwd
file --files-from=/etc/passwd
fd --ignore-file=/etc/passwd pattern .
```
Recognize the handful of path-valued long options and collect their `=`-attached (and space-separated) values into `readPaths`.
### Root cause
Most of the above trace to the same thing: the classifier uses a naive whitespace split + prefix match rather than a real shell lexer, and the safe-allowlist trusts a verb without fully accounting for its argument grammar. Worth considering a small conservative lexer, or a "if any operand looks unmodelled, fall to ask" backstop, instead of widening the allowlist case by case.
### Notes
- The policy floor ordering itself is sound: sensitive-read floor, then the workspace-jail `readPaths` loop, then the safe-allow -- so the fix for each of these is to make sure the relevant operand reaches `readPaths` (or to force the command to `unknown`), no `policy.ts` change required.
- All repros classify `safe` today on the #250 branch; verified by probing `classifyBash` directly.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start in extensions/loom/exec-guard/bash-risk.ts and inspect classifyBash, SAFE_PREFIXES, SAFE_COMMANDS, PATH_READING, and readPaths. Reproduce the listed commands with classifyBash directly, then verify that git path operands, find/fd execution flags, variable-containing operands, and attached path-valued options are no longer classified as safe. Confirm the existing policy.ts ordering needs no change.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- bash, git, typescript
- Domain
- cli, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100