feat(shell): argv + safe-subset engine, increment 1 (#34)#38
Merged
Conversation
WHAT: Replace the fail-closed shell stub with the argv + safe-subset engine (ADR 0005 D3). New parse.rs is the exec-funnel classifier: a quote-aware tokenizer that resolves a cmd string to a single command's argv, refusing dynamic constructs by design ($(...), backticks, subshells = Dynamic) and the not-yet-implemented operators (|, &&, ||, ;, <, >, globs, $VAR = Unsupported), distinct from Malformed. shell_tool.rs now accepts program+args or cmd, checks the exec/cwd leash, spawns directly (std::process in spawn_blocking) with capture + timeout, and returns structured denied envelopes; sandbox_kind is reported honestly (None — L2 advisory until L3, ADR 0005 D1). WHY: Per ADR 0005 the boundary is L3 and the engine is L2 convenience. This un-stubs a usable, honestly-advisory confined shell without the brush fork or upstream dependency, and structurally excludes the dynamic attack surface. Increment 1 = single command; pipelines/redirects/&&/globs follow (#34). brush-bridle-core stays the deferred reversible engine (#20). TEST: 26 crate tests incl. the security keystones — quoted metacharacter is a literal arg (echo "a|b" prints a|b), command substitution is refused and never runs, a refused pipeline means the downstream rm never executes. just check green (fmt + clippy all-features & no-default-features + workspace tests). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HMGPEApE4XfwgMhgFbRn6c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements increment 1 of #34 (ADR 0005 D3): replaces the fail-closed shell stub with the argv + safe-subset engine.
agent-bridleis the exec funnel — it parses the request itself, checks the leash, and spawns directly. L2 convenience; the L3 boundary stays deferred (#35), so runs are honestly advisory (sandbox_kind: none, ADR 0005 D1).What
parse.rs— the safe-subset classifier: quote-aware tokenizer → a single command's argv. Refuses$(...)/backticks/subshells by design (Dynamic); refuses|,&&,||,;,<,>, globs,$VARasUnsupported(later increments);Malformedfor bad input.shell_tool.rs—program+argsorcmd;exec/cwdleash checks; direct spawn (std::process in spawn_blocking) with capture + timeout; structureddeniedenvelopes.lib.rs/Cargo.toml— de-stubbed; documented as the engine; brush kept as the deferred reversible engine (brush-bridle-core: optional full-bash shell engine (deferred, reversible — not the path to a usable shell) #20).Scope (this increment)
Single command with quoted args. Pipelines / redirections /
&&/ globbing follow as separate increments on #34.Test plan
just checkgreen (fmt + clippy all-features & no-default-features + workspace tests). Security keystones covered:echo "a|b"is a literal arg;$(...)is refused and never runs; a refused pipeline means the downstreamrmnever executes; out-of-scope exec → structured denial; MCP boundary surfaces denials in-band.Part of #34.
🤖 Generated with Claude Code