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
{{ message }}
Repository navigation
Stop an Inherited timeout Bound From Reaching a Loop Under a Nested timeout #2055
gh-write-guard.py credits a timeout around an outer bash -c as the bound for a loop inside a nested timeout ... bash -c in that payload (bounded = (inherited_timeout and not backgrounded) or local). A nested timeout runs its child in a process group of its own, so the outer timeout reaches that child only when the outer shell execs the nested timeout. When the payload does not end with it, the outer timeout ends the outer shell and the nested one keeps running.
Allowed today, and not bounded:
timeout 900 bash -c "timeout -s 0 800 bash -c 'until [ -f x ]; do sleep 60; done'; true"
timeout 900 bash -c "timeout 0 bash -c 'until [ -f x ]; do sleep 60; done'; true"
A reviewer reproduced the escape with GNU coreutils 9.7 and bash 5.2 on a short sleep; touch payload. The file still appeared after the outer timeout fired. Without the trailing ; true, bash execs the nested command and the outer signal does reach it, so whether the shape escapes depends on the shell.
Origin
The inherited-bound logic predates #1634. The signal-0 form is a new way to reach it, found by the local strict review on feature/auto-1634 (handoff #2044), which judges nested timeouts written directly on one command line and leaves this payload path unchanged.
Done looks like
An inherited bound does not reach a loop that sits under a nested timeout inside the payload, or the README's requirement 7 declares the gap. A self-test row covers each shape above.
A further shape, raised by a local strict review on feature/auto-1634 (handoff #2072): with an outer -s KILL, the escape does not depend on the trailing ; true. SIGKILL cannot be forwarded, so even where bash execs the nested timeout, the outer one kills it and leaves the loop in its own process group running.
Declined per #2517, approved by the maintainer, under GOVERNANCE.md "Trust Boundaries and Hardening Effort": The guard backstops an agent's own mistakes, and this is a command shape built to defeat it rather than one an agent session writes, so a miss does not realistically occur. See #2517 for the per-issue reason.
Activity
ptr727 commentedon Oct 1, 2026
A further shape, raised by a local strict review on
feature/auto-1634(handoff #2072): with an outer-s KILL, the escape does not depend on the trailing; true. SIGKILL cannot be forwarded, so even where bash execs the nestedtimeout, the outer one kills it and leaves the loop in its own process group running.timeout -s KILL 10 bash -c "timeout -s 0 800 bash -c 'until [ -f x ]; do sleep 60; done'"Deny a Signal-0 timeout as a Wait Bound in the Guard (#2117)
ptr727 commentedon Oct 8, 2026
Declined per #2517, approved by the maintainer, under GOVERNANCE.md "Trust Boundaries and Hardening Effort": The guard backstops an agent's own mistakes, and this is a command shape built to defeat it rather than one an agent session writes, so a miss does not realistically occur. See #2517 for the per-issue reason.