You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
yaml.py's cleanup rule is None. GitLab's after_script: is correctly excluded (already lands in func_start as an executable-logic anchor, confirmed by existing test coverage — no change needed there; a dedicated cleanup rule over it would double-count, same rejection shape as jcl's DISP=(...,DELETE) in #2610). But ordinary shell-level resource teardown embedded in run:/script: content — rm -rf <non-root-path>, docker rm/docker stop, docker-compose down/docker compose down, bare kill <pid> — matches no current rule: high_risk_execution's rm -rf is deliberately root-only (asserted in test_yaml_strict.py L63/193), io only catches install verbs, panics_and_aborts's kill only catches the signal-numbered form. yaml's own philosophy (per corpus notes) is that shell embedded in run:/script: counts like code (branch/io/high_risk_execution all reach into it), so teardown verbs there being invisible is an inconsistency, not a design choice.
Fix shape (illustrative): re.compile(r"\brm[ \t]+-rf?[ \t]+(?!/(?:[ \t]|$))\S{1,200}\b|\bdocker(?:-compose)?[ \t]+(?:rm|stop|down)\b|\bkill[ \t]+(?!-[0-9])\S{1,64}\b", re.I) — needs ReDoS/boundary review and overlap re-check against panics_and_aborts/high_risk_execution before landing.
Found by the #1096/#2560 rosetta n/a review sweep.
Already shipped — closing as done. The rule landed in #2681 ("Rosetta batch 3 wave 2 — doc-comment pairing, rule over-claims, three None rules"), which only listed closes #2672, so this stayed open.
yaml.py's cleanup is no longer None, and the shipped shape is this issue's proposal with one improvement:
Two deltas from the illustrative shape here, both tightening it: the docker alternative also accepts the space formdocker compose down (the proposal only had docker-compose), and the rm -rf root guard is (?!/(?:[^A-Za-z]|$)) rather than (?!/(?:[ \t]|$)), so rm -rf / followed by anything non-alphabetic is still left to high_risk_execution instead of leaking into cleanup.
Verified end to end against engine main (538ef8a):
Overlap re-check, which this issue asked for, is settled in the rule's own comment: after_script: stays with func_start (no double-count), and the rule keys off the shell verb rather than the block keyword, so teardown inside run:/script: double-counts with branch/io exactly the way this language's documented philosophy already has shell-in-yaml behave. high_risk_execution's root-only rm -rf / and panics_and_aborts' signal-numbered kill -9 are both preserved — test_yaml_strict.py L63/193 still assert them, and the simple-case table pins run: rm -rf /tmp/build-cache positive against run: rm -rf / negative.
Corpus pairing: keyword-rosetta's c.yml plants run: 'rm -rf /tmp/build-artifact' and run: 'docker compose down'. verify_language.py yaml → PASS, 76 assertions across 4 files.
Band: the cleanup cell is yaml=2 against a corpus median of 2 — +0%, green. No new red cell manufactured.
122 yaml tests pass, including the ReDoS sweep.
Same caveat as #2646, and it matters more here because the alternation is broader: no real-world file in the golden master exercises this rule.language-crucible's yaml corpus is 8 Ansible task files with no CI workflow, compose file or teardown verb in them, so a regression in this alternation would not be caught by crucible-audit. Filed as squid-protocol/language-crucible#23.
Activity
fix(core-engine): Rosetta batch 3 wave 2 — doc-comment pairing, rule …
squid-protocol commentedon Sep 4, 2026
Already shipped — closing as done. The rule landed in #2681 ("Rosetta batch 3 wave 2 — doc-comment pairing, rule over-claims, three None rules"), which only listed
closes #2672, so this stayed open.yaml.py'scleanupis no longerNone, and the shipped shape is this issue's proposal with one improvement:Two deltas from the illustrative shape here, both tightening it: the docker alternative also accepts the space form
docker compose down(the proposal only haddocker-compose), and therm -rfroot guard is(?!/(?:[^A-Za-z]|$))rather than(?!/(?:[ \t]|$)), sorm -rf /followed by anything non-alphabetic is still left tohigh_risk_executioninstead of leaking into cleanup.Verified end to end against engine
main(538ef8a):after_script:stays withfunc_start(no double-count), and the rule keys off the shell verb rather than the block keyword, so teardown insiderun:/script:double-counts withbranch/ioexactly the way this language's documented philosophy already has shell-in-yaml behave.high_risk_execution's root-onlyrm -rf /andpanics_and_aborts' signal-numberedkill -9are both preserved —test_yaml_strict.pyL63/193 still assert them, and the simple-case table pinsrun: rm -rf /tmp/build-cachepositive againstrun: rm -rf /negative.keyword-rosetta'sc.ymlplantsrun: 'rm -rf /tmp/build-artifact'andrun: 'docker compose down'.verify_language.py yaml→ PASS, 76 assertions across 4 files.cleanupcell is yaml=2 against a corpus median of 2 — +0%, green. No new red cell manufactured.Same caveat as #2646, and it matters more here because the alternation is broader: no real-world file in the golden master exercises this rule.
language-crucible's yaml corpus is 8 Ansible task files with no CI workflow, compose file or teardown verb in them, so a regression in this alternation would not be caught bycrucible-audit. Filed as squid-protocol/language-crucible#23.