[GH-ISSUE #5606] [Bug] inspect-macho aborts on executables linked without LC_UUID #3399

Closed
opened 2026-10-31 00:39:55 +00:00 by bsakaguchi · 0 comments
Owner

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

Before submitting

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

Area

Native analysis or decompilation

Observed behavior

node scripts/rea.mjs inspect-macho "$work_dir/probe" --json aborts on a thin arm64 executable linked with -Wl,-no_uuid. The native-macos provider returns execution_failure, no inspection Evidence, and guidance to run rea doctor, although its captured dyld_info diagnostic identifies the target property: missing LC_UUID load command. The same source linked normally succeeds. A UUID-less object-file control also succeeds with uuid: null, so this report concerns the linked executable case.

Reproduction

With the source checkout's locked dependencies installed and CLI built, run from its root on the stated macOS toolchain:

work_dir="$(mktemp -d)"
mkdir -p "$work_dir"/home "$work_dir"/config "$work_dir"/data "$work_dir"/cache "$work_dir"/state "$work_dir"/temp "$work_dir"/out
cat > "$work_dir/probe.c" <<'C'
int exported_add(int a, int b) { return a + b; }
int main(void) { return exported_add(1, 2); }
C
clang -Wl,-no_uuid -o "$work_dir/probe" "$work_dir/probe.c"
clang -o "$work_dir/control" "$work_dir/probe.c"
for image in probe control; do
  env -i PATH="$PATH" HOME="$work_dir/home" \
    XDG_CONFIG_HOME="$work_dir/config" XDG_DATA_HOME="$work_dir/data" \
    XDG_CACHE_HOME="$work_dir/cache" XDG_STATE_HOME="$work_dir/state" \
    TMPDIR="$work_dir/temp" REA_LOG_LEVEL=silent \
    node scripts/rea.mjs inspect-macho "$work_dir/$image" --json \
    > "$work_dir/out/$image.json" 2> "$work_dir/out/$image.stderr"
  printf '%s exit: %s\n' "$image" "$?"
done
cat "$work_dir/out/probe.json"

These commands were independently executed at the baseline below. An equivalent isolated runner freshly compiled and inspected both executables after compiling current main. Each revision had one failing probe invocation and one successful normal-link control invocation. The fixtures were inspected without executing them.

Expected behavior

Return available inspection facts with uuid: null and truthful limitations for unsupported observations. If this executable property is intentionally unsupported, return a target-specific refusal naming the missing LC_UUID and retaining the diagnostic. The caller should be able to distinguish target content from provider malfunction.

Source-derived contract: src/contracts/native/nativeToolContracts.ts:95-105 advertises Mach-O inspection facts; src/domain/native/nativeInspection.ts:123 permits a null UUID; src/native/parsers/machoUuid.ts:139-143,208-220 represents absent UUID observations as null; docs/tool-design.md:50-59 requires facts, coverage, limitations, and preservation of partial provider facts. These references are at the baseline below. Nullable UUID alone does not require treating every unsupported image as fully inspected.

Impact and scope

P2: this bounded native-inspection case discards otherwise readable facts and recommends host diagnosis for a deterministic target-content condition. Both tested revisions reproduced it. Data loss, security impact, and failure of general REA analysis workflows were not established. Rebuilding with a UUID changes the analyzed bytes; external readers do not return REA Evidence. Alternative REA workflows preserving the required result were not tested, so workaround availability remains unknown. Universal images, other architectures/toolchains, and MCP transport were not tested.

REA version

rea-agents 6.7.0, source commit 074768901f3cdc8205b61773fb1faf6f6c7b3ca8. Rechecked with a fresh runtime compile of current main 90e433df06b3f83417176b8db1b0a905f9df1d3a (also 6.7.0): still fails. These are source-checkout reproductions.

Runtime and platform

Node.js v26.12.0; macOS 27.0.1 arm64; Apple clang 21.0.0 (clang-2100.3.34.2); Apple linker ld-27037.1. Hopper/Ghidra are not involved.

Target and artifact context

Self-built thin arm64 Mach-O EXECUTE image with 15 readable load commands and no LC_UUID, produced by the documented linker option -no_uuid. The normal-link control uses the same C source. The baseline object-file control was compiled with clang -c and has no UUID.

Interface

CLI

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

The failing CLI exits 1; this relevant JSON subset is identical on both tested revisions:

{
  "code": "execution_failure",
  "category": "execution_failure",
  "retryable": false,
  "message": "Analysis could not complete. Run `rea doctor` and review the reported details; repeating the unchanged request is not expected to succeed.",
  "details": {
    "provider_id": "native-macos",
    "operation": "inspect_macho",
    "diagnostics": {
      "tool": "dyld_info",
      "reason": "nonzero-exit",
      "exit_code": 1,
      "signal": null
    }
  }
}

Captured stdout contains missing LC_UUID load command; stderr is empty and capture is not truncated. The private operand prefix is omitted here. Separately executed xcrun dyld_info -imports and -exports each exit 1 with that diagnostic on the probe. xcrun otool -h -l, xcrun llvm-objdump --macho --private-headers, xcrun nm -gjU --no-dyldinfo, and xcrun dwarfdump --uuid all exit 0 on it; nm lists _exported_add and _main, and dwarfdump produces no UUID row. The normal-link control passes those readers and REA, returning a non-null UUID, three exports, 16 load commands, and three segments.

The baseline-only object control exits 0 from REA with uuid: null and four load commands. The baseline's focused src/native/NativeMachoInspection.test.ts suite passes 19 tests; that does not establish restoration of this executable case. Evidence provenance: observed; local verification: independently reproduced.

Typed outcome or recovery expected

Inspection Evidence with readable facts, null UUID, and explicit missing coverage is preferred because the contract represents absent UUID and partial facts. An explicit unsupported_target refusal naming the missing LC_UUID is an acceptable target-aware fallback if maintainers exclude this input. A generic provider failure with doctor guidance does not distinguish those outcomes. Preserve normal executable and UUID-less object success, and keep genuine launcher/cleanup failures separately classified.

Analysis or suspected cause

Source-derived explanation: src/native/NativeMachoInspection.ts:50-55,111-117 requires both dyld_info modes and returns a failed command before normalization and UUID reconciliation. At the baseline, src/native/NativeMacOSProvider.ts:904-923,934-957,1124-1136 invokes inspection and maps the nonzero native exit to the generic adapter error. Current main retains that required-command/early-return path and generic translation. This agrees with the real CLI diagnostic; it is not a claim that every UUID-less Mach-O fails.

Additional context

Prepared with AI assistance and independently reproduced against real Apple tools. The installed linker manual documents -no_uuid as omitting LC_UUID and warns about debugger/crash-reporting tracking. No fix or successful restoration has been tested; no earlier known-good version was established.

Prior mention: #4195 noted this dyld_info failure in passing; that issue was closed for an unrelated architecture-label fix, and current main still fails as shown.

Originally created by @coygeek on GitHub (Oct 20, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5606 ### 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 Native analysis or decompilation ### Observed behavior `node scripts/rea.mjs inspect-macho "$work_dir/probe" --json` aborts on a thin arm64 executable linked with `-Wl,-no_uuid`. The native-macos provider returns `execution_failure`, no inspection Evidence, and guidance to run `rea doctor`, although its captured `dyld_info` diagnostic identifies the target property: `missing LC_UUID load command`. The same source linked normally succeeds. A UUID-less object-file control also succeeds with `uuid: null`, so this report concerns the linked executable case. ### Reproduction With the source checkout's locked dependencies installed and CLI built, run from its root on the stated macOS toolchain: ```sh work_dir="$(mktemp -d)" mkdir -p "$work_dir"/home "$work_dir"/config "$work_dir"/data "$work_dir"/cache "$work_dir"/state "$work_dir"/temp "$work_dir"/out cat > "$work_dir/probe.c" <<'C' int exported_add(int a, int b) { return a + b; } int main(void) { return exported_add(1, 2); } C clang -Wl,-no_uuid -o "$work_dir/probe" "$work_dir/probe.c" clang -o "$work_dir/control" "$work_dir/probe.c" for image in probe control; do env -i PATH="$PATH" HOME="$work_dir/home" \ XDG_CONFIG_HOME="$work_dir/config" XDG_DATA_HOME="$work_dir/data" \ XDG_CACHE_HOME="$work_dir/cache" XDG_STATE_HOME="$work_dir/state" \ TMPDIR="$work_dir/temp" REA_LOG_LEVEL=silent \ node scripts/rea.mjs inspect-macho "$work_dir/$image" --json \ > "$work_dir/out/$image.json" 2> "$work_dir/out/$image.stderr" printf '%s exit: %s\n' "$image" "$?" done cat "$work_dir/out/probe.json" ``` These commands were independently executed at the baseline below. An equivalent isolated runner freshly compiled and inspected both executables after compiling current main. Each revision had one failing probe invocation and one successful normal-link control invocation. The fixtures were inspected without executing them. ### Expected behavior Return available inspection facts with `uuid: null` and truthful limitations for unsupported observations. If this executable property is intentionally unsupported, return a target-specific refusal naming the missing `LC_UUID` and retaining the diagnostic. The caller should be able to distinguish target content from provider malfunction. Source-derived contract: `src/contracts/native/nativeToolContracts.ts:95-105` advertises Mach-O inspection facts; `src/domain/native/nativeInspection.ts:123` permits a null UUID; `src/native/parsers/machoUuid.ts:139-143,208-220` represents absent UUID observations as null; `docs/tool-design.md:50-59` requires facts, coverage, limitations, and preservation of partial provider facts. These references are at the baseline below. Nullable UUID alone does not require treating every unsupported image as fully inspected. ### Impact and scope P2: this bounded native-inspection case discards otherwise readable facts and recommends host diagnosis for a deterministic target-content condition. Both tested revisions reproduced it. Data loss, security impact, and failure of general REA analysis workflows were not established. Rebuilding with a UUID changes the analyzed bytes; external readers do not return REA Evidence. Alternative REA workflows preserving the required result were not tested, so workaround availability remains unknown. Universal images, other architectures/toolchains, and MCP transport were not tested. ### REA version `rea-agents` 6.7.0, source commit `074768901f3cdc8205b61773fb1faf6f6c7b3ca8`. Rechecked with a fresh runtime compile of current main `90e433df06b3f83417176b8db1b0a905f9df1d3a` (also 6.7.0): still fails. These are source-checkout reproductions. ### Runtime and platform Node.js v26.12.0; macOS 27.0.1 arm64; Apple clang 21.0.0 (clang-2100.3.34.2); Apple linker ld-27037.1. Hopper/Ghidra are not involved. ### Target and artifact context Self-built thin arm64 Mach-O EXECUTE image with 15 readable load commands and no `LC_UUID`, produced by the documented linker option `-no_uuid`. The normal-link control uses the same C source. The baseline object-file control was compiled with `clang -c` and has no UUID. ### Interface CLI ### Earliest failure stage Native analysis or reconstruction ### Relevant output or evidence The failing CLI exits 1; this relevant JSON subset is identical on both tested revisions: ```json { "code": "execution_failure", "category": "execution_failure", "retryable": false, "message": "Analysis could not complete. Run `rea doctor` and review the reported details; repeating the unchanged request is not expected to succeed.", "details": { "provider_id": "native-macos", "operation": "inspect_macho", "diagnostics": { "tool": "dyld_info", "reason": "nonzero-exit", "exit_code": 1, "signal": null } } } ``` Captured stdout contains `missing LC_UUID load command`; stderr is empty and capture is not truncated. The private operand prefix is omitted here. Separately executed `xcrun dyld_info -imports` and `-exports` each exit 1 with that diagnostic on the probe. `xcrun otool -h -l`, `xcrun llvm-objdump --macho --private-headers`, `xcrun nm -gjU --no-dyldinfo`, and `xcrun dwarfdump --uuid` all exit 0 on it; nm lists `_exported_add` and `_main`, and dwarfdump produces no UUID row. The normal-link control passes those readers and REA, returning a non-null UUID, three exports, 16 load commands, and three segments. The baseline-only object control exits 0 from REA with `uuid: null` and four load commands. The baseline's focused `src/native/NativeMachoInspection.test.ts` suite passes 19 tests; that does not establish restoration of this executable case. Evidence provenance: observed; local verification: independently reproduced. ### Typed outcome or recovery expected Inspection Evidence with readable facts, null UUID, and explicit missing coverage is preferred because the contract represents absent UUID and partial facts. An explicit `unsupported_target` refusal naming the missing `LC_UUID` is an acceptable target-aware fallback if maintainers exclude this input. A generic provider failure with doctor guidance does not distinguish those outcomes. Preserve normal executable and UUID-less object success, and keep genuine launcher/cleanup failures separately classified. ### Analysis or suspected cause Source-derived explanation: `src/native/NativeMachoInspection.ts:50-55,111-117` requires both `dyld_info` modes and returns a failed command before normalization and UUID reconciliation. At the baseline, `src/native/NativeMacOSProvider.ts:904-923,934-957,1124-1136` invokes inspection and maps the nonzero native exit to the generic adapter error. Current main retains that required-command/early-return path and generic translation. This agrees with the real CLI diagnostic; it is not a claim that every UUID-less Mach-O fails. ### Additional context Prepared with AI assistance and independently reproduced against real Apple tools. The installed linker manual documents `-no_uuid` as omitting `LC_UUID` and warns about debugger/crash-reporting tracking. No fix or successful restoration has been tested; no earlier known-good version was established. Prior mention: #4195 noted this `dyld_info` failure in passing; that issue was closed for an unrelated architecture-label fix, and current main still fails as shown.
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#3399
No description provided.