Skip to content

Stop an Inherited timeout Bound From Reaching a Loop Under a Nested timeout #2055

Closed as not planned

Description

@ptr727

Problem

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.

Activity

  1. added
    bugSomething isn't working
    pre-existingReview finding classed pre-existing per local-strict-review Disposing of Findings
    on Sep 29, 2026
  2. ptr727 commented on Oct 1, 2026

    @ptr727
    OwnerAuthor

    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.

    timeout -s KILL 10 bash -c "timeout -s 0 800 bash -c 'until [ -f x ]; do sleep 60; done'"
  3. ptr727 commented on Oct 8, 2026

    @ptr727
    OwnerAuthor

    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.

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

    bugSomething isn't workingpre-existingReview finding classed pre-existing per local-strict-review Disposing of Findings

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions