Skip to content

Confined shell engine: argv + safe-subset executor (pipes/globs/&&/redirects; refuse dynamic constructs) #34

Description

@hartsock

Tracks ADR 0005 D3 — the default confined-shell engine for this pass (L3 is the boundary, L2 is convenience). No brush fork, no upstream dependency.

Why

The brush CommandInterceptor (L2) requires a fork crates.io won't let us publish and that waits on reubeno/brush#1184 (#20) — so today the shell is a fail-closed stub (ADR 0003). ADR 0005 decouples: ship a usable, honestly-advisory confined shell now where bridle is the exec funnel, and let L3 (#31) become the boundary.

Scope — implement directly (no shell interpreter)

  • Pipelines a | b — spawn N processes, wire stdout→stdin via OS pipes; check each argv0 against exec scope at the funnel.
  • Globs *.rs — expand with the glob crate against fs_read scope; refuse expansions that escape scope.
  • Sequencing/branching &&, ||, ; — exit-code logic over argv commands.
  • Redirections >, >>, <, 2>&1 — bridle opens the target (canonical fs_read/fs_write check, I6) and wires the fd.
  • Safe scalar expansion ($HOME-style env), quoting/word-splitting for argv parsing.
  • Reuse the shared leash plumbing: ToolContext, the Denial sink, the result envelope (sandbox_kind, I9).

Structurally refuse (least authority by construction — ADR 0001 "opaque ⇒ never cleared")

  • Command substitution $(...) / backticks; eval; process substitution <(...)/>(...); dynamic $VAR-as-command; functions; control flow with computed command names. Refused with a legible message (these are the undecidable interiors; they belong on the --yolo path, ADR 0003 / D5).

Notes

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions