[PR #2425] [CLOSED] fix(ghidra): disclose unapplied PE PDB symbol coverage #5217

Closed
opened 2026-10-31 01:04:53 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/2425
Author: @thangldw
Created: 10/13/2026
Status: ❌ Closed

Base: main ← Head: codex/fix-ghidra-pdb-limitation


📝 Commits (1)

  • aac29c9 fix(ghidra): disclose unapplied PE PDB symbol coverage

📊 Changes

6 files changed (+167 additions, -1 deletions)

View changed files

📝 bridge/ghidra/ReaGhidraBridge.java (+22 -0)
📝 docs/mcp-contracts.md (+14 -0)
📝 src/ghidra/GhidraProvider.behavior.test.ts (+71 -0)
📝 src/ghidra/GhidraProviderClient.ts (+18 -1)
📝 src/ghidra/GhidraSessionValues.test.ts (+34 -0)
📝 src/ghidra/GhidraSessionValues.ts (+8 -0)

📄 Description

Summary

Fixes #2259.

PE queries can return analysis-generated function names without disclosing that the target references unapplied PDB symbols. Report that missing coverage from Ghidra's parsed Program Information, including the declared file, GUID and age when available.

Problem and expected behavior

A source-owned PE/PDB pair is recognized by direct Ghidra 12.1.4: PDB Loaded = true, with add_numbers and main named. REA imports its immutable private target copy, returns FUN_140001000 by address, rejects the add_numbers lookup, and previously emitted no PDB limitation. Successful query Evidence should disclose the referenced but unapplied symbols without implying that the binary is stripped or the companion mismatched.

Change and scope

The Java bridge reads Ghidra's existing PdbParserConstants fields after auto-analysis. A typed optional handshake report retains identity and application status; unknown identity components remain null. PE queries consume that report through the existing startup promise/cache and add a session limitation only when a PDB reference is present and not applied.

Scope is disclosure only. No companion admission, search, copying, download or symbol-server configuration is added. Related open alternatives #2275 and #2283 were discovered during the final main update; this implementation uses Ghidra-owned parsed facts and has real CLI/MCP verification plus applied/no-reference and partial-identity controls.

Contract and boundary impact

  • Semantic owner and earliest changed stage: Ghidra PE loader/PDB analyzer facts, carried by the authenticated bridge handshake before query Evidence projection.
  • Contribution scope fit and linked maintainer decision: ordinary coverage-disclosure fix in an existing provider; new authority/provider decision not applicable.
  • CLI and MCP/tool-catalog contract: existing query schemas unchanged; adds an optional internal handshake report and an Evidence limitation.
  • Provider, bridge, target-format, or platform compatibility: Ghidra 12.1.4 verified; old handshake shape remains readable. GUID may be absent for legacy CodeView records; age is unsigned 32-bit.
  • Evidence, artifact, provenance, or reconstruction contract: original target bytes/digest and profile retained; report describes application, not complete symbol recovery.
  • Target selection, authority, upstream behavior, and cleanup details: existing target snapshot, startup, cancellation, progress and cleanup ownership reused. No target execution or mutation.
  • Generated metadata, package, or installation impact: no dependency/version change or committed generated files.

Expected effects:

  • Read existing files or captured data.
  • Launch or attach to a process. Existing Ghidra query startup; no new target execution.
  • Inject instrumentation or run scripts/code.
  • Change process memory, registers, files, or configuration.
  • Contact network services.
  • Recover protected code or work around protections.
  • Documentation or usability only; no target interaction.
  • Not sure yet; investigation or maintainer guidance needed.

Evidence and regression coverage

  • Provider regression failed on main 11fe5a1 for both unapplied and partial-identity PDB cases because no limitation was returned. Applied/no-reference controls remain free of the limitation.

  • Typed handshake tests retain nullable identity/application facts and reject malformed, missing, overflowing or undeclared fields.

  • Real Ghidra baseline and repaired CLI/MCP runs use a Clang/LLD-generated PE/PDB pair, without executing the PE. The target SHA-256 is unchanged across baseline/fixed CLI Evidence.

  • Real MCP controls also cover a PE without a debug reference and a legacy NB10 reference with unknown GUID. Queries and close_binary succeed.

  • Independent subagent full-diff review: no actionable findings.

  • Remaining proof gaps: macOS arm64 host with cross-compiled PE x86_64; no Windows/MSVC execution or live symbol-server claim. Provider/handshake unit controls are simulated and are separate from real-provider replay.

  • Observed, derived, and inferred claims remain distinguishable.

  • Artifact identity, source provenance, and failed attempts remain preserved.

  • Unsupported, incomplete, unavailable, or uncertain outcomes remain visible.

Validation performed

Node 24.18.0/npm 11.16.0, Ghidra 12.1.4, Temurin JDK 21.0.12.1+1, macOS arm64. Updated onto main 37b7550 without conflicts:

  • Focused provider, handshake, client lifecycle, target snapshot and MCP suites: 117 tests passed across 6 files.
  • Real stdio MCP replay: RSDS/unapplied, no-reference and legacy NB10 controls passed; close_binary succeeded.
  • npm run check: passed typecheck, lint, formatting, knip, metadata, module boundaries and architecture guards.
  • npm run docs:check: passed.
  • npm run verify:test-discovery: all 1003 files discovered exactly once.
  • git diff --check: passed.

Compatibility, safety, and release

  • Breaking changes or migration steps: none.
  • Real Hopper/Ghidra, browser, or OS coverage: real Ghidra CLI/MCP on macOS arm64; matching native decompiler built from the same release source. Windows/MSVC and other Ghidra releases unverified.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: declared PDB identity is preserved as source evidence; existing authenticated handshake and process ownership remain. This patch does not admit or retrieve companions.

Before merge

  • This PR addresses a concrete problem or an agreed enhancement.
  • Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff.
  • The PR has one focused outcome and the title follows type(scope): outcome.
  • Related issue is linked, or the reason for not linking one is stated above.
  • Tests cover changed observable behavior and meaningful failure paths.
  • Owning docs, contracts, and generated metadata are updated where needed.
  • User-visible CLI/MCP changes include representative output.
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/2425 **Author:** [@thangldw](https://github.com/thangldw) **Created:** 10/13/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `codex/fix-ghidra-pdb-limitation` --- ### 📝 Commits (1) - [`aac29c9`](https://github.com/morluto/rea/commit/aac29c9fd5425fbf0378acda5592add644d41f18) fix(ghidra): disclose unapplied PE PDB symbol coverage ### 📊 Changes **6 files changed** (+167 additions, -1 deletions) <details> <summary>View changed files</summary> 📝 `bridge/ghidra/ReaGhidraBridge.java` (+22 -0) 📝 `docs/mcp-contracts.md` (+14 -0) 📝 `src/ghidra/GhidraProvider.behavior.test.ts` (+71 -0) 📝 `src/ghidra/GhidraProviderClient.ts` (+18 -1) 📝 `src/ghidra/GhidraSessionValues.test.ts` (+34 -0) 📝 `src/ghidra/GhidraSessionValues.ts` (+8 -0) </details> ### 📄 Description ## Summary Fixes #2259. PE queries can return analysis-generated function names without disclosing that the target references unapplied PDB symbols. Report that missing coverage from Ghidra's parsed Program Information, including the declared file, GUID and age when available. ## Problem and expected behavior A source-owned PE/PDB pair is recognized by direct Ghidra 12.1.4: `PDB Loaded = true`, with `add_numbers` and `main` named. REA imports its immutable private target copy, returns `FUN_140001000` by address, rejects the `add_numbers` lookup, and previously emitted no PDB limitation. Successful query Evidence should disclose the referenced but unapplied symbols without implying that the binary is stripped or the companion mismatched. ## Change and scope The Java bridge reads Ghidra's existing PdbParserConstants fields after auto-analysis. A typed optional handshake report retains identity and application status; unknown identity components remain null. PE queries consume that report through the existing startup promise/cache and add a session limitation only when a PDB reference is present and not applied. Scope is disclosure only. No companion admission, search, copying, download or symbol-server configuration is added. Related open alternatives #2275 and #2283 were discovered during the final main update; this implementation uses Ghidra-owned parsed facts and has real CLI/MCP verification plus applied/no-reference and partial-identity controls. ## Contract and boundary impact - Semantic owner and earliest changed stage: Ghidra PE loader/PDB analyzer facts, carried by the authenticated bridge handshake before query Evidence projection. - Contribution scope fit and linked maintainer decision: ordinary coverage-disclosure fix in an existing provider; new authority/provider decision not applicable. - CLI and MCP/tool-catalog contract: existing query schemas unchanged; adds an optional internal handshake report and an Evidence limitation. - Provider, bridge, target-format, or platform compatibility: Ghidra 12.1.4 verified; old handshake shape remains readable. GUID may be absent for legacy CodeView records; age is unsigned 32-bit. - Evidence, artifact, provenance, or reconstruction contract: original target bytes/digest and profile retained; report describes application, not complete symbol recovery. - Target selection, authority, upstream behavior, and cleanup details: existing target snapshot, startup, cancellation, progress and cleanup ownership reused. No target execution or mutation. - Generated metadata, package, or installation impact: no dependency/version change or committed generated files. Expected effects: - [x] Read existing files or captured data. - [x] Launch or attach to a process. Existing Ghidra query startup; no new target execution. - [ ] Inject instrumentation or run scripts/code. - [ ] Change process memory, registers, files, or configuration. - [ ] Contact network services. - [ ] Recover protected code or work around protections. - [ ] Documentation or usability only; no target interaction. - [ ] Not sure yet; investigation or maintainer guidance needed. ## Evidence and regression coverage - Provider regression failed on main `11fe5a1` for both unapplied and partial-identity PDB cases because no limitation was returned. Applied/no-reference controls remain free of the limitation. - Typed handshake tests retain nullable identity/application facts and reject malformed, missing, overflowing or undeclared fields. - Real Ghidra baseline and repaired CLI/MCP runs use a Clang/LLD-generated PE/PDB pair, without executing the PE. The target SHA-256 is unchanged across baseline/fixed CLI Evidence. - Real MCP controls also cover a PE without a debug reference and a legacy NB10 reference with unknown GUID. Queries and close_binary succeed. - Independent subagent full-diff review: no actionable findings. - Remaining proof gaps: macOS arm64 host with cross-compiled PE x86_64; no Windows/MSVC execution or live symbol-server claim. Provider/handshake unit controls are simulated and are separate from real-provider replay. - [x] Observed, derived, and inferred claims remain distinguishable. - [x] Artifact identity, source provenance, and failed attempts remain preserved. - [x] Unsupported, incomplete, unavailable, or uncertain outcomes remain visible. ## Validation performed Node 24.18.0/npm 11.16.0, Ghidra 12.1.4, Temurin JDK 21.0.12.1+1, macOS arm64. Updated onto main `37b7550` without conflicts: - Focused provider, handshake, client lifecycle, target snapshot and MCP suites: 117 tests passed across 6 files. - Real stdio MCP replay: RSDS/unapplied, no-reference and legacy NB10 controls passed; close_binary succeeded. - `npm run check`: passed typecheck, lint, formatting, knip, metadata, module boundaries and architecture guards. - `npm run docs:check`: passed. - `npm run verify:test-discovery`: all 1003 files discovered exactly once. - `git diff --check`: passed. ## Compatibility, safety, and release - Breaking changes or migration steps: none. - Real Hopper/Ghidra, browser, or OS coverage: real Ghidra CLI/MCP on macOS arm64; matching native decompiler built from the same release source. Windows/MSVC and other Ghidra releases unverified. - Package or release metadata impact: none. - Security, privacy, process, or containment review: declared PDB identity is preserved as source evidence; existing authenticated handshake and process ownership remain. This patch does not admit or retrieve companions. ## Before merge - [x] This PR addresses a concrete problem or an agreed enhancement. - [x] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [x] The PR has one focused outcome and the title follows `type(scope): outcome`. - [x] Related issue is linked, or the reason for not linking one is stated above. - [x] Tests cover changed observable behavior and meaningful failure paths. - [x] Owning docs, contracts, and generated metadata are updated where needed. - [x] User-visible CLI/MCP changes include representative output. - [x] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-31 01:04:53 +00:00
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#5217
No description provided.