[GH-ISSUE #2290] [Bug] Static CLI can remain alive after denied process inspection reports cleanup_incomplete #757

Closed
opened 2026-10-15 18:28:03 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @morluto on GitHub (Oct 12, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/2290

Observed behavior

While verifying #2218 in consolidated #2252 (head 35f0cdf1dd), a negative macOS sandbox run rejected the setuid /bin/ps process inspector with spawn EPERM. REA correctly emitted cleanup_incomplete with process-inspection uncertainty and retained local resources, but the public CLI remained alive after printing the error. One repeat was still alive more than eight minutes later and was stopped by the test supervisor. The configured source-analysis timeout was 10 seconds.

This is separate from the helper cache fix: the same compiler/SDK, private cache, inert application and static-analysis command succeeded when the policy narrowly allowed the read-only /bin/ps inspector. Fresh permitted cold/warm runs cleaned their temporary files. Denied process inspection is intentionally an unmet prerequisite; this issue concerns bounded CLI completion after the reported failure, not forcing ownership checks to succeed.

Reproduction

On macOS with an installed compatible Swift compiler and macOS SDK, create an inert directory containing package.json ({"name":"inert-analysis-fixture","main":"index.js"}) and index.js (export function greet(name) { return hello ${name}; }). Select an absolute compiler path, SDKROOT, caller module cache, HOME and TMPDIR within a dedicated test directory. Invoke:

node <rea>/scripts/rea.mjs analyze-javascript-application <fixture> \
  --artifact-format directory --max-heap-mb 256 \
  --analysis-timeout-ms 10000 --format json

Run under a macOS sandbox with this policy, substituting an absolute working directory:

(version 1)
(allow default)
(deny network*)
(deny file-write*)
(allow file-write* (subpath "<working-directory>"))
(allow file-write* (literal "/dev/null"))

/bin/ps is setuid on this host. The sandbox rejects its spawn. REA reports cleanup_incomplete with reason: "process table could not be inspected: spawn EPERM"; the CLI then remains alive. Adding the separate (allow process-exec (literal "/bin/ps") (with no-sandbox)) exception permits the successful control run, but intentionally weakens that policy for the read-only inspector and is not a general containment guarantee.

Expected behavior and limits

An actionable failure should complete within a bounded lifecycle while retaining honest cleanup uncertainty and source evidence. Do not signal processes with unresolved identity, discard retained ownership records, or bypass process inspection to make the command appear successful.

Observed on the current consolidation with Node 24.18.0/npm 11.16.0, installed Xcode Swift compiler and macOS SDK. This is two local negative runs and a successful control; no unmodified-main comparison or root-cause determination has been completed. It does not establish that #2252 introduced the lifecycle behavior. The target source was never executed. Temporary/output paths in this report are placeholders; no global developer settings were changed.

Originally created by @morluto on GitHub (Oct 12, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/2290 ### Observed behavior While verifying #2218 in consolidated #2252 (head 35f0cdf1dd8c0f65acbcbf3b9ed4983e3a180b44), a negative macOS sandbox run rejected the setuid `/bin/ps` process inspector with `spawn EPERM`. REA correctly emitted `cleanup_incomplete` with process-inspection uncertainty and retained local resources, but the public CLI remained alive after printing the error. One repeat was still alive more than eight minutes later and was stopped by the test supervisor. The configured source-analysis timeout was 10 seconds. This is separate from the helper cache fix: the same compiler/SDK, private cache, inert application and static-analysis command succeeded when the policy narrowly allowed the read-only `/bin/ps` inspector. Fresh permitted cold/warm runs cleaned their temporary files. Denied process inspection is intentionally an unmet prerequisite; this issue concerns bounded CLI completion after the reported failure, not forcing ownership checks to succeed. ### Reproduction On macOS with an installed compatible Swift compiler and macOS SDK, create an inert directory containing `package.json` (`{"name":"inert-analysis-fixture","main":"index.js"}`) and `index.js` (`export function greet(name) { return `hello ${name}`; }`). Select an absolute compiler path, SDKROOT, caller module cache, HOME and TMPDIR within a dedicated test directory. Invoke: ```sh node <rea>/scripts/rea.mjs analyze-javascript-application <fixture> \ --artifact-format directory --max-heap-mb 256 \ --analysis-timeout-ms 10000 --format json ``` Run under a macOS sandbox with this policy, substituting an absolute working directory: ```scheme (version 1) (allow default) (deny network*) (deny file-write*) (allow file-write* (subpath "<working-directory>")) (allow file-write* (literal "/dev/null")) ``` `/bin/ps` is setuid on this host. The sandbox rejects its spawn. REA reports `cleanup_incomplete` with `reason: "process table could not be inspected: spawn EPERM"`; the CLI then remains alive. Adding the separate `(allow process-exec (literal "/bin/ps") (with no-sandbox))` exception permits the successful control run, but intentionally weakens that policy for the read-only inspector and is not a general containment guarantee. ### Expected behavior and limits An actionable failure should complete within a bounded lifecycle while retaining honest cleanup uncertainty and source evidence. Do not signal processes with unresolved identity, discard retained ownership records, or bypass process inspection to make the command appear successful. Observed on the current consolidation with Node 24.18.0/npm 11.16.0, installed Xcode Swift compiler and macOS SDK. This is two local negative runs and a successful control; no unmodified-main comparison or root-cause determination has been completed. It does not establish that #2252 introduced the lifecycle behavior. The target source was never executed. Temporary/output paths in this report are placeholders; no global developer settings were changed.
bsakaguchi 2026-10-15 18:28:03 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#757
No description provided.