fix(sandbox): preserve argv value boundaries - #713
Conversation
|
Tick the box to add this pull request to the merge queue (same as
|
XuPeng-SH
left a comment
There was a problem hiding this comment.
Deep review of ed0a3ff against its moi-dev base 2de0e7c.
Requesting changes for one confirmed P1 regression: GNU xargs --show-limits is not a no-dispatch mode. Returning Safe at that flag prevents the resolver from inspecting a child command that xargs will execute.
Independent reproduction:
- GNU findutils 4.9.0:
printf 'data\n' | xargs --show-limits printf 'REVIEW713_CHILD_RAN:%s\n'prints the limits and thenREVIEW713_CHILD_RAN:data. - Compiled the actual base and head bash_ast modules with the locked tree-sitter 0.24.7 / tree-sitter-bash 0.23.3 dependencies and the repository's CommandRisk enum.
- For
xargs --show-limits truncate -s 0 important.db, the base returns[DestructiveCommand("truncate")]; this head returns[]. The same regression occurs with --no-run-if-empty after --show-limits; nonempty input still permits execution. - A benign printf child remains safe on both versions. The --help and --version controls correctly become safe on this head.
Only the harmless printf command was executed. Destructive command examples were passed as strings to the analyzer, never run. I traced the production path from analyze_command_risks_in_workspace into execute_bash validation: destructive-command rejection depends on this classification. This is a regression in that check, not a claim that OS isolation or every independent permission layer is bypassed.
The central single-argv consumer is otherwise a sensible improvement: the changed shell-option, launcher-option, and leading-operand paths reuse the existing may_split model; quoted scalar controls remain supported. The optional inline-only --eof/--replace distinction also preserves the intended child boundary. I reviewed both changed files and found no other independently substantiated blocker.
Validation: all 11 existing tests in the actual bash_ast module passed in an isolated Cargo harness, and git diff --check passed. I did not independently run the full astra-sandbox/astra-tools suites or workspace Clippy. The new terminal-mode tests cover --help and --version but omit --show-limits; add a rejecting analyzer/public-validator regression for a destructive child and a harmless real-xargs dispatch check before treating an option as terminal.
What type of PR is this?
Which issue(s) this PR fixes
N/A — synchronizes the latest argv-boundary corrections from
mainPR #697 aftermoi-devPR #711 merged.What this PR does / why we need it
The AST resolver advanced across some source words without proving they remain one runtime argv entry, and several GNU
xargs/findexecution semantics were modeled incorrectly.This change:
xargsvalue-bearing options;xargs --eof[=END],--replace[=R], and--max-lines[=MAX-LINES]as optional inline-value forms;xargs --show-limitsas nonterminal and continues resolving its child; only--helpand--versionterminate dispatch;findword that could become a predicate even when quoted, unless a literal./,../, or/prefix proves it is a path;Architecture and complexity delta
astra-sandboxBash AST executable resolver.xargs/finddispatch resolution, and publicexecute_bashvalidation.Production wiring and verification
execute_bashvalidation.xargsvalues, dynamic leading operands, GNUxargsoptional-value and nonterminal modes, quoted dynamicfindpredicate injection, benign proven-path and child controls, and terminal modes.Verification:
cargo fmt --check -- crates/astra-sandbox/src/bash_ast.rs crates/astra-tools/src/shell_ops.rscargo test -p astra-sandbox --lib— 153 passedcargo test -p astra-tools validate_execute_bash --lib— 12 passedcargo clippy -p astra-sandbox -p astra-tools --all-targets -- -D warningsxargs --show-limits, bare--max-lines, and quoted dynamicfind -printprobes so the registry is checked against real utility dispatch semantics.