Skip to content

fix(guardrails): block-hook-bypass producer detection misses three inline-write forms (one a documented accepted residual) #2217

Description

@kyle-sexton

Three inline-write forms reach a real file through block-hook-bypass.sh without matching any
detector. All three sit in the guard's own declared threat model (inline interpreter code, and a
producer whose stdout is redirected into a file), so they are gaps in something already modeled
rather than new scope. One of them is a documented accepted residual, not an oversight — see its
row.

The guard is explicitly "a speed bump … not a boundary", so none of these is critical. What makes
them worth one issue is that the interpreter arm interacts: widening the interpreter pattern touches
the same regex that #1601 and #2148 report as over-blocking, so all of it wants one sitting.

Rows

  • I7 C-H1plugins/guardrails/hooks/block-hook-bypass.sh:670 — the Bash-lane interpreter
    detector requires the literal python3, so python -c, py -c and python3.11 -c all pass. The
    same floor exists in the PowerShell lane's ps::might_write_via_python3 (invoked at :638).
  • I7 C-H3plugins/guardrails/hooks/block-hook-bypass.sh (strip_literals /
    normalize_segments) — a producer whose quoted content spans a physical newline is split from
    its own redirect: the strip carries the open quote span across lines but re-emits the newline,
    normalize_segments splits on \n, and producer_redirect_bypass requires producer and redirect
    in one segment.
  • I8 G1plugins/guardrails/hooks/block-hook-bypass.sh:670-673, residual documented at
    :635-636 — a stdin heredoc (python3 - <<'PY' … PY, no -c) is uncovered. This is a
    documented accepted residual, not an unrecognized gap.
    File/treat it as reopening an accepted
    residual on new reachability evidence
    : a session hit it while trying to comply with the guard's
    own remediation. A fix that lands here must update the acceptance comment, not contradict it.

Evidence

C-H1, reproduced at HEAD (payloads built with jq -n --arg, piped to the hook; rc=2 blocked,
rc=0 allowed):

rc=2 :: python3 -c "open(\"f\",\"w\").write(\"x\")"
rc=0 :: python -c "open(\"f\",\"w\").write(\"x\")"
rc=0 :: py -c "open(\"f\",\"w\").write(\"x\")"
rc=0 :: python3.11 -c "open(\"f\",\"w\").write(\"x\")"
rc=2 :: echo "*" > .gitignore          # control: the guard is live

block-hook-bypass.sh:670:

if [[ "$EXEC_LC" =~ (^|[[:space:];|&()/\\]+)python3(\.exe)?[[:space:]]+-c ]] &&

Sharpening datum: the guard's own scope note advertises the uncovered spelling as its example.
block-hook-bypass.sh:586-589 — "known shell file-write forms plus recognized inline interpreter
code (e.g. python -c)". The note names the one spelling the regex does not match.

C-H3, reproduced at HEAD:

cmd = $'printf \'a\nb\n\' > notes.md'   → rc=0  (allowed)
cmd = 'printf "a\nb\n" > notes.md'      → rc=2  (blocked)

The discriminator is a physical newline inside the quote span. Mechanism note for whoever fixes
it: emitting a space rather than a newline when a quote span is carried open across a line boundary
is safe, because the span's content is already dropped.

G1, at HEAD block-hook-bypass.sh:670-673 — the detector requires a literal -c; a
python3 - <<PY invocation has none, and neither cat_redirect_bypass nor
producer_redirect_bypass covers it. The acceptance is stated at :635-636:

  # `python3 … -c` + a write indicator in prose, a line/block comment, or a quoted
  # string now blocks; here-string mentions stay inert (blanked first, like the git
  # lane). ACCEPTED RESIDUAL: a stdin heredoc (`python3 - <<PY … PY`, no `-c`) is
  # uncovered here, as it is today.

Adjacent, not duplicate

Provenance

Severity: MED (cluster max — C-H1 MED, C-H3 LOW, G1 MED)
Provenance: mixed. C-H1 and C-H3 are AUDITOR_VERIFIED and were independently reproduced at HEAD
by the validation pass. G1 is SELF_REPORTED — it has not had an independent auditor pass; only
its code anchor was confirmed at HEAD.
Origin: handoff-inbox items 2026-08-10-plugin-quality-audit-four-components (C-H1, C-H3) and
20260811-021645-routed audit-pass report-path item (G1).
Ledger: .work/handoff-inbox-batch-4/ledgers/I7-four-components-023241Z.md §§ C-H1, C-H3 and
.work/handoff-inbox-batch-4/ledgers/I8-audit-pass-report-path.md § G1.
Verified against repo HEAD 685dd381.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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