fix(mcp): accept authentic native Evidence for managed boundary verification (#4761)

The MCP verify_managed_native_boundaries handler resolved native
observations through an inspect_macho/analyze_function allowlist before
calling the shared verification service, and reported any other authentic
operation as evidence_integrity_mismatch. The domain already owns which
native operations it can read symbols from and counts the rest as
unsupported, which is what the CLI returns. The MCP resolver now only
authenticates native observations and leaves operation support to the
shared workflow, so both adapters return the same partial verification.

Fixes #4639

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kaoru0822andClaude Opus 5.5 authored and GitHub committed 2026-10-17 04:27:06 -07:00
1 parent f1ab5959bd
commit f03a55909d
2 files changed
+136 -12

No files matched your search

@@ -4,20 +4,25 @@ import { EvidenceIntegrityError } from "../../domain/evidenceErrors.js";
import type { Result } from "../../domain/result.js";
import { err, ok } from "../../domain/result.js";
/**
* Authenticate caller-supplied records. When `expectedOperations` is omitted,
* the shared workflow owns which authentic operations it can use.
*/
const parseExpectedEvidence = (
rawEvidence: readonly Evidence[],
expectedOperations: readonly string[],
expectedOperations?: readonly string[],
): Result<Evidence[], EvidenceIntegrityError> => {
try {
const evidence = rawEvidence.map(parseEvidence);
for (const record of evidence)
if (
!expectedOperations.includes(record.operation) ||
record.predicate_type !== "rea.analysis"
)
throw new TypeError(
`Expected ${expectedOperations.join(" or ")} Evidence, received ${record.operation}`,
);
if (expectedOperations !== undefined)
for (const record of evidence)
if (
!expectedOperations.includes(record.operation) ||
record.predicate_type !== "rea.analysis"
)
throw new TypeError(
`Expected ${expectedOperations.join(" or ")} Evidence, received ${record.operation}`,
);
return ok(evidence);
} catch (cause: unknown) {
return err(
@@ -43,11 +48,14 @@ export const resolveManagedBoundaryEvidence = (
): Result<Evidence[], EvidenceIntegrityError> =>
parseExpectedEvidence([evidence], ["inspect_managed_native_boundaries"]);
/**
* Authenticate native observations without an operation allowlist: the domain
* counts authentic operations it cannot read symbols from as unsupported.
*/
export const resolveNativeEvidence = (
evidence: readonly Evidence[],
): Result<Evidence[], EvidenceIntegrityError> => {
return parseExpectedEvidence(evidence, ["inspect_macho", "analyze_function"]);
};
): Result<Evidence[], EvidenceIntegrityError> =>
parseExpectedEvidence(evidence);
export const sourceEvidence = (input: {
readonly managed_artifact?: Evidence | undefined;
@@ -0,0 +1,116 @@
import { Client } from "@modelcontextprotocol/client";
import { StdioClientTransport } from "@modelcontextprotocol/client/stdio";
import { writeFile } from "node:fs/promises";
import { join, resolve } from "node:path";
import { afterAll, beforeAll, expect } from "vitest";
import { createEvidence, parseEvidence } from "../../../src/domain/evidence.js";
import { managedNativeVerificationResultSchema } from "../../../src/domain/managed/managedNativeVerificationSchemas.js";
import { buildManagedPeFixture } from "../../../src/dotnet/ManagedPe.fixture.js";
import { parseMcpToolError } from "../../fixtures/mcpToolError.js";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
import { cliTest } from "../../support/cli/cliFixture.js";
const client = new Client({ name: "managed-native-adapters", version: "1" });
const transport = new StdioClientTransport({
command: process.execPath,
args: [resolve("scripts/rea.mjs"), "mcp"],
cwd: process.cwd(),
env: { PATH: process.env.PATH ?? "" },
stderr: "pipe",
});
beforeAll(async () => {
await client.connect(transport);
transport.stderr?.on("data", () => undefined);
});
afterAll(async () => {
await Promise.all([client.close(), transport.close()]);
});
/** Authentic native Evidence whose operation the workflow cannot read symbols from. */
const signatureEvidence = () =>
createEvidence(
{
path: "/usr/bin/true",
sha256: "a".repeat(64),
format: "mach-o",
architecture: "arm64",
},
{ id: "native", name: "Native", version: "simulated" },
{
operation: "inspect_signature",
parameters: {},
result: { signed: true },
limitations: ["No native provider executed."],
},
);
cliTest(
"counts authentic unsupported native Evidence identically through MCP and CLI",
async ({ cli }) => {
const root = await createTestTempDirectory("rea-managed-native-adapters-");
const path = join(root, "fixture.dll");
await writeFile(path, buildManagedPeFixture({ pinvoke: {} }));
const inspected = await client.callTool({
name: "inspect_managed_native_boundaries",
arguments: { path },
});
expect(inspected.isError).not.toBe(true);
const managed = parseEvidence(inspected.structuredContent);
const native = signatureEvidence();
const input = {
managed_boundaries: managed,
native_observations: [native],
};
const mcp = await client.callTool({
name: "verify_managed_native_boundaries",
arguments: input,
});
expect(mcp.isError, JSON.stringify(mcp.content)).not.toBe(true);
const mcpResult = managedNativeVerificationResultSchema.parse(
parseEvidence(mcp.structuredContent).normalized_result,
);
const request = join(root, "verify.json");
await writeFile(request, JSON.stringify(input));
const cliRun = await cli.run({
arguments: ["verify-managed-native-boundaries", request, "--json"],
});
expect(cliRun.exitCode, cliRun.stderr).toBe(0);
const cliResult = managedNativeVerificationResultSchema.parse(
parseEvidence(cliRun.json).normalized_result,
);
expect(mcpResult).toEqual(cliResult);
expect(mcpResult).toMatchObject({
native_observations: {
total: 1,
accepted: 0,
unsupported: 1,
symbols: 0,
},
summary: { unresolved: 1 },
pinvoke_imports: [
expect.objectContaining({ basis: "unsupported-native-evidence" }),
],
coverage: { status: "partial" },
evidence_links: [managed.evidence_id, native.evidence_id],
});
expect(mcpResult.limitations).toContain(
"Some native Evidence operations were unsupported by this workflow.",
);
const tampered = await client.callTool({
name: "verify_managed_native_boundaries",
arguments: {
...input,
native_observations: [{ ...native, operation: "inspect_macho" }],
},
});
expect(parseMcpToolError(tampered)).toMatchObject({
error: { code: "evidence_integrity_mismatch" },
});
},
60_000,
);