[GH-ISSUE #2545] fix(process): unlistable child directories abort filesystem snapshots #863

Closed
opened 2026-10-15 18:29:06 +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/2545

Summary

A selected filesystem observation root containing an unlistable child directory causes the whole snapshot to fail with a directory-opening permission error. REA returns no partial snapshot, even when readable entries were visited first. The documented capture contract requires partial enumeration and its uncertainty to remain visible rather than erasing usable observations.

Runtime or environment

Repository revision 8b181716ac, Node v26.10.0, npm 11.19.1, and locked dependencies. A non-root user on a POSIX host executed a real filesystem snapshot probe. No child workload or full process-capture CLI was executed.

Steps to reproduce

  1. Create a disposable readable root containing a-visible.txt with contents visible and an empty child directory z-blocked. Run as a non-root user on a POSIX filesystem enforcing directory read permissions.
  2. Change only z-blocked to permission mode zero. Leave the root and readable file accessible.
  3. Parse a process scenario with executable set to the running Node executable, working_directory set to the absolute root, and filesystem_observation_paths containing that root. Call snapshotRoots with the parsed scenario. This is the production operation used before preparing a process capture.
  4. Observe the directory-opening failure. Restore the child's mode to 0700 and repeat, confirming the root is complete and the readable file is present. As another control, make only the regular file unreadable and repeat, then restore its permissions.

The local focused probe executed the blocked-directory case and both controls once, restoring fixture permissions afterward. These calls do not launch the scenario executable.

Expected behavior

The snapshot should preserve the readable file and other observed states while marking the affected root's enumeration incomplete with a meaningful reason. Absence below the unlisted directory must remain unknown. A fully listable root should still have complete coverage, and an unavailable content hash should not imply missing directory enumeration.

Actual behavior

The blocked-directory case rejected with EACCES and syscall opendir, so the caller received no snapshot. Restoring the directory's permissions returned a complete root containing the readable file. Making only the regular file unreadable returned a snapshot with a file_unavailable hash omission and EACCES, while root enumeration remained complete. Source inspection establishes that a preparation snapshot error propagates as a failed process capture.

Evidence

  • Expected source: docs/process-capture.md:220 describes unknown absence under incomplete root enumeration and preservation of other known facts; docs/process-capture.md:377 includes enumeration failures in coverage accounting. AGENTS.md, Architecture and Cleanup, requires preservation of partial facts and meaningful failure reasons.
  • Failure source: src/process/capture/FilesystemSnapshot.ts:255 performs the unguarded directory open; the real permissions probe observed its EACCES rejection. src/process/capture/ProcessCaptureLifecycle.ts:1482 and src/process/capture/ProcessHarness.ts:647 establish propagation through capture preparation. src/process/capture/ProcessScenarioRuntimeValidation.ts:62 resolves selected observation paths without recursively rejecting unlistable children.
  • Evidence provenance: observed
  • Local verification: reproduced
  • Reproduction completeness: complete

No matching existing failure was found in read-only issue searches. A directory disappearing before the open is a source-established related possibility, but that race was not executed

Restoration check

Repeat the permission fixture and require a returned snapshot retaining the readable file, incomplete coverage for the affected root, and truthful access-failure evidence. Any previously observed descendant missing from an unlisted subtree must be classified as unknown rather than deleted. Preserve complete-root success when the directory becomes listable and the existing per-file hash omission behavior for an unreadable regular file. Cancellation must continue to terminate observation rather than become an ordinary coverage omission.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: A bounded valid observation root with an inaccessible child loses the entire filesystem checkpoint and source-established capture preparation fails. The local probe demonstrates permission failure rather than broad incidence or a process-launch failure.
  • Workaround status: available
  • Workaround basis: Restoring list permission on the owned fixture directory preserved the selected coverage and made the same snapshot succeed. This workaround applies where the capture user can safely correct those permissions; no universal remedy for foreign directories was established.
Originally created by @coygeek on GitHub (Oct 13, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/2545 ## Summary A selected filesystem observation root containing an unlistable child directory causes the whole snapshot to fail with a directory-opening permission error. REA returns no partial snapshot, even when readable entries were visited first. The documented capture contract requires partial enumeration and its uncertainty to remain visible rather than erasing usable observations. ## Runtime or environment Repository revision 8b181716aca2cb467be499cba226abfb5ae19141, Node v26.10.0, npm 11.19.1, and locked dependencies. A non-root user on a POSIX host executed a real filesystem snapshot probe. No child workload or full process-capture CLI was executed. ## Steps to reproduce 1. Create a disposable readable root containing `a-visible.txt` with contents `visible` and an empty child directory `z-blocked`. Run as a non-root user on a POSIX filesystem enforcing directory read permissions. 2. Change only `z-blocked` to permission mode zero. Leave the root and readable file accessible. 3. Parse a process scenario with `executable` set to the running Node executable, `working_directory` set to the absolute root, and `filesystem_observation_paths` containing that root. Call `snapshotRoots` with the parsed scenario. This is the production operation used before preparing a process capture. 4. Observe the directory-opening failure. Restore the child's mode to `0700` and repeat, confirming the root is complete and the readable file is present. As another control, make only the regular file unreadable and repeat, then restore its permissions. The local focused probe executed the blocked-directory case and both controls once, restoring fixture permissions afterward. These calls do not launch the scenario executable. ## Expected behavior The snapshot should preserve the readable file and other observed states while marking the affected root's enumeration incomplete with a meaningful reason. Absence below the unlisted directory must remain unknown. A fully listable root should still have complete coverage, and an unavailable content hash should not imply missing directory enumeration. ## Actual behavior The blocked-directory case rejected with `EACCES` and syscall `opendir`, so the caller received no snapshot. Restoring the directory's permissions returned a complete root containing the readable file. Making only the regular file unreadable returned a snapshot with a `file_unavailable` hash omission and `EACCES`, while root enumeration remained complete. Source inspection establishes that a preparation snapshot error propagates as a failed process capture. ## Evidence - Expected source: `docs/process-capture.md:220` describes unknown absence under incomplete root enumeration and preservation of other known facts; `docs/process-capture.md:377` includes enumeration failures in coverage accounting. `AGENTS.md`, Architecture and Cleanup, requires preservation of partial facts and meaningful failure reasons. - Failure source: `src/process/capture/FilesystemSnapshot.ts:255` performs the unguarded directory open; the real permissions probe observed its EACCES rejection. `src/process/capture/ProcessCaptureLifecycle.ts:1482` and `src/process/capture/ProcessHarness.ts:647` establish propagation through capture preparation. `src/process/capture/ProcessScenarioRuntimeValidation.ts:62` resolves selected observation paths without recursively rejecting unlistable children. - Evidence provenance: observed - Local verification: reproduced - Reproduction completeness: complete No matching existing failure was found in read-only issue searches. A directory disappearing before the open is a source-established related possibility, but that race was not executed ## Restoration check Repeat the permission fixture and require a returned snapshot retaining the readable file, incomplete coverage for the affected root, and truthful access-failure evidence. Any previously observed descendant missing from an unlisted subtree must be classified as unknown rather than deleted. Preserve complete-root success when the directory becomes listable and the existing per-file hash omission behavior for an unreadable regular file. Cancellation must continue to terminate observation rather than become an ordinary coverage omission. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: A bounded valid observation root with an inaccessible child loses the entire filesystem checkpoint and source-established capture preparation fails. The local probe demonstrates permission failure rather than broad incidence or a process-launch failure. - Workaround status: available - Workaround basis: Restoring list permission on the owned fixture directory preserved the selected coverage and made the same snapshot succeed. This workaround applies where the capture user can safely correct those permissions; no universal remedy for foreign directories was established.
bsakaguchi 2026-10-15 18:29:06 +00:00
Author
Owner

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

Fixed on main: snapshot enumeration catches an unreadable child directory, retains readable sibling and directory observations, and marks the root incomplete with a directory_unavailable/EACCES omission. Missing descendants remain unknown.

Validation: the real non-root POSIX permission regression retains readable entries and marks an unreadable directory subtree unknown in src/process/capture/FilesystemCoverage.test.ts passed locally today, alongside all 14 coverage tests. The earlier audit cited the wrong test file; this closure is based on the actual permission fixture and current producing boundary.

<!-- gh-comment-id:6161838621 --> @morluto commented on GitHub (Oct 14, 2026): Fixed on main: snapshot enumeration catches an unreadable child directory, retains readable sibling and directory observations, and marks the root incomplete with a `directory_unavailable`/`EACCES` omission. Missing descendants remain unknown. Validation: the real non-root POSIX permission regression `retains readable entries and marks an unreadable directory subtree unknown` in `src/process/capture/FilesystemCoverage.test.ts` passed locally today, alongside all 14 coverage tests. The earlier audit cited the wrong test file; this closure is based on the actual permission fixture and current producing boundary.
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#863
No description provided.