Skip to content

fix(exec): Windows child can spawn a grandchild before Job Object assignment #9

Description

@CMGS

Surfaced in the 2026-07-16 whole-repo audit. Windows-only; not verifiable on the macOS dev host, so filed rather than fixed blind.

Problem

agent/exec.go calls cmd.Start() then procCtl.AfterStart(cmd)AssignProcessToJobObject (agent/sysproc_windows.go). exec.Cmd.Start() creates the child running immediately — no CREATE_SUSPENDED — so between Start() returning and the Job Object assignment completing, the child can spawn a grandchild that never becomes a job member. That grandchild then survives JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE when the session ends via windowsProcessController.close().

This is the Windows analogue of the guarantee Linux gets from Setpgid + process-group kill (covered by TestServerExecBackgroundChildDoesNotPinSession), which has no Windows equivalent test.

Fix direction

Create the process with CREATE_SUSPENDED via a raw windows.CreateProcess (os/exec doesn't expose the primary thread handle needed to resume), assign to the Job Object, then ResumeThread. Alternatively, document the narrow race as accepted.

Acceptance

  • A Windows exec whose child immediately spawns a grandchild: ending the session kills both (Job Object membership established at creation, pre-resume).
  • A Windows-target test mirroring TestServerExecBackgroundChildDoesNotPinSession.
  • Verified on a Windows runner, not a mac-only green.

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