[GH-ISSUE #2519] fix(verify-ghidra-dos): reports complete cleanup with unavailable process lineage #837

Closed
opened 2026-10-15 18:28:52 +00:00 by bsakaguchi · 1 comment
Owner

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

Summary

The DOS Ghidra verification command can report success and complete cleanup after its final process-lineage observation returns unavailable. This contradicts the lane's promise to verify owned process cleanup. The failure is established from source; no complete Ghidra run or actual process leak was reproduced.

Runtime or environment

The failure was verified at source baseline a2d8b94dd5 and is still present at 8b181716ac, inspected with Node v26.10.0 and npm 11.19.1. The affected lane supports Linux x64 and macOS x64/arm64 and requires a caller-provided supported Ghidra/JDK installation. No Ghidra version was executed for this verification.

Steps to reproduce

These are source-verification steps on the stated baseline. Runtime reproduction was not run.

  1. Follow the verify:ghidra:dos npm command into the DOS verifier. Its starting conditions are no extra arguments, a Linux/macOS host, and an available Ghidra installation configured through GHIDRA_INSTALL_DIR.
  2. Trace a run in which the generated DOS MZ fixture passes the analysis assertions and cleanup successfully closes the client/transport, preserves the fixture bytes, finds no owned Ghidra runtime directory, and removes the temporary workspace.
  3. Consider the launcher's parent exiting after the verifier captures its run identity while the verifier remains alive. The final lineage helper compares the current parent PID with the captured parent PID and returns process_lineage.status: "unavailable" when they differ. No prior lane guard requires that parent to remain alive. A final operating-system process-snapshot failure also produces unavailable status.
  4. Trace that helper result through the final reporting code. The descendant assertion runs only for verified status. The unavailable result reaches the unconditional success-report write.

Expected behavior

For the source-generated DOS fixture, the command must verify owned process and project cleanup before reporting successful verification and complete cleanup. If process lineage cannot be inspected, the command must fail verification and preserve that uncertainty instead of reporting overall success or complete process cleanup.

Actual behavior

The source shows that an otherwise successful run with unavailable process lineage skips the descendant assertion and emits a report containing ok: true and cleanup: "complete", alongside the unavailable lineage status and reason. The final reporting code does not reject that status. This is a false cleanup-complete acceptance result, not evidence that a provider process actually leaked. Owned runtime directories are checked separately before reporting, so a leftover matching directory would fail that earlier assertion.

Evidence

  • Expected source: docs/testing.md:669-674 names owned process/project cleanup as a DOS lane check; docs/testing.md:254-257 requires owned cleanup verification before success.
  • Failure source: package.json:182 selects scripts/verify-real-ghidra-dos.mjs; its entry guards at lines 30-51, run creation at line 60, report assignment at lines 393-448, cleanup at lines 453-478, and final reporting at lines 480-490 establish the reachable acceptance path. scripts/lib/verifier-run.mjs:13-17 captures the parent identity, lines 54-59 return unavailable when it changes, and lines 99-105 return unavailable for snapshot failure.
  • Evidence provenance: static
  • Local verification: static-proof
  • Reproduction completeness: complete

Runtime reproduction was not run. The helper returns unavailable without throwing, the preceding DOS checks do not validate process lineage or require an unchanged parent, and the final reporting branch accepts this result after successful earlier checks. This establishes the failed contract without treating a simulated reporting fragment as a real-provider run.

The inspected MIPS verifier tails reject unavailable status as well as surviving descendants. They provide a comparison rather than a separate contract or a claim about every other verifier.

Issue #354 is closed prior work on verifier run identities and lineage. Its completion comment references merged implementation work. This report concerns the DOS lane's acceptance of an unavailable observation, rather than the absence of run identity support.

Restoration check

With the same otherwise successful DOS run, make the final lineage observation unavailable through the parent-change condition or a controlled observation failure. The command must exit nonzero, must not emit an overall verification-success report, and must make the unverified cleanup state explicit. Merely replacing the cleanup field while retaining ok: true does not restore the success guarantee. As a passing control, verified lineage with zero descendants and successful project cleanup must still permit success. Verified lineage with a surviving descendant must still fail, and an owned runtime-directory leftover must continue to fail the existing directory check.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: A bounded optional verification lane can accept an unknown process-cleanup state as complete, weakening its documented success guarantee. No actual leak, frequency, or failure of the main analysis workflow was observed.
  • Workaround status: available
  • Workaround basis: The emitted report retains the lineage status and reason. A reviewer can accept cleanup only when that status is verified and its descendant list is empty, rejecting unavailable observations instead of relying on the cleanup field.
Originally created by @coygeek on GitHub (Oct 13, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/2519 ## Summary The DOS Ghidra verification command can report success and complete cleanup after its final process-lineage observation returns unavailable. This contradicts the lane's promise to verify owned process cleanup. The failure is established from source; no complete Ghidra run or actual process leak was reproduced. ## Runtime or environment The failure was verified at source baseline a2d8b94dd50dab8d966239dd63ab84718aa8b4b4 and is still present at 8b181716aca2cb467be499cba226abfb5ae19141, inspected with Node v26.10.0 and npm 11.19.1. The affected lane supports Linux x64 and macOS x64/arm64 and requires a caller-provided supported Ghidra/JDK installation. No Ghidra version was executed for this verification. ## Steps to reproduce These are source-verification steps on the stated baseline. Runtime reproduction was not run. 1. Follow the `verify:ghidra:dos` npm command into the DOS verifier. Its starting conditions are no extra arguments, a Linux/macOS host, and an available Ghidra installation configured through `GHIDRA_INSTALL_DIR`. 2. Trace a run in which the generated DOS MZ fixture passes the analysis assertions and cleanup successfully closes the client/transport, preserves the fixture bytes, finds no owned Ghidra runtime directory, and removes the temporary workspace. 3. Consider the launcher's parent exiting after the verifier captures its run identity while the verifier remains alive. The final lineage helper compares the current parent PID with the captured parent PID and returns `process_lineage.status: "unavailable"` when they differ. No prior lane guard requires that parent to remain alive. A final operating-system process-snapshot failure also produces unavailable status. 4. Trace that helper result through the final reporting code. The descendant assertion runs only for verified status. The unavailable result reaches the unconditional success-report write. ## Expected behavior For the source-generated DOS fixture, the command must verify owned process and project cleanup before reporting successful verification and complete cleanup. If process lineage cannot be inspected, the command must fail verification and preserve that uncertainty instead of reporting overall success or complete process cleanup. ## Actual behavior The source shows that an otherwise successful run with unavailable process lineage skips the descendant assertion and emits a report containing `ok: true` and `cleanup: "complete"`, alongside the unavailable lineage status and reason. The final reporting code does not reject that status. This is a false cleanup-complete acceptance result, not evidence that a provider process actually leaked. Owned runtime directories are checked separately before reporting, so a leftover matching directory would fail that earlier assertion. ## Evidence - Expected source: `docs/testing.md:669-674` names owned process/project cleanup as a DOS lane check; `docs/testing.md:254-257` requires owned cleanup verification before success. - Failure source: `package.json:182` selects `scripts/verify-real-ghidra-dos.mjs`; its entry guards at lines 30-51, run creation at line 60, report assignment at lines 393-448, cleanup at lines 453-478, and final reporting at lines 480-490 establish the reachable acceptance path. `scripts/lib/verifier-run.mjs:13-17` captures the parent identity, lines 54-59 return unavailable when it changes, and lines 99-105 return unavailable for snapshot failure. - Evidence provenance: static - Local verification: static-proof - Reproduction completeness: complete Runtime reproduction was not run. The helper returns unavailable without throwing, the preceding DOS checks do not validate process lineage or require an unchanged parent, and the final reporting branch accepts this result after successful earlier checks. This establishes the failed contract without treating a simulated reporting fragment as a real-provider run. The inspected MIPS verifier tails reject unavailable status as well as surviving descendants. They provide a comparison rather than a separate contract or a claim about every other verifier. [Issue #354](https://github.com/morluto/rea/issues/354) is closed prior work on verifier run identities and lineage. Its completion comment references merged implementation work. This report concerns the DOS lane's acceptance of an unavailable observation, rather than the absence of run identity support. ## Restoration check With the same otherwise successful DOS run, make the final lineage observation unavailable through the parent-change condition or a controlled observation failure. The command must exit nonzero, must not emit an overall verification-success report, and must make the unverified cleanup state explicit. Merely replacing the cleanup field while retaining `ok: true` does not restore the success guarantee. As a passing control, verified lineage with zero descendants and successful project cleanup must still permit success. Verified lineage with a surviving descendant must still fail, and an owned runtime-directory leftover must continue to fail the existing directory check. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: A bounded optional verification lane can accept an unknown process-cleanup state as complete, weakening its documented success guarantee. No actual leak, frequency, or failure of the main analysis workflow was observed. - Workaround status: available - Workaround basis: The emitted report retains the lineage status and reason. A reviewer can accept cleanup only when that status is verified and its descendant list is empty, rejecting unavailable observations instead of relying on the cleanup field.
bsakaguchi 2026-10-15 18:28:52 +00:00
Author
Owner

@morluto commented on GitHub (Oct 14, 2026):

Addressed on main in eca18e08ac80ac838eef78788bf82429bbb30673.

DOS verifier success requires positively verified process lineage and no remaining descendants. Unavailable lineage cannot produce cleanup complete.

Validation: Affected suites passed in the merged 65-file run (1169 passed, 2 explicit skips), with full static/architecture checks and documentation checks passing. Final installed-package verification is recorded separately in the audit. Verifier trust-boundary controls cover unavailable lineage, terminal modes, idle TCP teardown, and shared fixture cleanup; no real-provider verifier success is inferred.

Verification scope: Controlled source and production-boundary verification on macOS with pinned Node 24.18.0; real external engines and Windows hosts were not independently rerun. Closure covers the described source defect, not broader provider conformance or performance.

<!-- gh-comment-id:6159227329 --> @morluto commented on GitHub (Oct 14, 2026): Addressed on main in [eca18e08ac80ac838eef78788bf82429bbb30673](https://github.com/morluto/rea/commit/eca18e08ac80ac838eef78788bf82429bbb30673). DOS verifier success requires positively verified process lineage and no remaining descendants. Unavailable lineage cannot produce cleanup complete. Validation: Affected suites passed in the merged 65-file run (1169 passed, 2 explicit skips), with full static/architecture checks and documentation checks passing. Final installed-package verification is recorded separately in the audit. Verifier trust-boundary controls cover unavailable lineage, terminal modes, idle TCP teardown, and shared fixture cleanup; no real-provider verifier success is inferred. Verification scope: Controlled source and production-boundary verification on macOS with pinned Node 24.18.0; real external engines and Windows hosts were not independently rerun. Closure covers the described source defect, not broader provider conformance or performance.
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#837
No description provided.