Two guarded-mode false-positives surfaced in real scan traces.
The reviewer blocked a boolean SQL injection probe
(`curl "…/login?username='+OR+'1'='1"`) for being an injection attempt at all,
though it is a read-only GET that changes nothing. The prompt said "allow only
non-destructive" but never established that in-scope offensive testing is the
tool's authorized purpose, so the model blocked on the technique. Rewrite the
guarded-mode guidance to judge by effect: in-scope injection probes, recon,
enumeration, and fuzzing pass, while destructive or persistent effects block —
with SQL spelled out (boolean/UNION/time-based read probes pass; DROP, DELETE,
INSERT, INTO OUTFILE, stacked statements, and command execution block).
Ambiguous evidence still fails closed, and every deterministic block, the
completeness gate, observe's passive-only rule, and scope enforcement are kept.
Separately the reviewer blocked a plain `curl` as "use of bash shell within a
curl command". The shell wrapper stamps `shell: bash` onto every exec_command
for execution, and the evidence packet passed that transport default straight
to the reviewer, which read it as the agent invoking a shell. Strip the
harness-injected transport keys (`shell`, `max_output_tokens`) from the packet's
original_arguments; the command itself is still parsed from `cmd`, so an
agent-authored `bash -c` payload is unaffected.
Note: the effect-based prompt also lets in-scope recon tools (nmap, subfinder,
ffuf, katana) through, which the old prompt blocked as "scanning" or "high
volume". That follows directly from judging by effect rather than technique.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Grouped browser verbs were classified by their verb alone. `tab` and `session`
sit in the passive set, so `tab new <url>` — documented as navigating — and
`session clear` earned a deterministic allow and executed unreviewed in guarded
mode and unblocked in observe, while `open <url>`, the same navigation, was
reviewed. Passivity is now decided from verb plus subcommand, and the packet
carries the result so observe mode stops maintaining a second copy of the rule
that could drift more permissive than guarded. The blocked-action list still
matches on the bare verb, so `auth login` keeps matching `auth`.
Interpreters were a seven-name allowlist, so `python3.12`, `/usr/bin/python3`,
`php`, and `deno` set no script path and produced a packet with no artifacts
that was still stamped complete — the exact shape the reviewer is told it may
allow. Recognize versioned and common interpreters so their sources are
actually collected, and fail closed when a command runs code that cannot be
resolved to an inspectable script.
`from pkg import payload` collected only the package initializer, because an
imported name was treated as an attribute and never as a submodule. Effectful
code in `pkg/payload.py` executed without appearing in the evidence.
Workspace staging runs twice per run and was not idempotent: the second pass
read the origin from `source_path`, which the first pass had already rewritten
to the copy. With the completion marker absent it cleared the destination and
then copied from that same emptied directory, silently handing the agent an
empty workspace. The origin is now read back from `original_source_path`.
Each fix is covered by a test that fails when the fix is reverted.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Introduce a pre-execution safety layer that reviews effectful agent actions
against compiled, frozen evidence before they run.
`--safety-mode guarded` allows non-destructive interaction after review;
`--safety-mode observe` permits passive target interaction only. `off` stays
the default, so existing runs are unchanged.
Deterministic rules decide what they can on their own: destructive commands,
code-loading environment overrides, blocked browser actions, and mutating
requests in observe mode are refused without a model call, and a small set of
read-only commands is allowed outright. Everything else compiles an evidence
packet — command, scope, script source and its local import closure, prior
tool-call evidence, and browser snapshot context — for a bounded reviewer that
may make one isolated inspection call. Incomplete evidence fails closed.
In safety modes, user-owned local directories are copied into the run
directory so the originals are never mounted writable, while `.git`,
`.agents`, and `.codex` inside the copy stay read-only.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>