Found by the workstream-B adversary pass's cross-guard parity probe (HIGH-5, the non-H-22 half) and independently confirmed by reading the source.
The gap
H-22's shell flank and H-19's gate-marker check each carry an interpreter leg. The three older protected-file guards carry none:
$ grep -c "python3?|node|perl|ruby|sh" core/pysrc/_hooklib.py
0
LOG_TRUNC_RE/LOG_DESTROY_RE (H-05, overrides.log), DECISIONS_* (H-11, decisions/ADRs) and CONTEXT_* (H-18, CONTEXT.md) match redirects and write verbs only. So an interpreter one-liner reaches all three:
| shape |
H-22 open-tasks.md |
H-05 overrides.log |
H-11 decisions/ADR |
H-18 CONTEXT.md |
python3 -c |
BLOCK |
ALLOW |
ALLOW |
ALLOW |
py -c |
BLOCK (as of #564 remediation) |
ALLOW |
ALLOW |
ALLOW |
pwsh -Command |
BLOCK (as of #564 remediation) |
ALLOW |
ALLOW |
ALLOW |
The H-22 column is current after the remediation commit on sprint/portable-release-and-protected-state; the other three are unchanged.
Scope note
This is pre-existing and structural — not a regression from #564. It was left out of that sprint's remediation deliberately, to avoid widening scope into three guards the sprint did not touch.
The fix is cheap
_bashguardlib._INTERP_TOKENS and _INTERP_INLINE_CODE already exist as shared constants (added in the #564 remediation). Adding one interp_re leg per guard, built from those, is the same edit three times.
Decide per guard whether the inline-code requirement applies: for H-22 it is load-bearing (a sanctioned helper is invoked as python3 helper.py <args> and matching the bare token blocked it). H-05/H-11/H-18 have no equivalent sanctioned interpreter caller, so they may want the broader token-only match H-19 keeps.
Refs #564, #237, #335.
Found by the workstream-B adversary pass's cross-guard parity probe (HIGH-5, the non-H-22 half) and independently confirmed by reading the source.
The gap
H-22's shell flank and H-19's gate-marker check each carry an interpreter leg. The three older protected-file guards carry none:
LOG_TRUNC_RE/LOG_DESTROY_RE(H-05,overrides.log),DECISIONS_*(H-11, decisions/ADRs) andCONTEXT_*(H-18,CONTEXT.md) match redirects and write verbs only. So an interpreter one-liner reaches all three:python3 -cpy -cpwsh -CommandThe H-22 column is current after the remediation commit on
sprint/portable-release-and-protected-state; the other three are unchanged.Scope note
This is pre-existing and structural — not a regression from #564. It was left out of that sprint's remediation deliberately, to avoid widening scope into three guards the sprint did not touch.
The fix is cheap
_bashguardlib._INTERP_TOKENSand_INTERP_INLINE_CODEalready exist as shared constants (added in the #564 remediation). Adding oneinterp_releg per guard, built from those, is the same edit three times.Decide per guard whether the inline-code requirement applies: for H-22 it is load-bearing (a sanctioned helper is invoked as
python3 helper.py <args>and matching the bare token blocked it). H-05/H-11/H-18 have no equivalent sanctioned interpreter caller, so they may want the broader token-only match H-19 keeps.Refs #564, #237, #335.