[GH-ISSUE #8216] [Bug] Missing Ghidra project program is hidden behind generic doctor advice #6490

Closed
opened 2026-11-01 21:11:36 +00:00 by bsakaguchi · 3 comments
Owner

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

Before submitting

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

Area

MCP or agent integration

Observed behavior

When an existing Ghidra project contains valid programs but the selected program name does not exist, the first provider query returns generic execution_failure and advises rea doctor. Ghidra's output identifies the missing project program, but that reason is buried in captured diagnostics. A provider-scoped doctor run without a target reported healthy: true; it did not check which program should be selected.

Reproduction

On macOS arm64, REA 38433cfb4577b133d7598f9439c6448299cb44eb, Ghidra 12.1.4 and JDK 21:

  1. Import the same self-built Mach-O into one owned project twice, as root programs program_alpha and program_beta. Give their same function distinct metadata names so selection is observable. Both programs record the original target SHA-256.
  2. Set REA_GHIDRA_PROJECT_PATH to that project and leave REA_GHIDRA_PROGRAM_NAME unset. Open the original target whose basename is workflow, which is not a root program name in the project, and call procedure_pseudo_code.
  3. open_binary succeeds as a lazy target binding; the first query returns execution_failure / Analysis could not complete. Run rea doctor.... Captured Ghidra output says Requested project program file(s) not found: workflow.
  4. In separate REA servers with REA_GHIDRA_PROGRAM_NAME=program_alpha and program_beta, opening the same target and querying the respective annotated names succeeded. All 12 original project regular-file content digests and the target digest were unchanged.

One missing-default selection and two explicit controls were run. Ghidra was headless, the target was never executed, and REA opened an owned read-only project copy.

Expected behavior

Preserve the selected project and fail closed, but surface an actionable missing-program reason and the selected/default name when a trustworthy producer can establish that condition. Explain how to choose the exact root program via REA_GHIDRA_PROGRAM_NAME in the environment starting REA, including that a restart is needed for a new selection. Do not silently pick another program or infer the intended one from equal binary hashes. Avoid treating arbitrary process logs or all pre-handshake failures as missing-program proof.

Impact and scope

An agent following the top-level advice is not told which selection is missing or how to change it. Observed only on this Ghidra/macOS fixture; no claim about other startup failures or automatic project enumeration.

REA version

38433cfb4577b133d7598f9439c6448299cb44eb (PR #8187 branch)

Runtime and platform

Node 24.22.1; macOS 26.3 arm64; Ghidra 12.1.4; JDK 21.

Target and artifact context

Two root programs in one caller-owned Ghidra project, both imported from byte-identical self-owned Mach-O files; selected binary not executed.

Interface

MCP

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

First query: execution_failure, failure_message: Ghidra exited before bridge startup, generic doctor remediation. Captured provider output: Requested project program file(s) not found: workflow. Explicit program selections returned their own annotated names and comments. A separate no-target rea doctor --provider ghidra --json returned scope healthy: true, but its scope explicitly had target: null.

Typed outcome or recovery expected

Actionable, bounded missing-program recovery from a structured/verified producer signal, with exact selection and project context; continue to distinguish target binding from Ghidra readiness.

Analysis or suspected cause

NOT_ENOUGH_INFO for a safe structured attribution mechanism: in this case Ghidra exits before REA's bridge script starts. The direct output identifies the cause for the experimenter, but string matching a generic log should not be assumed robust.

Additional context

Related but distinct: #8169 handles an imported-byte digest mismatch after a program is found; #8208 handles a missing function inside a successfully opened project; #3751 and #3817 discuss project selection and folder boundaries. Choosing between two same-digest programs is caller intent, not something the digest can decide.

Originally created by @morluto on GitHub (Oct 30, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/8216 ### 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 MCP or agent integration ### Observed behavior When an existing Ghidra project contains valid programs but the selected program name does not exist, the first provider query returns generic `execution_failure` and advises `rea doctor`. Ghidra's output identifies the missing project program, but that reason is buried in captured diagnostics. A provider-scoped doctor run without a target reported `healthy: true`; it did not check which program should be selected. ### Reproduction On macOS arm64, REA `38433cfb4577b133d7598f9439c6448299cb44eb`, Ghidra 12.1.4 and JDK 21: 1. Import the same self-built Mach-O into one owned project twice, as root programs `program_alpha` and `program_beta`. Give their same function distinct metadata names so selection is observable. Both programs record the original target SHA-256. 2. Set `REA_GHIDRA_PROJECT_PATH` to that project and leave `REA_GHIDRA_PROGRAM_NAME` unset. Open the original target whose basename is `workflow`, which is not a root program name in the project, and call `procedure_pseudo_code`. 3. `open_binary` succeeds as a lazy target binding; the first query returns `execution_failure` / `Analysis could not complete. Run rea doctor...`. Captured Ghidra output says `Requested project program file(s) not found: workflow`. 4. In separate REA servers with `REA_GHIDRA_PROGRAM_NAME=program_alpha` and `program_beta`, opening the same target and querying the respective annotated names succeeded. All 12 original project regular-file content digests and the target digest were unchanged. One missing-default selection and two explicit controls were run. Ghidra was headless, the target was never executed, and REA opened an owned read-only project copy. ### Expected behavior Preserve the selected project and fail closed, but surface an actionable missing-program reason and the selected/default name when a trustworthy producer can establish that condition. Explain how to choose the exact root program via `REA_GHIDRA_PROGRAM_NAME` in the environment starting REA, including that a restart is needed for a new selection. Do not silently pick another program or infer the intended one from equal binary hashes. Avoid treating arbitrary process logs or all pre-handshake failures as missing-program proof. ### Impact and scope An agent following the top-level advice is not told which selection is missing or how to change it. Observed only on this Ghidra/macOS fixture; no claim about other startup failures or automatic project enumeration. ### REA version `38433cfb4577b133d7598f9439c6448299cb44eb` (PR #8187 branch) ### Runtime and platform Node 24.22.1; macOS 26.3 arm64; Ghidra 12.1.4; JDK 21. ### Target and artifact context Two root programs in one caller-owned Ghidra project, both imported from byte-identical self-owned Mach-O files; selected binary not executed. ### Interface MCP ### Earliest failure stage Native analysis or reconstruction ### Relevant output or evidence First query: `execution_failure`, `failure_message: Ghidra exited before bridge startup`, generic doctor remediation. Captured provider output: `Requested project program file(s) not found: workflow`. Explicit program selections returned their own annotated names and comments. A separate no-target `rea doctor --provider ghidra --json` returned scope `healthy: true`, but its scope explicitly had `target: null`. ### Typed outcome or recovery expected Actionable, bounded missing-program recovery from a structured/verified producer signal, with exact selection and project context; continue to distinguish target binding from Ghidra readiness. ### Analysis or suspected cause NOT_ENOUGH_INFO for a safe structured attribution mechanism: in this case Ghidra exits before REA's bridge script starts. The direct output identifies the cause for the experimenter, but string matching a generic log should not be assumed robust. ### Additional context Related but distinct: #8169 handles an imported-byte digest mismatch after a program is found; #8208 handles a missing function inside a successfully opened project; #3751 and #3817 discuss project selection and folder boundaries. Choosing between two same-digest programs is caller intent, not something the digest can decide.
bsakaguchi 2026-11-01 21:11:36 +00:00
  • closed this issue
  • added the
    bug
    triage
    labels
Author
Owner

@macjayz commented on GitHub (Oct 30, 2026):

I'd like to take this one. It follows on from #8114, which made the startup-timeout guidance depend on existing-project mode.

Plan:

  1. When the launcher's Ghidra output establishes that the requested project program is missing, project it as a typed result rather than generic execution_failure. Include the selected or defaulted program name, and say whether it came from REA_GHIDRA_PROGRAM_NAME or the target basename.
  2. Remediation names REA_GHIDRA_PROGRAM_NAME as a server-start environment setting that must match an exact root program name, and drops the rea doctor advice for this case.
  3. Keep fail-closed behavior and the selected project. No fallback to a fresh import or another program.
  4. Tests: missing default name (target basename not in the project), and explicit REA_GHIDRA_PROGRAM_NAME that doesn't exist. Unrelated launch failures still get the existing generic result.

If #8217's changed-project case turns out to share the same projection point, I'll keep it to a separate PR unless you'd rather have both together.

<!-- gh-comment-id:6534191157 --> @macjayz commented on GitHub (Oct 30, 2026): I'd like to take this one. It follows on from #8114, which made the startup-timeout guidance depend on existing-project mode. Plan: 1. When the launcher's Ghidra output establishes that the requested project program is missing, project it as a typed result rather than generic `execution_failure`. Include the selected or defaulted program name, and say whether it came from `REA_GHIDRA_PROGRAM_NAME` or the target basename. 2. Remediation names `REA_GHIDRA_PROGRAM_NAME` as a server-start environment setting that must match an exact root program name, and drops the `rea doctor` advice for this case. 3. Keep fail-closed behavior and the selected project. No fallback to a fresh import or another program. 4. Tests: missing default name (target basename not in the project), and explicit `REA_GHIDRA_PROGRAM_NAME` that doesn't exist. Unrelated launch failures still get the existing generic result. If #8217's changed-project case turns out to share the same projection point, I'll keep it to a separate PR unless you'd rather have both together.
Author
Owner

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

Looping in @gensokyo-dev @kaoru0822-kitauji @N0zoM1z0 for visibility on the Ghidra, Kuna, and REA tool-design investigation.

<!-- gh-comment-id:6538799381 --> @morluto commented on GitHub (Oct 31, 2026): Looping in @gensokyo-dev @kaoru0822-kitauji @N0zoM1z0 for visibility on the Ghidra, Kuna, and REA tool-design investigation.
Author
Owner

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

Real-provider follow-up for merged #8222 on main e6d061897, macOS arm64, Node 24.22.1, Ghidra 12.1.4 and JDK 21. I reused the original source-owned Mach-O and the two-program project from this report; no target was executed.

  • With REA_GHIDRA_PROGRAM_NAME unset, MCP open_binary succeeded as a lazy binding and the first query returned configuration_invalid, naming workflow as defaulted from the target basename. Recovery instructed setting the exact root program in the server-start environment, restarting, and reopening.
  • With REA_GHIDRA_PROGRAM_NAME=program_gamma, the first query returned the same error category and named the explicit selection. The public CLI decompile with the same selection exited 1 and returned the same code, message and recovery in JSON.
  • With REA_GHIDRA_PROGRAM_NAME=program_alpha, the real MCP query succeeded and returned the program-specific selected_alpha annotation and pseudocode. All three MCP sessions closed successfully.

The executable hash and all 12 original project-file content hashes matched before and after the MCP and CLI calls. This exercises the original case and a valid-selection control with a real provider; it does not establish behavior for truncated Ghidra output, other platforms, or all startup failures.

<!-- gh-comment-id:6540594614 --> @morluto commented on GitHub (Oct 31, 2026): Real-provider follow-up for merged #8222 on main `e6d061897`, macOS arm64, Node 24.22.1, Ghidra 12.1.4 and JDK 21. I reused the original source-owned Mach-O and the two-program project from this report; no target was executed. * With `REA_GHIDRA_PROGRAM_NAME` unset, MCP `open_binary` succeeded as a lazy binding and the first query returned `configuration_invalid`, naming `workflow` as defaulted from the target basename. Recovery instructed setting the exact root program in the server-start environment, restarting, and reopening. * With `REA_GHIDRA_PROGRAM_NAME=program_gamma`, the first query returned the same error category and named the explicit selection. The public CLI `decompile` with the same selection exited 1 and returned the same code, message and recovery in JSON. * With `REA_GHIDRA_PROGRAM_NAME=program_alpha`, the real MCP query succeeded and returned the program-specific `selected_alpha` annotation and pseudocode. All three MCP sessions closed successfully. The executable hash and all 12 original project-file content hashes matched before and after the MCP and CLI calls. This exercises the original case and a valid-selection control with a real provider; it does not establish behavior for truncated Ghidra output, other platforms, or all startup failures.
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#6490
No description provided.