feat: #297 — --disable-ocap/--yolo interim exec escape hatch#298
Merged
Conversation
a5eb976 to
d52e440
Compare
Operator-reported: on stub-shell builds (the only crates.io-publishable
configuration) agent-bridle's shell tool fails closed on every command,
so run_command cannot do agentic coding at all without the brush
CommandInterceptor patch underneath. This adds the explicit, loud,
interim bypass the issue specifies:
- newt-core: `ocap_disabled()` (NEWT_DISABLE_OCAP=1, exact-value,
fail-closed read; env-only — deliberately NO config key) and a
run_command bypass that executes on the plain host shell (bash -c,
sh fallback; cmd /C on Windows) with the SAME venv/PATH prefix and
an envelope structurally identical to the bridle one
({exit_code, stdout, stderr, sandbox_kind}, denied/denials omitted),
so envelope_denied/shell_envelope_output and the loop need no changes.
- Scope: exec only. web_fetch is NOT bypassed — determined empirically
that the stub-shell branch stubs only the shell tool; the web tool at
agent-bridle rev 2129c91 is the real leash-enforcing implementation.
fs tools keep the newt-native workspace fence: yolo is unconfined
exec, fenced fs — never authority-off.
- Precedence: --disable-ocap > --prompt-for-permissions for exec
(nothing is denied, so the #263 gate is structurally unreachable);
fs prompting unaffected.
- newt-cli: --disable-ocap with visible alias --yolo (global), threads
via NEWT_DISABLE_OCAP=1 exactly like #289's --prompt-for-permissions.
- newt-tui: unmissable session-start banner + ONE ocap-disabled record
({decision: "ocap-disabled", scope: "session", kind: exec, target: *})
in the #263 permission log so the audit trail shows the session ran open.
- Everything is doc-marked INTERIM, referencing #297, agent-bridle#20,
and reubeno/brush#1184 — removed (or demoted to a debug flag) when
brush upstreams CommandInterceptor.
13 new tests: flag-off pinned bit-for-bit (stub error verbatim), yolo
runs the denied command on the host shell with envelope parity, banner,
log record round-trip, fs fence enforced under yolo, precedence over
prompt mode (exec never prompts, fs still does), env-var equivalence,
exact-value flag parsing, --yolo alias. Coverage 90.10% (floor 80%).
Refs #297
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
d52e440 to
88554f1
Compare
hartsock
added a commit
that referenced
this pull request
Jun 27, 2026
Operator-reported: on stub-shell builds (the only crates.io-publishable
configuration) agent-bridle's shell tool fails closed on every command,
so run_command cannot do agentic coding at all without the brush
CommandInterceptor patch underneath. This adds the explicit, loud,
interim bypass the issue specifies:
- newt-core: `ocap_disabled()` (NEWT_DISABLE_OCAP=1, exact-value,
fail-closed read; env-only — deliberately NO config key) and a
run_command bypass that executes on the plain host shell (bash -c,
sh fallback; cmd /C on Windows) with the SAME venv/PATH prefix and
an envelope structurally identical to the bridle one
({exit_code, stdout, stderr, sandbox_kind}, denied/denials omitted),
so envelope_denied/shell_envelope_output and the loop need no changes.
- Scope: exec only. web_fetch is NOT bypassed — determined empirically
that the stub-shell branch stubs only the shell tool; the web tool at
agent-bridle rev 2129c91 is the real leash-enforcing implementation.
fs tools keep the newt-native workspace fence: yolo is unconfined
exec, fenced fs — never authority-off.
- Precedence: --disable-ocap > --prompt-for-permissions for exec
(nothing is denied, so the #263 gate is structurally unreachable);
fs prompting unaffected.
- newt-cli: --disable-ocap with visible alias --yolo (global), threads
via NEWT_DISABLE_OCAP=1 exactly like #289's --prompt-for-permissions.
- newt-tui: unmissable session-start banner + ONE ocap-disabled record
({decision: "ocap-disabled", scope: "session", kind: exec, target: *})
in the #263 permission log so the audit trail shows the session ran open.
- Everything is doc-marked INTERIM, referencing #297, agent-bridle#20,
and reubeno/brush#1184 — removed (or demoted to a debug flag) when
brush upstreams CommandInterceptor.
13 new tests: flag-off pinned bit-for-bit (stub error verbatim), yolo
runs the denied command on the host shell with envelope parity, banner,
log record round-trip, fs fence enforced under yolo, precedence over
prompt mode (exec never prompts, fs still does), env-var equivalence,
exact-value flag parsing, --yolo alias. Coverage 90.10% (floor 80%).
Refs #297
Co-authored-by: hartsock <hartsock@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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.
Ref #297.
What this PR does
The explicit, loud, interim bypass for the stub-shell fail-closed exec problem (#297):
--disable-ocap(alias--yolo) +NEWT_DISABLE_OCAP=1— global CLI flag threaded via env exactly like feat: #263 — --prompt-for-permissions (prompted ocap grants with session record) #289's--prompt-for-permissions. Deliberately no config-file key: the bypass must be asserted per invocation and can never silently persist. The env read is fail-closed: only the exact value1asserts it.newt-core/src/agentic/tools.rs): when asserted,run_commandskipsagent_bridle::registry().dispatch("shell", …)and runs the command on the plain host shell —bash -cwithsh -cfallback (cmd /Con Windows) — with the samevenv_cmd_prefix()applied, and wraps the result in an envelope structurally identical to the bridle one:{ exit_code, stdout, stderr, sandbox_kind: "none" }withdenied/denialsomitted exactly as the bridle envelope omits them when nothing was denied.envelope_denied/shell_envelope_outputand the loop's truncation/denial/exit-code handling needed zero changes.feat/stub-shellbranch (locked rev2129c91) stubs only the shell tool (ShellTool::invokeunconditionally returns the "temporarily unavailable… feat(core): add CommandInterceptor exec/open hook to ShellExtensions reubeno/brush#1184" error);agent-bridle-tool-webon the same rev is the full real implementation (net allowlist, SSRF screen, redirect re-check, IP pin, actual fetch). The existingweb_fetchleash-denial tests passing on stub CI corroborate this. Scoped to actual breakage, per the issue.read_file/write_file/edit_file/list_dirkeep the newt-native workspace fence under yolo — unconfined exec, fenced fs, never a global authority-off switch.⚠ ocap DISABLED (--disable-ocap): commands run unconfined on the host shell …) plus ONE record in the feat(permissions): --prompt-for-permissions — interactive grant on capability denial, with a session-recorded decision log #263 permission log:{ tool: "run_command", kind: "exec", target: "*", decision: "ocap-disabled", scope: "session" }.--disable-ocap>--prompt-for-permissionsfor exec — nothing is denied, so the feat(permissions): --prompt-for-permissions — interactive grant on capability denial, with a session-recorded decision log #263 gate is structurally unreachable forrun_command; fs prompting unaffected (tested).CommandInterceptor.Test plan
13 new tests (8 newt-core, 4 newt-tui, 1 newt-cli), all env-mutating ones serialized behind async-aware locks with RAII env restore:
error: … reubeno/brush/pull/1184).echo yolo-ok→yolo-ok\n); empty output keeps the(exit N)shape.exit_code/stdout/stderr/sandbox_kindpresent,denied/denialsomitted,envelope_deniedreads false,shell_envelope_outputformats it identically.echo "$VIRTUAL_ENV"underNEWT_VENV).ocap-disabledrecord shape + jsonl round-trip.NEWT_DISABLE_OCAPexact-value semantics (1on;0/empty/true/yesoff) — the env-var-equivalence half (the flag just exports the var).--disable-ocapand--yoloalias parse (bare and explicitcode), off by default.Gates:
just checkgreen,just cov-cigreen at 90.10% (floor 80%),just shell-checkgreen (no patch-wiring changes).Out of scope
[patch.crates-io]block or any agent-bridle changes (tracked by agent-bridle#20 / its crates.io release).web_fetch— empirically not broken on stub builds (see finding above).run_command.🤖 Generated with Claude Code