From 1926fc2dace081987c0b70f2a79c1d87e606bcbd Mon Sep 17 00:00:00 2001 From: Entrpi <133157614+Entrpi@users.noreply.github.com> Date: Sat, 31 Oct 2026 01:30:23 +1100 Subject: [PATCH] fix(ida): admit architecture families by allowlist (#7485) IDA refused MIPS, RISC-V, PowerPC, Hexagon and arm64_32 by denylist, so any family nobody excluded was reported supported, and the label ternary printed "Hexagon" for any other metadata family. Admit exactly the families IDA admits today (x86, x86_64, arm, arm64) and name every other family from its own architecture id. Families that Ghidra admits keep the pointer to a Ghidra profile. Refusal text now uses architecture ids, for example "no verified mips lane" instead of "no verified MIPS lane". --- docs/ida-provider.md | 6 +++++ src/ida/IdaProvider.test.ts | 33 +++++++++++++++++++++++- src/ida/IdaProvider.ts | 50 ++++++++++++++++++------------------- 3 files changed, 62 insertions(+), 27 deletions(-) diff --git a/docs/ida-provider.md b/docs/ida-provider.md index 9f2a2f262a..685d638b9a 100644 --- a/docs/ida-provider.md +++ b/docs/ida-provider.md @@ -220,6 +220,12 @@ For guided registration, set `REA_IDA_MCP_CONFIG` before `rea setup --client { ).toMatchObject({ status: "unsupported", code: "architecture_unsupported", - reason: expect.stringContaining("Hexagon"), + reason: expect.stringMatching(/hexagon.*Ghidra/su), }); }); + it("admits only the families IDA admits today, so new families stay refused", () => { + const config = parseConfig({}); + if (!config.ok) throw new Error("expected valid configuration"); + const provider = new IdaProvider(config.value, {}); + const admitted: readonly string[] = ["x86", "x86_64", "arm", "arm64"]; + for (const architecture of BINARY_ARCHITECTURES) { + // Admission reads only kind, format and family, so one ELF shape + // covers every recognized family, including any added later. + const support = provider.inspectTargetSupport({ + path: "/tmp/fixture.elf", + sha256: "a".repeat(64), + kind: "executable", + format: "elf", + architecture, + availableArchitectures: [architecture], + } as BinaryTarget); + expect(support, architecture).toMatchObject( + admitted.includes(architecture) + ? { status: "supported" } + : { + status: "unsupported", + code: "architecture_unsupported", + reason: expect.stringContaining(architecture), + }, + ); + } + }); it("declines thin arm64_32 Mach-O targets without a verified lane", () => { const config = parseConfig({}); if (!config.ok) throw new Error("expected valid configuration"); diff --git a/src/ida/IdaProvider.ts b/src/ida/IdaProvider.ts index f670c16e15..47730e621a 100644 --- a/src/ida/IdaProvider.ts +++ b/src/ida/IdaProvider.ts @@ -8,6 +8,7 @@ import { import type { AnalysisProfileCommitment } from "../domain/analysisProfile.js"; import { isElfMetadataArchitecture, + type BinaryArchitecture, type BinaryTarget, } from "../domain/binaryTargetTypes.js"; import { err, ok } from "../domain/result.js"; @@ -53,6 +54,17 @@ import { ProviderCleanupError } from "../domain/providerCleanupError.js"; import type { ProviderInspectionScope } from "../application/ProviderInspectionScope.js"; import type { ProviderRejectionCode } from "../domain/providerSelection.js"; +/** + * Families IDA admits today. Every other family is refused, including families + * that REA recognizes after this list was written. + */ +const IDA_ARCHITECTURES = new Set([ + "x86", + "x86_64", + "arm", + "arm64", +]); + /** Bring-your-own IDA MCP candidate; discovery performs no provider startup. */ export class IdaProvider implements AnalysisProviderCandidate { readonly #ownedResources = new ArtifactResourceScope(); @@ -300,32 +312,6 @@ export class IdaProvider implements AnalysisProviderCandidate { "IDA does not admit caller-selected GameCube DOL images. Open the target with Ghidra and select format gamecube-dol.", diagnostics, }; - if ( - target.kind === "executable" && - (isElfMetadataArchitecture(target.architecture) || - target.architecture === "hexagon") - ) - return { - status: "unsupported", - code: "architecture_unsupported", - reason: `REA's IDA adapter has no verified ${ - target.architecture === "mips" - ? "MIPS" - : target.architecture === "riscv" - ? "RISC-V" - : target.architecture === "powerpc" - ? "PowerPC" - : "Hexagon" - } lane. Select a supported Ghidra profile instead.`, - diagnostics, - }; - if (target.kind === "executable" && target.architecture === "arm64_32") - return { - status: "unsupported", - code: "architecture_unsupported", - reason: "REA's IDA adapter has no verified arm64_32 lane.", - diagnostics, - }; if (target.kind !== "executable") return { status: "unsupported", @@ -342,6 +328,18 @@ export class IdaProvider implements AnalysisProviderCandidate { "IDA does not admit headerless raw binaries. Open the target with Ghidra and supply architecture and entry_point.", diagnostics, }; + if (!IDA_ARCHITECTURES.has(target.architecture)) + return { + status: "unsupported", + code: "architecture_unsupported", + // Header-declared families that Ghidra admits keep the pointer there. + reason: + isElfMetadataArchitecture(target.architecture) || + target.architecture === "hexagon" + ? `REA's IDA adapter has no verified ${target.architecture} lane. Select a supported Ghidra profile instead.` + : `REA's IDA adapter has no verified ${target.architecture} lane.`, + diagnostics, + }; return target.format === "mach-o-universal" ? { status: "unknown",