Skip to content

[CI mirror] cap-hook-upstream — early-warning for upstream #1184#3

Open
hartsock wants to merge 3 commits into
ci-base-mainfrom
cap-hook-upstream
Open

[CI mirror] cap-hook-upstream — early-warning for upstream #1184#3
hartsock wants to merge 3 commits into
ci-base-mainfrom
cap-hook-upstream

Conversation

@hartsock

Copy link
Copy Markdown
Owner

Not for merging. This fork-only PR exists purely to run the upstream ci.yaml job suite (build, test, check, check-deps, check-schemas, analyze-public-api, bash-completion-tests, os-tests) against the cap-hook-upstream branch ahead of time, so any breakage is caught before it reaches the maintainer on reubeno#1184.

🤖 Generated with Claude Code

@hartsock hartsock closed this Jun 13, 2026
@hartsock hartsock reopened this Jun 13, 2026
@hartsock hartsock closed this Jun 14, 2026
@hartsock hartsock reopened this Jun 14, 2026
@hartsock
hartsock force-pushed the cap-hook-upstream branch 7 times, most recently from fde15cc to 03a6eb6 Compare June 20, 2026 03:24
@hartsock
hartsock force-pushed the cap-hook-upstream branch 5 times, most recently from 2cde127 to e59257b Compare June 29, 2026 03:24
Embedders of brush-core could not confine command execution in-process.
The path-separator dispatch branch in commands.rs (e.g. `/bin/rm`, `./x`)
bypasses both the PATH search and the builtin table, so any name- or
PATH-based gate an embedder might apply is trivially defeated. ShellExtensions
carried only ErrorFormatter (presentation), with no authority seam.

Add an optional CommandInterceptor component to ShellExtensions, mirroring the
existing ErrorFormatter pattern, with two default-allow hooks:

  - before_exec(program, args) -> ExecDecision, called at the single external-
    spawn funnel (execute_external_command), so BOTH dispatch branches —
    including the path-separator branch — are covered.
  - before_open(path, write) -> OpenDecision, called in Shell::open_file, the
    single choke point for all filesystem-path opens (redirections + source/.).

On Deny, execs fail with a new ErrorKind::ExecDenied (exit code 126) and opens
fail with a PermissionDenied io::Error surfaced by the existing redirection /
source error wrapping. Neither panics nor silently skips.

The change is purely additive: ShellExtensionsImpl gains a second type param
that defaults to DefaultCommandInterceptor (allow-all), so DefaultShellExtensions
and all existing call sites are source-compatible and byte-for-byte identical in
behavior. The full existing suite (including the YAML bash-compat and redirection
cases) passes unchanged.

Motivation: agent-bridle, an object-capability confinement layer for LLM coding
agents. The agent harness is a confused deputy (full ambient authority + untrusted
instructions); the ocap remedy enforces attenuated capabilities at the point of
use. An embedded brush is the script-execution surface, so enforcement must live
inside the shell before the spawn/open — and must cover the path-separator bypass.

Includes brush-core/tests/command_interceptor_tests.rs, which proves a custom
interceptor denies `rm`, denies the absolute-path `/bin/rm` (the load-bearing
path-separator case), allows `/bin/true`, denies writes outside an allowed dir,
and allows read-only source opens. Upstream contribution drafted at
docs/upstream/reubeno-brush-exec-open-hook.md (not yet filed).

Assisted-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@hartsock
hartsock force-pushed the cap-hook-upstream branch from e59257b to fc1de3a Compare July 6, 2026 03:24
Comment thread .github/workflows/cd.yaml

- name: "Install Rust toolchain"
uses: actions-rust-lang/setup-rust-toolchain@46268bd060767258de96ed93c1251119784f2ab6 # v1.16.1
uses: actions-rust-lang/setup-rust-toolchain@166cdcfd11aee3cb47222f9ddb555ce30ddb9659 # v1.17.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants