Skip to content

SessionEnd kills whatever pid broker.json names, without checking it is still a broker (pid reuse → SIGTERM to an unrelated process group) #743

Description

@demisx

Version: 1.0.6 · OS: macOS

scripts/session-lifecycle-hook.mjs handleSessionEnd loads broker.json for the session cwd and passes its pid to teardownBrokerSession, which calls terminateProcessTree(pid) (scripts/lib/broker-lifecycle.mjs, scripts/lib/process.mjs) with no check that the process is still an app-server-broker.mjs — no argv, start-time, or socket-ownership comparison. broker.json is only removed by a SessionEnd whose cwd matches, so entries whose broker died some other way (worktree removed, session killed, machine slept) stay behind indefinitely, and their pids get recycled.

Observed on 1.0.6, macOS, 16 days of uptime: 320 broker.json files under ~/.claude/plugins/data/codex-openai-codex/state/ (343 state dirs in total); 4 of them name a pid that is alive today and belongs to something else:

224-scope-backlog-skills-to-backlog-column-358be27031764eea/broker.json -> pid 73768 is now: Slack ShipIt
265-add-verification-must-be-able-to-fail-rule-c33891ccc7c234eb/broker.json -> pid 21722 is now: login
360-share-master-board-workflow-2cba6deeb0cafbd8/broker.json -> pid 60269 is now: Wispr Flow Helper
97-simplify-push-guard-refspec-config-782d049f8463288a/broker.json -> pid 2046 is now: WallpaperSonomaExtension

A session that ends in a cwd with one of those entries sends SIGTERM to that process group.

Related, already on file (linked rather than repeated): #380 (cwd-hash lookup misses brokers whose job cwd ≠ session cwd, which is how these entries go stale), #605 / #543 (brokers never self-terminate). #521 reports the same missing validation as an attacker-gated security issue on shared Linux hosts with a world-writable os.tmpdir(); this report is the accidental path to the same primitive — no attacker, no shared host, and it reproduces on macOS, which #521 explicitly excludes.

This report is only the identity check: before signalling broker.json's pid, confirm the process is still a broker — e.g. compare its argv against the recorded endpoint/pid-file, or the pid-file's own contents — and drop the entry instead of killing when it is not.

Repro: pick any stale broker.json whose pid is alive and is not a broker, run a session in that cwd, /quit; the unrelated process receives SIGTERM.

Activity

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions