[GH-ISSUE #5454] [Bug] Scoped Hopper doctor reports healthy when configuration blocks native analysis #3315

Closed
opened 2026-10-31 00:39:04 +00:00 by bsakaguchi · 1 comment
Owner

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

Before submitting

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

Area

Provider or capability discovery

Observed behavior

Scoped Hopper doctor reports healthy: true and exits 0 with REA_ANALYSIS_PROVIDER=Hopper, but analyze with the same environment, target, and explicit --provider hopper exits 1 with configuration_invalid. Doctor misses a configuration prerequisite that blocks the selected native analysis before any provider session starts.

REA_GHIDRA_STARTUP_TIMEOUT_MS=abc produces the same mismatch with Hopper selected: scoped doctor succeeds, while search-bytes rejects the configuration. In both doctor cases, environment_healthy is false because unrelated components are unavailable, but the explicit scope reports healthy success without identifying the invalid setting.

Reproduction

The independent verifier ran the following cases from the baseline checkout with dependencies and the CLI already built, an installed executable Hopper, isolated HOME/XDG directories, and a synthetic thin arm64 Mach-O header. A submission-time replay of all cases on current main produced the same results.

Set HOPPER_LAUNCHER_PATH to the installed Hopper executable and TMPDIR to an existing disposable parent directory. From the checkout root:

: "${HOPPER_LAUNCHER_PATH:?Set this to the installed Hopper executable}"
scratch="$(mktemp -d "${TMPDIR:?Set TMPDIR to a disposable parent directory}/rea-verify.XXXXXX")"
mkdir -p "$scratch/home" "$scratch/config" "$scratch/data" "$scratch/cache" "$scratch/state" "$scratch/temp"
python3 - "$scratch/thin-macho" <<'PYTHON'
import pathlib, struct, sys
pathlib.Path(sys.argv[1]).write_bytes(
    struct.pack('<8I', 0xfeedfacf, 0x0100000c, 0, 2, 0, 0, 0, 0)
)
PYTHON
run_rea() {
  setting="$1"
  shift
  env -i PATH="$PATH" NO_COLOR=1 \
    HOME="$scratch/home" XDG_CONFIG_HOME="$scratch/config" \
    XDG_DATA_HOME="$scratch/data" XDG_CACHE_HOME="$scratch/cache" \
    XDG_STATE_HOME="$scratch/state" TMPDIR="$scratch/temp" \
    HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_NO_ANALYTICS=1 \
    HOPPER_LAUNCHER_PATH="$HOPPER_LAUNCHER_PATH" \
    GHIDRA_INSTALL_DIR="$scratch/absent-ghidra" \
    REA_IDA_MCP_CONFIG="$scratch/absent-ida.json" \
    "$setting" node scripts/rea.mjs "$@" </dev/null
}
run_rea REA_ANALYSIS_PROVIDER=hopper doctor --provider hopper --target "$scratch/thin-macho" --json
run_rea REA_ANALYSIS_PROVIDER=Hopper doctor --provider hopper --target "$scratch/thin-macho" --json
run_rea REA_ANALYSIS_PROVIDER=Hopper analyze "$scratch/thin-macho" --provider hopper --json
run_rea REA_GHIDRA_STARTUP_TIMEOUT_MS=abc doctor --provider hopper --json
run_rea REA_GHIDRA_STARTUP_TIMEOUT_MS=abc search-bytes "$scratch/thin-macho" '48 8b' --provider hopper --json
run_rea REA_ANALYSIS_PROVIDER=Hopper capabilities --json

Expected behavior

The scoped readiness check should identify an invalid environment setting that blocks native analysis with the selected engine, report unsuccessful health, and exit nonzero. The valid-preference control should continue to succeed.

docs/installation.md:313-348 identifies scoped doctor as the readiness check for one analysis engine and says scope_checks determine healthy and exit status. docs/cli.md:177-195 documents the standing preference, explicit provider override, and scoped doctor diagnosis. These expectations concern process configuration, before target/provider use.

Impact and scope

A caller following the documented readiness check receives success and proceeds into native analysis that immediately fails. The reproduced cases are bounded to invalid environment settings. The native error identifies the setting and remediation; correcting it is a practical workaround. capabilities also independently rejects the invalid provider preference.

Only the native commands above were reproduced. Some session routes bypass the shared configuration parser, based on source inspection, so this report does not claim every analysis route fails. No provider analysis session was started.

REA version

6.7.0; source commit 074768901f3cdc8205b61773fb1faf6f6c7b3ca8. Also reproduced on current main 052956af3416fa01d93837e54fdec3ad2739f6d1 after compiling its runtime.

Runtime and platform

Node.js v26.12.0; macOS 27.0.1; arm64. Hopper was installed and executable. NOT_ENOUGH_INFO: the Hopper version and successful engine analysis were not measured; failure occurs before a provider session starts.

Target and artifact context

Synthetic 32-byte thin arm64 Mach-O header, generated in the reproduction. The target check passes in both target-scoped doctor cases. No private binary or target data is required.

Interface

CLI

Earliest failure stage

Setup or provider admission

Relevant output or evidence

The independent baseline verification and current-main replay observed:

Setting and command Exit Relevant result
REA_ANALYSIS_PROVIDER=hopper, target-scoped doctor 0 healthy: true; node, target, host, hopper checks pass
REA_ANALYSIS_PROVIDER=Hopper, same doctor 0 healthy: true; same required checks pass
REA_ANALYSIS_PROVIDER=Hopper, analyze 1 configuration_invalid, category: invalid_input; remediation names REA_ANALYSIS_PROVIDER
REA_GHIDRA_STARTUP_TIMEOUT_MS=abc, scoped Hopper doctor 0 healthy: true; node, host, hopper checks pass
Same invalid timeout, search-bytes 1 configuration_invalid; timeout must be a positive decimal integer
REA_ANALYSIS_PROVIDER=Hopper, capabilities 1 configuration_invalid; names the provider preference

Typed outcome or recovery expected

Doctor should return nonzero, identify the configuration setting that blocks selected native analysis, and avoid healthy: true. Native commands should retain their validation. The valid provider control should retain healthy success.

Analysis or suspected cause

Source-derived reasoning at the baseline: src/cli/setupCommands.ts:123-135 reaches doctor, and src/application/Doctor.ts:251-299 assembles readiness without the complete application-configuration validation used by the native path. src/composition/directAnalysis.ts:17-25 binds native analysis to parseConfig; src/application/DirectAnalysis.ts:246-255 returns its configuration error before session creation. src/config/parseConfig.ts:43-67 maps both settings under test.

Additional context

This report was prepared with AI assistance and independently reproduced by a verifier. Submission-time replay confirmed the same results on current main.

Related #3306, fixed by #3755, covers REA_HOPPER_STARTUP_TIMEOUT_MS. The current-main replay includes that fix and still reproduces the different settings reported here. #3054 concerns different Hopper launcher resolution; this reproduction supplies the same explicit launcher to every command.

Originally created by @coygeek on GitHub (Oct 20, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5454 ### 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 Provider or capability discovery ### Observed behavior Scoped Hopper doctor reports `healthy: true` and exits 0 with `REA_ANALYSIS_PROVIDER=Hopper`, but `analyze` with the same environment, target, and explicit `--provider hopper` exits 1 with `configuration_invalid`. Doctor misses a configuration prerequisite that blocks the selected native analysis before any provider session starts. `REA_GHIDRA_STARTUP_TIMEOUT_MS=abc` produces the same mismatch with Hopper selected: scoped doctor succeeds, while `search-bytes` rejects the configuration. In both doctor cases, `environment_healthy` is false because unrelated components are unavailable, but the explicit scope reports healthy success without identifying the invalid setting. ### Reproduction The independent verifier ran the following cases from the baseline checkout with dependencies and the CLI already built, an installed executable Hopper, isolated HOME/XDG directories, and a synthetic thin arm64 Mach-O header. A submission-time replay of all cases on current main produced the same results. Set `HOPPER_LAUNCHER_PATH` to the installed Hopper executable and `TMPDIR` to an existing disposable parent directory. From the checkout root: ```sh : "${HOPPER_LAUNCHER_PATH:?Set this to the installed Hopper executable}" scratch="$(mktemp -d "${TMPDIR:?Set TMPDIR to a disposable parent directory}/rea-verify.XXXXXX")" mkdir -p "$scratch/home" "$scratch/config" "$scratch/data" "$scratch/cache" "$scratch/state" "$scratch/temp" python3 - "$scratch/thin-macho" <<'PYTHON' import pathlib, struct, sys pathlib.Path(sys.argv[1]).write_bytes( struct.pack('<8I', 0xfeedfacf, 0x0100000c, 0, 2, 0, 0, 0, 0) ) PYTHON run_rea() { setting="$1" shift env -i PATH="$PATH" NO_COLOR=1 \ HOME="$scratch/home" XDG_CONFIG_HOME="$scratch/config" \ XDG_DATA_HOME="$scratch/data" XDG_CACHE_HOME="$scratch/cache" \ XDG_STATE_HOME="$scratch/state" TMPDIR="$scratch/temp" \ HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_NO_ANALYTICS=1 \ HOPPER_LAUNCHER_PATH="$HOPPER_LAUNCHER_PATH" \ GHIDRA_INSTALL_DIR="$scratch/absent-ghidra" \ REA_IDA_MCP_CONFIG="$scratch/absent-ida.json" \ "$setting" node scripts/rea.mjs "$@" </dev/null } run_rea REA_ANALYSIS_PROVIDER=hopper doctor --provider hopper --target "$scratch/thin-macho" --json run_rea REA_ANALYSIS_PROVIDER=Hopper doctor --provider hopper --target "$scratch/thin-macho" --json run_rea REA_ANALYSIS_PROVIDER=Hopper analyze "$scratch/thin-macho" --provider hopper --json run_rea REA_GHIDRA_STARTUP_TIMEOUT_MS=abc doctor --provider hopper --json run_rea REA_GHIDRA_STARTUP_TIMEOUT_MS=abc search-bytes "$scratch/thin-macho" '48 8b' --provider hopper --json run_rea REA_ANALYSIS_PROVIDER=Hopper capabilities --json ``` ### Expected behavior The scoped readiness check should identify an invalid environment setting that blocks native analysis with the selected engine, report unsuccessful health, and exit nonzero. The valid-preference control should continue to succeed. `docs/installation.md:313-348` identifies scoped doctor as the readiness check for one analysis engine and says `scope_checks` determine `healthy` and exit status. `docs/cli.md:177-195` documents the standing preference, explicit provider override, and scoped doctor diagnosis. These expectations concern process configuration, before target/provider use. ### Impact and scope A caller following the documented readiness check receives success and proceeds into native analysis that immediately fails. The reproduced cases are bounded to invalid environment settings. The native error identifies the setting and remediation; correcting it is a practical workaround. `capabilities` also independently rejects the invalid provider preference. Only the native commands above were reproduced. Some session routes bypass the shared configuration parser, based on source inspection, so this report does not claim every analysis route fails. No provider analysis session was started. ### REA version 6.7.0; source commit `074768901f3cdc8205b61773fb1faf6f6c7b3ca8`. Also reproduced on current main `052956af3416fa01d93837e54fdec3ad2739f6d1` after compiling its runtime. ### Runtime and platform Node.js v26.12.0; macOS 27.0.1; arm64. Hopper was installed and executable. NOT_ENOUGH_INFO: the Hopper version and successful engine analysis were not measured; failure occurs before a provider session starts. ### Target and artifact context Synthetic 32-byte thin arm64 Mach-O header, generated in the reproduction. The target check passes in both target-scoped doctor cases. No private binary or target data is required. ### Interface CLI ### Earliest failure stage Setup or provider admission ### Relevant output or evidence The independent baseline verification and current-main replay observed: | Setting and command | Exit | Relevant result | | --- | --- | --- | | `REA_ANALYSIS_PROVIDER=hopper`, target-scoped doctor | 0 | `healthy: true`; node, target, host, hopper checks pass | | `REA_ANALYSIS_PROVIDER=Hopper`, same doctor | 0 | `healthy: true`; same required checks pass | | `REA_ANALYSIS_PROVIDER=Hopper`, analyze | 1 | `configuration_invalid`, `category: invalid_input`; remediation names `REA_ANALYSIS_PROVIDER` | | `REA_GHIDRA_STARTUP_TIMEOUT_MS=abc`, scoped Hopper doctor | 0 | `healthy: true`; node, host, hopper checks pass | | Same invalid timeout, search-bytes | 1 | `configuration_invalid`; timeout must be a positive decimal integer | | `REA_ANALYSIS_PROVIDER=Hopper`, capabilities | 1 | `configuration_invalid`; names the provider preference | ### Typed outcome or recovery expected Doctor should return nonzero, identify the configuration setting that blocks selected native analysis, and avoid `healthy: true`. Native commands should retain their validation. The valid provider control should retain healthy success. ### Analysis or suspected cause Source-derived reasoning at the baseline: `src/cli/setupCommands.ts:123-135` reaches doctor, and `src/application/Doctor.ts:251-299` assembles readiness without the complete application-configuration validation used by the native path. `src/composition/directAnalysis.ts:17-25` binds native analysis to `parseConfig`; `src/application/DirectAnalysis.ts:246-255` returns its configuration error before session creation. `src/config/parseConfig.ts:43-67` maps both settings under test. ### Additional context This report was prepared with AI assistance and independently reproduced by a verifier. Submission-time replay confirmed the same results on current main. Related [#3306](https://github.com/morluto/rea/issues/3306), fixed by [#3755](https://github.com/morluto/rea/pull/3755), covers `REA_HOPPER_STARTUP_TIMEOUT_MS`. The current-main replay includes that fix and still reproduces the different settings reported here. [#3054](https://github.com/morluto/rea/issues/3054) concerns different Hopper launcher resolution; this reproduction supplies the same explicit launcher to every command.
Author
Owner

@matbrgz commented on GitHub (Oct 20, 2026):

Cross-referencing with canonical issue #5245 () and sibling #5475. All relate to Hopper provider environment admission, capability reporting in , and state mutations. Cataloged under Cluster AU in consolidation tracker #4330.

<!-- gh-comment-id:6292616776 --> @matbrgz commented on GitHub (Oct 20, 2026): Cross-referencing with canonical issue #5245 () and sibling #5475. All relate to Hopper provider environment admission, capability reporting in , and state mutations. Cataloged under Cluster AU in consolidation tracker #4330.
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#3315
No description provided.