[GH-ISSUE #6098] [Bug] Thin Mach-O extraction invents an unregistered slice and reports an integrity failure #3731

Closed
opened 2026-10-31 00:43:27 +00:00 by bsakaguchi · 0 comments
Owner

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

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Evidence, artifacts, or reconstruction

Observed behavior

inspect-artifact successfully inventories a real thin arm64e Mach-O as one root occurrence, with root/complete coverage and no integrity contradictions. extract-artifact on the same unchanged bytes fails with integrity_mismatch and Regular artifact entry is missing from inventory: slices/arm64e.

The public error claims that bytes contradict declared integrity and recommends --integrity-policy record-and-continue. Executing that retry returns the same failure. Real Apple lipo and the built CLI were used; no reader or provider was mocked.

Reproduction

On the macOS environment below, from an already built checkout with locked dependencies, the following summarizes the executed sequence. thin-echo is a disposable output filename that must not already exist:

/usr/bin/lipo /bin/echo -thin arm64e -output thin-echo
/usr/bin/lipo -detailed_info thin-echo
node scripts/rea.mjs inspect-artifact thin-echo --format json
node scripts/rea.mjs extract-artifact thin-echo --format json
node scripts/rea.mjs extract-artifact thin-echo --format json --integrity-policy record-and-continue

The input was placed in an isolated directory and TMPDIR was set to that directory so generated extraction destinations could be checked. Each CLI command was run once. Inspection exited 0; both extraction calls exited 1. SHA-256 was calculated before and after every call and remained unchanged. No generated extraction destination remained after either failure. The executable was inspected, never executed.

Expected behavior

Extraction should agree with its own root-only inventory. Return an empty extraction for an artifact without child contents, or a truthful typed unsupported/availability refusal identifying that limitation. Do not report contradictory source bytes when extraction itself introduces an entry absent from inventory.

The extraction contract materializes regular children. The inventory reader selection and coverage creates a slice reader only for universal Mach-O and explicitly returns root/complete coverage for a thin file. No requirement to introduce a new thin-file slice-extraction capability is asserted.

Impact and scope

P2: the materializer routes a valid thin executable through a reader inconsistent with inventory, returns a false integrity diagnosis, and supplies an ineffective recovery command. The tested input reproduced deterministically under both policies. Root inventory remains available through inspect-artifact; this is an observed way to inspect the actual contents without extraction.

No source mutation, successful output corruption or retained extraction directory was observed. Runtime scope is one bare thin arm64e file on macOS. Other thin architectures and MCP were not executed. An app bundle directory uses a different reader and is not included in this claim.

REA version

rea-agents 6.7.0; source 52415975942a4b9c53a817915b313ccc404f280e.

Runtime and platform

macOS 27.0.1 arm64; Node.js v26.12.0; native Apple lipo. No external analysis engine.

Target and artifact context

A 51,792-byte thin arm64e Mach-O produced from the arm64e slice of the system echo executable. SHA-256: a3c4cdbe23f5ce48c1f12f6dcdf4159aef92698a0717c2142f92e393dfe11206. No declared slice-integrity metadata, nested archive, or changed bytes.

Interface

CLI

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

The successful inspection's inventory contains only logical_path: ".", entry_kind: "file", artifact_format: "mach-o", and hash_status: "verified". It reports:

{
  "coverage": {"scope": "root", "status": "complete"},
  "integrity_contradictions": [],
  "limitations": ["Artifact has no child container entries."]
}

Both extraction calls return:

{
  "code": "artifact_operation_failed",
  "category": "integrity_mismatch",
  "retryable": false,
  "details": {
    "operation": "extract_artifact",
    "reason": "integrity",
    "detail": "Regular artifact entry is missing from inventory: slices/arm64e"
  }
}

Their message and remediation say: Artifact bytes contradict declared integrity. If expected, rerun extract_artifact with integrity_policy=record-and-continue (CLI: --integrity-policy record-and-continue) to retain observed bytes as untrusted; otherwise get a fresh copy.

Typed outcome or recovery expected

A result consistent with root-only inventory, or a typed applicability refusal that does not misidentify the source as corrupt or recommend the ineffective policy retry. Preserve actual integrity checks for matching inventoried entries.

Analysis or suspected cause

Source-derived explanation: the extraction format guard admits both thin and universal Mach-O. Its reader selector then falls through to MachOSliceArtifactReader. The slice reader yields slices/arm64e from the successful non-fat lipo record and structural thin header. The writer's inventory lookup cannot find that child in the root-only inventory and throws integrity.

The public CLI chooses its own output destination; callers do not supply output_root to this command. This failure is before reading or writing a selected slice's payload.

Additional context

Relevant extraction, inventory and slice-reader files are unchanged between the tested revision and freshly fetched upstream main d8a9673fc44fde4bd30ff98c241886e6683580ca; the later revision was inspected, not executed.

Related reports concern distinct fixes: #5982 types malformed lipo output; #4280 matches universal arm64e.x1 metadata; #4271 diagnoses duplicate ZIP paths, whose collision preflight is already present here; #6068 classifies managed source changes. This reproduction uses a valid non-fat lipo response, no duplicate paths, and unchanged source bytes. #5868 concerns historical-capture cancellation.

Originally created by @coygeek on GitHub (Oct 21, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6098 ### Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area Evidence, artifacts, or reconstruction ### Observed behavior `inspect-artifact` successfully inventories a real thin arm64e Mach-O as one root occurrence, with root/complete coverage and no integrity contradictions. `extract-artifact` on the same unchanged bytes fails with `integrity_mismatch` and `Regular artifact entry is missing from inventory: slices/arm64e`. The public error claims that bytes contradict declared integrity and recommends `--integrity-policy record-and-continue`. Executing that retry returns the same failure. Real Apple lipo and the built CLI were used; no reader or provider was mocked. ### Reproduction On the macOS environment below, from an already built checkout with locked dependencies, the following summarizes the executed sequence. `thin-echo` is a disposable output filename that must not already exist: ```sh /usr/bin/lipo /bin/echo -thin arm64e -output thin-echo /usr/bin/lipo -detailed_info thin-echo node scripts/rea.mjs inspect-artifact thin-echo --format json node scripts/rea.mjs extract-artifact thin-echo --format json node scripts/rea.mjs extract-artifact thin-echo --format json --integrity-policy record-and-continue ``` The input was placed in an isolated directory and `TMPDIR` was set to that directory so generated extraction destinations could be checked. Each CLI command was run once. Inspection exited 0; both extraction calls exited 1. SHA-256 was calculated before and after every call and remained unchanged. No generated extraction destination remained after either failure. The executable was inspected, never executed. ### Expected behavior Extraction should agree with its own root-only inventory. Return an empty extraction for an artifact without child contents, or a truthful typed unsupported/availability refusal identifying that limitation. Do not report contradictory source bytes when extraction itself introduces an entry absent from inventory. The [extraction contract](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/contracts/artifactToolContracts.ts#L30-L39) materializes regular children. The [inventory reader selection and coverage](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/artifacts/inventory/reader.ts#L39-L103) creates a slice reader only for universal Mach-O and explicitly returns root/complete coverage for a thin file. No requirement to introduce a new thin-file slice-extraction capability is asserted. ### Impact and scope P2: the materializer routes a valid thin executable through a reader inconsistent with inventory, returns a false integrity diagnosis, and supplies an ineffective recovery command. The tested input reproduced deterministically under both policies. Root inventory remains available through `inspect-artifact`; this is an observed way to inspect the actual contents without extraction. No source mutation, successful output corruption or retained extraction directory was observed. Runtime scope is one bare thin arm64e file on macOS. Other thin architectures and MCP were not executed. An app bundle directory uses a different reader and is not included in this claim. ### REA version `rea-agents` 6.7.0; source `52415975942a4b9c53a817915b313ccc404f280e`. ### Runtime and platform macOS 27.0.1 arm64; Node.js v26.12.0; native Apple lipo. No external analysis engine. ### Target and artifact context A 51,792-byte thin arm64e Mach-O produced from the arm64e slice of the system echo executable. SHA-256: `a3c4cdbe23f5ce48c1f12f6dcdf4159aef92698a0717c2142f92e393dfe11206`. No declared slice-integrity metadata, nested archive, or changed bytes. ### Interface CLI ### Earliest failure stage Native analysis or reconstruction ### Relevant output or evidence The successful inspection's inventory contains only `logical_path: "."`, `entry_kind: "file"`, `artifact_format: "mach-o"`, and `hash_status: "verified"`. It reports: ```json { "coverage": {"scope": "root", "status": "complete"}, "integrity_contradictions": [], "limitations": ["Artifact has no child container entries."] } ``` Both extraction calls return: ```json { "code": "artifact_operation_failed", "category": "integrity_mismatch", "retryable": false, "details": { "operation": "extract_artifact", "reason": "integrity", "detail": "Regular artifact entry is missing from inventory: slices/arm64e" } } ``` Their message and remediation say: `Artifact bytes contradict declared integrity. If expected, rerun extract_artifact with integrity_policy=record-and-continue (CLI: --integrity-policy record-and-continue) to retain observed bytes as untrusted; otherwise get a fresh copy.` ### Typed outcome or recovery expected A result consistent with root-only inventory, or a typed applicability refusal that does not misidentify the source as corrupt or recommend the ineffective policy retry. Preserve actual integrity checks for matching inventoried entries. ### Analysis or suspected cause Source-derived explanation: [the extraction format guard](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/artifacts/extraction/ArtifactExtraction.ts#L438-L468) admits both thin and universal Mach-O. [Its reader selector](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/artifacts/extraction/ArtifactExtraction.ts#L471-L488) then falls through to `MachOSliceArtifactReader`. The [slice reader](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/artifacts/MachOSliceArtifactReader.ts#L118-L188) yields `slices/arm64e` from the successful non-fat lipo record and structural thin header. [The writer's inventory lookup](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/artifacts/extraction/ArtifactExtraction.ts#L317-L329) cannot find that child in the root-only inventory and throws `integrity`. The public CLI chooses its own output destination; callers do not supply `output_root` to this command. This failure is before reading or writing a selected slice's payload. ### Additional context Relevant extraction, inventory and slice-reader files are unchanged between the tested revision and freshly fetched upstream main `d8a9673fc44fde4bd30ff98c241886e6683580ca`; the later revision was inspected, not executed. Related reports concern distinct fixes: #5982 types malformed lipo output; #4280 matches universal arm64e.x1 metadata; #4271 diagnoses duplicate ZIP paths, whose collision preflight is already present here; #6068 classifies managed source changes. This reproduction uses a valid non-fat lipo response, no duplicate paths, and unchanged source bytes. #5868 concerns historical-capture cancellation.
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#3731
No description provided.