Action Guard denies a script because a comment contains the word "kill"
Live dogfood FP, Jarvis box, 1 Aug 2026 10:30 UTC — hit while responding to a cron-watcher escalation, i.e. at the exact moment the blocked tool was the thing needed.
python3 /home/ubuntu/clawd/skills/cron-autofix/scripts/cron_autofix.py --dry-run
→ DENIED: recognised dangerous operation requires approval
[rule: stop-process-or-service; matched: "kill"] [stop-process-or-service]
There is no kill in that script. Every occurrence of the token is prose:
| line |
context |
| 23 |
# active runner, so it sits idle until the 60s pre-execution watchdog kills it. |
| 62 |
docstring: kill that agent mid-run. Only call when invoked from the main session/manually |
| 218 |
argparse help text: do NOT use from a scheduled cron run — it self-kills mid-restart |
Verified there is no executable call:
grep -nE '"(kill|pkill|systemctl)"|subprocess.*kill|os\.kill' cron_autofix.py
→ no matches
The invoked command is also --dry-run, which by contract mutates nothing.
Mechanism
This is fallout from the v4.47.17 fix that folds invoked script file contents into the scan (the script-file bypass, correctly closed). That change made file bodies command surface — but the scan treats the entire file as executable text, so comments, docstrings and CLI help strings are matched as if they were commands. The irony is sharp: lines 23/62/218 exist specifically to warn the reader not to kill things carelessly. Documenting the hazard is what triggers the block.
Note the compounding failure mode: bypassPermissions means no prompt can be raised, so the correct-by-design deny (#139 family) turns a false positive into a hard, unrecoverable denial for an unattended agent. A benign FP in an attended session is friction; here it removes the repair tool from the box during an incident.
Why this is worse than an ordinary FP
The blocked script is the cron repair tool. The sequence was: cron watcher escalates a failed job → run the repair tool → tool denied. Had the job been genuinely broken rather than a stale-history re-escalation, remediation would have been blocked by our own guard, on a box with no human awake to approve it. Availability of the recovery path is part of the security property, not separate from it.
Fix direction
- When scanning script file contents, strip comments and string literals before matching, per language (
# for shell/Python, // and /* */ for JS/TS, docstrings for Python). A token inside a comment is not command surface.
- Failing that (or as well): weight file-content matches lower than matches in the invoked command line itself — the command line is what actually executes; a file body is context.
- Regression fixture: a script whose only dangerous tokens are in comments/docstrings/argparse help must not gate.
cron_autofix.py is a good real-world fixture — I'll add it to the guard FP corpus (research/guard-fp-corpus-2026-07-31.json).
Family: #89 (over-gates read-only/benign ops), and the same shape as the closed #128 (quoted payload args scanned as command surface) — but a distinct mechanism, since that one was about argument quoting in the command string and this is about file bodies pulled in by the 4.47.17 scan.
Action Guard denies a script because a comment contains the word "kill"
Live dogfood FP, Jarvis box, 1 Aug 2026 10:30 UTC — hit while responding to a cron-watcher escalation, i.e. at the exact moment the blocked tool was the thing needed.
There is no kill in that script. Every occurrence of the token is prose:
# active runner, so it sits idle until the 60s pre-execution watchdog kills it.kill that agent mid-run. Only call when invoked from the main session/manuallydo NOT use from a scheduled cron run — it self-kills mid-restartVerified there is no executable call:
The invoked command is also
--dry-run, which by contract mutates nothing.Mechanism
This is fallout from the v4.47.17 fix that folds invoked script file contents into the scan (the script-file bypass, correctly closed). That change made file bodies command surface — but the scan treats the entire file as executable text, so comments, docstrings and CLI help strings are matched as if they were commands. The irony is sharp: lines 23/62/218 exist specifically to warn the reader not to kill things carelessly. Documenting the hazard is what triggers the block.
Note the compounding failure mode:
bypassPermissionsmeans no prompt can be raised, so the correct-by-design deny (#139 family) turns a false positive into a hard, unrecoverable denial for an unattended agent. A benign FP in an attended session is friction; here it removes the repair tool from the box during an incident.Why this is worse than an ordinary FP
The blocked script is the cron repair tool. The sequence was: cron watcher escalates a failed job → run the repair tool → tool denied. Had the job been genuinely broken rather than a stale-history re-escalation, remediation would have been blocked by our own guard, on a box with no human awake to approve it. Availability of the recovery path is part of the security property, not separate from it.
Fix direction
#for shell/Python,//and/* */for JS/TS, docstrings for Python). A token inside a comment is not command surface.cron_autofix.pyis a good real-world fixture — I'll add it to the guard FP corpus (research/guard-fp-corpus-2026-07-31.json).Family: #89 (over-gates read-only/benign ops), and the same shape as the closed #128 (quoted payload args scanned as command surface) — but a distinct mechanism, since that one was about argument quoting in the command string and this is about file bodies pulled in by the 4.47.17 scan.