[GH-ISSUE #6076] [Bug] Managed inspectors classify non-PE targets as unavailable provider capabilities #3712

Closed
opened 2026-10-31 00:43:18 +00:00 by bsakaguchi · 0 comments
Owner

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

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

All three managed inspection commands report a readable non-PE executable as capability_unavailable / unsupported_provider, rather than unsupported_target. The selected path is absent from structured error details. The reason does retain the actual format: "Managed static triage requires a PE target; observed mach-o-universal."

Executed inspect-managed-artifact, inspect-managed-members, and inspect-managed-native-boundaries against /usr/bin/true; each exited 1 with that classification. Each command succeeded on a repository-generated managed PE/CLI assembly.

Reproduction

With locked dependencies and built runtime artifacts, save the following test in src/dotnet/managedInputs.repro.test.ts and run it from the repository root:

REA_REPRO_DIR="$(mktemp -d)" node node_modules/vitest/vitest.mjs run src/dotnet/managedInputs.repro.test.ts --maxWorkers=1

This is the relevant case and its controls from an executed focused test. It asserts the observed defect, so the observation test passes on the affected revision. CLI child processes, filesystem reads and parsing are real; the assembly fixture is synthetic data and is never executed.

import { spawnSync } from "node:child_process";
import { writeFileSync } from "node:fs";
import { join } from "node:path";
import { expect, it } from "vitest";
import { buildManagedPeFixture } from "./ManagedPe.fixture.js";

const directory = process.env.REA_REPRO_DIR;
if (!directory) throw new Error("Set REA_REPRO_DIR to a writable directory");
const good = join(directory, "assembly.dll");
writeFileSync(good, buildManagedPeFixture());
const run = (...args: string[]) => {
  const result = spawnSync(process.execPath,
    ["scripts/rea.mjs", ...args, "--json"], { encoding: "utf8" });
  expect(result.error).toBeUndefined();
  expect(result.stderr).toBe("");
  const json = JSON.parse(result.stdout);
  console.log(JSON.stringify({ command: args[0], exit: result.status,
    code: json.code ?? "success", category: json.category ?? null,
    partial: json.details?.partial_observation !== undefined }));
  return { exit: result.status, json };
};

it("observes non-PE classification in all three inspectors", () => {
  for (const command of ["inspect-managed-artifact", "inspect-managed-members",
    "inspect-managed-native-boundaries"]) {
    expect(run(command, good).exit).toBe(0);
    const result = run(command, "/usr/bin/true");
    expect(result).toMatchObject({ exit: 1, json: {
      code: "capability_unavailable", category: "unsupported_provider",
    } });
    expect(result.json.details.reason).toContain("observed mach-o-universal");
    expect(result.json.details.path).toBeUndefined();
  }
}, 60_000);

Expected behavior

Return the existing AnalysisUnsupportedTargetError classification with the operation, selected path and observed format. Its documented type contract describes this exact condition: a readable supplied artifact outside the operation's supported formats. Managed inspection remains limited to PE/CLI; this request does not add support for native Mach-O or ELF.

Impact and scope

P2: callers receive the wrong machine-readable refusal category and lose structured selected-path attribution. Format-based fallback can distinguish unsupported targets from missing provider capabilities only by interpreting prose in this result. The actual format remains in details.reason, which provides a practical workaround. No downstream fallback incident or incorrect successful analysis was observed.

Each of the three commands reproduced with a successful managed-input control. Execution covered universal Mach-O on macOS; ELF, thin Mach-O and other platforms were not executed. MCP shares the workflow by source inspection but its transport was not tested.

REA version

rea-agents 6.7.0; source revision 52415975942a4b9c53a817915b313ccc404f280e.

Runtime and platform

macOS 27.0.1 arm64; Node.js v24.18.0 (repository pin); locked Vitest 5.0.3. Initial manual CLI probes also reproduced on Node.js v26.12.0. No external analysis engine.

Target and artifact context

Readable universal Mach-O system executable, supplied as an explicit path. Positive controls used a synthetic PE/CLI assembly from the repository fixture generator. No assembly or system executable was run as a target.

Interface

CLI

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

Representative actual error from inspect-managed-members /usr/bin/true --json:

{
  "error": "Analysis failed",
  "code": "capability_unavailable",
  "category": "unsupported_provider",
  "message": "This analysis is unavailable for the current target. Choose another analysis or target.",
  "retryable": false,
  "remediation": {
    "action": "This analysis is unavailable for the current target. Choose another analysis or target."
  },
  "details": {
    "provider_id": "rea-dotnet-static",
    "operation": "inspect_managed_members",
    "reason": "Managed static triage requires a PE target; observed mach-o-universal."
  }
}

The artifact and native-boundary commands returned the same code/category/detail shape with their respective operation names. All three managed assembly controls exited 0.

Typed outcome or recovery expected

AnalysisUnsupportedTargetError / unsupported_target, category unsupported_target, with operation/path/reason and advice to choose a supported target or an operation supporting its format. Keep provider-capability errors for genuinely unimplemented operations.

Analysis or suspected cause

Source-derived: the non-PE guard uses the same AnalysisCapabilityUnavailableError type as the adjacent unimplemented-operation guard, although these refusals have different causes. Error-code mapping preserves that choice. Unsupported-target details include the selected path; capability details do not. The MCP registration forwards explicit paths to the same managed workflow; that adapter reachability is source-derived.

Additional context

#553 concerned a different explicit-target routing problem through a native session. #2191 / PR #2194 concern malformed PE layouts, after the non-PE check. Related reports #5985, #5988, #5990 (including its verification comment), #6063, #6065 and #6068 concern abort causes, supplied Evidence identities/roles, cleanup ownership or source mutation. None changes this format-refusal producer. The field-path reports #5950, #5971, #5980, #6001, #6003 and #6034 concern different validators or parent parsers.

An operation being available does not imply it accepts every target format; this report concerns how the explicit format constraint is classified. Fetched upstream main f86206535f8ec71014781f9d432a84b01e183e5d retains the managed format guard and relevant error mappings. Newer main was inspected, not executed. No regression range was established.

Originally created by @coygeek on GitHub (Oct 21, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6076 ### 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 All three managed inspection commands report a readable non-PE executable as `capability_unavailable` / `unsupported_provider`, rather than `unsupported_target`. The selected path is absent from structured error details. The reason does retain the actual format: "Managed static triage requires a PE target; observed mach-o-universal." Executed `inspect-managed-artifact`, `inspect-managed-members`, and `inspect-managed-native-boundaries` against `/usr/bin/true`; each exited 1 with that classification. Each command succeeded on a repository-generated managed PE/CLI assembly. ### Reproduction With locked dependencies and built runtime artifacts, save the following test in `src/dotnet/managedInputs.repro.test.ts` and run it from the repository root: ```sh REA_REPRO_DIR="$(mktemp -d)" node node_modules/vitest/vitest.mjs run src/dotnet/managedInputs.repro.test.ts --maxWorkers=1 ``` This is the relevant case and its controls from an executed focused test. It asserts the observed defect, so the observation test passes on the affected revision. CLI child processes, filesystem reads and parsing are real; the assembly fixture is synthetic data and is never executed. ```ts import { spawnSync } from "node:child_process"; import { writeFileSync } from "node:fs"; import { join } from "node:path"; import { expect, it } from "vitest"; import { buildManagedPeFixture } from "./ManagedPe.fixture.js"; const directory = process.env.REA_REPRO_DIR; if (!directory) throw new Error("Set REA_REPRO_DIR to a writable directory"); const good = join(directory, "assembly.dll"); writeFileSync(good, buildManagedPeFixture()); const run = (...args: string[]) => { const result = spawnSync(process.execPath, ["scripts/rea.mjs", ...args, "--json"], { encoding: "utf8" }); expect(result.error).toBeUndefined(); expect(result.stderr).toBe(""); const json = JSON.parse(result.stdout); console.log(JSON.stringify({ command: args[0], exit: result.status, code: json.code ?? "success", category: json.category ?? null, partial: json.details?.partial_observation !== undefined })); return { exit: result.status, json }; }; it("observes non-PE classification in all three inspectors", () => { for (const command of ["inspect-managed-artifact", "inspect-managed-members", "inspect-managed-native-boundaries"]) { expect(run(command, good).exit).toBe(0); const result = run(command, "/usr/bin/true"); expect(result).toMatchObject({ exit: 1, json: { code: "capability_unavailable", category: "unsupported_provider", } }); expect(result.json.details.reason).toContain("observed mach-o-universal"); expect(result.json.details.path).toBeUndefined(); } }, 60_000); ``` ### Expected behavior Return the existing `AnalysisUnsupportedTargetError` classification with the operation, selected path and observed format. Its [documented type contract](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/domain/analysisErrorCore.ts#L7-L21) describes this exact condition: a readable supplied artifact outside the operation's supported formats. Managed inspection remains limited to PE/CLI; this request does not add support for native Mach-O or ELF. ### Impact and scope P2: callers receive the wrong machine-readable refusal category and lose structured selected-path attribution. Format-based fallback can distinguish unsupported targets from missing provider capabilities only by interpreting prose in this result. The actual format remains in details.reason, which provides a practical workaround. No downstream fallback incident or incorrect successful analysis was observed. Each of the three commands reproduced with a successful managed-input control. Execution covered universal Mach-O on macOS; ELF, thin Mach-O and other platforms were not executed. MCP shares the workflow by source inspection but its transport was not tested. ### REA version rea-agents 6.7.0; source revision `52415975942a4b9c53a817915b313ccc404f280e`. ### Runtime and platform macOS 27.0.1 arm64; Node.js v24.18.0 (repository pin); locked Vitest 5.0.3. Initial manual CLI probes also reproduced on Node.js v26.12.0. No external analysis engine. ### Target and artifact context Readable universal Mach-O system executable, supplied as an explicit path. Positive controls used a synthetic PE/CLI assembly from the repository fixture generator. No assembly or system executable was run as a target. ### Interface CLI ### Earliest failure stage Native analysis or reconstruction ### Relevant output or evidence Representative actual error from `inspect-managed-members /usr/bin/true --json`: ```json { "error": "Analysis failed", "code": "capability_unavailable", "category": "unsupported_provider", "message": "This analysis is unavailable for the current target. Choose another analysis or target.", "retryable": false, "remediation": { "action": "This analysis is unavailable for the current target. Choose another analysis or target." }, "details": { "provider_id": "rea-dotnet-static", "operation": "inspect_managed_members", "reason": "Managed static triage requires a PE target; observed mach-o-universal." } } ``` The artifact and native-boundary commands returned the same code/category/detail shape with their respective operation names. All three managed assembly controls exited 0. ### Typed outcome or recovery expected `AnalysisUnsupportedTargetError` / `unsupported_target`, category `unsupported_target`, with operation/path/reason and advice to choose a supported target or an operation supporting its format. Keep provider-capability errors for genuinely unimplemented operations. ### Analysis or suspected cause Source-derived: the [non-PE guard](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/dotnet/ManagedStaticProvider.ts#L80-L95) uses the same AnalysisCapabilityUnavailableError type as the adjacent unimplemented-operation guard, although these refusals have different causes. [Error-code mapping](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/domain/analysisErrorProjection.ts#L242-L250) preserves that choice. [Unsupported-target details](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/domain/analysisErrorProjection.ts#L298-L303) include the selected path; [capability details](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/domain/analysisErrorProjection.ts#L396-L401) do not. The [MCP registration](https://github.com/morluto/rea/blob/52415975942a4b9c53a817915b313ccc404f280e/src/server/registerManagedTools.ts#L54-L59) forwards explicit paths to the same managed workflow; that adapter reachability is source-derived. ### Additional context #553 concerned a different explicit-target routing problem through a native session. #2191 / PR #2194 concern malformed PE layouts, after the non-PE check. Related reports #5985, #5988, #5990 (including its verification comment), #6063, #6065 and #6068 concern abort causes, supplied Evidence identities/roles, cleanup ownership or source mutation. None changes this format-refusal producer. The field-path reports #5950, #5971, #5980, #6001, #6003 and #6034 concern different validators or parent parsers. An operation being available does not imply it accepts every target format; this report concerns how the explicit format constraint is classified. Fetched upstream main `f86206535f8ec71014781f9d432a84b01e183e5d` retains the managed format guard and relevant error mappings. Newer main was inspected, not executed. No regression range was established.
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#3712
No description provided.