Skip to content

fix(guardrails): block-hook-bypass false-positives a print-only python3 -c, pushing users to the opaque form #2148

Description

@kyle-sexton

Filed by AI. Hit independently by two sessions today, and it is a false block that pushes the user
toward the less inspectable form — which makes it worse than an ordinary nuisance.

The false positive

plugins/guardrails/hooks/block-hook-bypass.sh rejects an inline python3 -c that performs no file
write at all:

BLOCKED: python3 -c file write bypasses Write/Edit hooks

The snippet in question only called print(). No redirect, no open(..., 'w'), no file write of any
kind.

Why this is worse than a nuisance

The guard exists so that file writes go through Write/Edit and their hooks. The observed workaround —
taken by the session that hit it — was to move the snippet into a script file and run that
instead
. That is strictly worse for the guard's own purpose:

  • An inline python3 -c is fully visible in the command string the hook inspects.
  • A script file is opaque to it — the hook sees python3 /tmp/thing.py and cannot see what the
    program does. The guard's own scope note says as much: writes inside an invoked script file are
    not seen.

So the block moved the operation from a form the guard can read to one it cannot. A guard that
blocks correct usage teaches people to route around it
, and here the route around is the exact blind
spot the guard is trying to cover.

This is the same dynamic documented in #2139, where the guarded thread-resolution wrapper is bypassed
by a raw mutation in 49 of 54 transcripts.

Scope note

I hit the sibling forms of this guard several times today and those blocks were correct — an
echo >file and a cat >file really were file-write workarounds, and being pushed to Write/Edit was
the right outcome. So this is a matcher precision problem on the python3 -c arm specifically, not
an argument against the guard.

What would close it

  • The python3 -c arm distinguishes a program that writes from one that does not, or narrows to
    forms that plausibly write (open(, >/>> redirects, pathlib, shutil, os.replace,
    subprocess with a redirect) rather than firing on the -c form itself.
  • Or, if precise detection inside arbitrary Python is judged infeasible — a defensible conclusion —
    then the message should say so and point at the sanctioned route, rather than asserting a file
    write that did not occur. A block whose stated reason is factually wrong for the command in hand
    is what makes a user reach for the opaque workaround instead of the intended one.

Acceptance

  • A print-only python3 -c is allowed.
  • A genuinely write-performing python3 -c is still blocked — with a control proving the case
    discriminates, i.e. it fails against the fixed matcher if the write detection is removed.
  • Neither assertion passes for the wrong reason: verify the fixture actually reaches the python3 -c
    arm rather than exiting earlier, since a guard that never ran looks identical to a guard that
    allowed.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions