Files
rea/tests/boundary/filesystem/managedRuntimeCorrelation.test.ts
T

238 lines
7.7 KiB
TypeScript

import { writeFile } from "node:fs/promises";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
import {
MANAGED_RUNTIME_DISABLED,
planManagedRuntimeCorrelationEvidence,
type ManagedRuntimePolicy,
} from "../../../src/application/ManagedRuntimeCorrelationService.js";
import { MANAGED_STATIC_PROVIDER } from "../../../src/application/InvestigationProviders.js";
import { createPermissionAuthority } from "../../../src/application/PermissionAuthority.js";
import { createEvidence } from "../../../src/domain/evidence.js";
import {
managedRuntimeCorrelationInputSchema,
managedRuntimeCorrelationResultSchema,
} from "../../../src/domain/managedRuntimeCorrelation.js";
import type { PermissionCeiling } from "../../../src/domain/permissionPolicy.js";
import { inspectManagedMembersBytes } from "../../../src/dotnet/ManagedMemberInspector.js";
import {
buildManagedPeFixture,
managedPeFixtureTarget,
} from "../../../src/dotnet/ManagedPe.fixture.js";
describe("managed runtime correlation planning", () => {
it("fails closed while the managed runtime authority is disabled", async () => {
const fixture = inspect(buildManagedPeFixture(), "/tmp/disabled.dll");
const result = await planManagedRuntimeCorrelationEvidence(
{
policy: () => MANAGED_RUNTIME_DISABLED,
authority: undefined,
},
inputFor(fixture.evidence, fixture.method),
);
expect(result.ok).toBe(false);
if (result.ok) return;
expect(result.error._tag).toBe("AnalysisCapabilityUnavailableError");
});
it("requires an explicit managed_runtime grant under an enabled ceiling", async () => {
const directory = await createTestTempDirectory("rea-managed-runtime-");
const artifactPath = join(directory, "fixture.dll");
const executablePath = join(directory, "dotnet");
await writeFile(artifactPath, buildManagedPeFixture());
await writeFile(executablePath, "#!/bin/sh\n");
const fixture = inspect(buildManagedPeFixture(), artifactPath);
const authority = await authorityFor(directory, executablePath, false);
const result = await planManagedRuntimeCorrelationEvidence(
{
policy: () => enabledPolicy(directory, executablePath),
authority,
},
inputFor(fixture.evidence, fixture.method),
);
expect(result.ok).toBe(false);
if (result.ok) return;
expect(result.error._tag).toBe("PermissionRequiredError");
});
it("records an exact-build non-executing admission plan when authorized", async () => {
const directory = await createTestTempDirectory("rea-managed-runtime-");
const artifactPath = join(directory, "fixture.dll");
const executablePath = join(directory, "dotnet");
await writeFile(artifactPath, buildManagedPeFixture());
await writeFile(executablePath, "#!/bin/sh\n");
const fixture = inspect(buildManagedPeFixture(), artifactPath);
const policy = enabledPolicy(directory, executablePath);
const authority = await authorityFor(directory, executablePath, true);
const result = await planManagedRuntimeCorrelationEvidence(
{ policy: () => policy, authority },
inputFor(fixture.evidence, fixture.method),
);
expect(result.ok).toBe(true);
if (!result.ok) return;
expect(result.value.operation).toBe("plan_managed_runtime_correlation");
expect(result.value.confidence).toBe("derived");
expect(result.value.authority).toBe("analyst-inference");
const plan = managedRuntimeCorrelationResultSchema.parse(
result.value.normalized_result,
);
expect(
managedRuntimeCorrelationInputSchema.safeParse({
...inputFor(fixture.evidence, fixture.method),
bounds: {
timeout_ms: 60_001,
max_threads: 257,
max_output_bytes: 1_048_577,
allow_network: false,
allow_ui: false,
},
}).success,
).toBe(true);
expect(
managedRuntimeCorrelationResultSchema.safeParse({
...plan,
limitations: Array.from({ length: 1_001 }, () => "x".repeat(4_097)),
}).success,
).toBe(true);
expect(plan).toMatchObject({
executed: false,
authority_model: {
capability: "managed_runtime",
default_enabled: false,
per_call_approval_required: true,
},
method_lock: {
token: "0x06000001",
exact_build_required: true,
},
requested_runtime: {
effect: "instrumentation",
executable_path: executablePath,
network: "none",
},
effect_taxonomy: {
instruments_code: true,
invokes_target_code: false,
},
unsupported_until_executor_exists: true,
});
});
it("rejects a method lock that no longer matches static Evidence", async () => {
const directory = await createTestTempDirectory("rea-managed-runtime-");
const artifactPath = join(directory, "fixture.dll");
const executablePath = join(directory, "dotnet");
await writeFile(artifactPath, buildManagedPeFixture());
await writeFile(executablePath, "#!/bin/sh\n");
const fixture = inspect(buildManagedPeFixture(), artifactPath);
const authority = await authorityFor(directory, executablePath, true);
const result = await planManagedRuntimeCorrelationEvidence(
{
policy: () => enabledPolicy(directory, executablePath),
authority,
},
{
...inputFor(fixture.evidence, fixture.method),
method: {
...inputFor(fixture.evidence, fixture.method).method,
normalized_il_sha256: "0".repeat(64),
},
},
);
expect(result.ok).toBe(false);
if (result.ok) return;
expect(result.error._tag).toBe("AnalysisInputError");
});
});
const enabledPolicy = (
root: string,
executablePath: string,
): ManagedRuntimePolicy => ({
status: "enabled",
roots: [root],
executablePath,
});
const authorityFor = async (
root: string,
executablePath: string,
granted: boolean,
) => {
const ceiling: PermissionCeiling = {
capability: "managed_runtime",
roots: [root],
executables: [executablePath],
environment_names: [],
network: "none",
mount: false,
};
const authority = await createPermissionAuthority(
[ceiling],
granted
? [
{
...ceiling,
grant_id: "administrator:managed_runtime",
lifetime: "administrator",
operation_identity: null,
expires_at: null,
},
]
: [],
);
if (!authority.ok) throw authority.error;
return authority.value;
};
const inputFor = (
staticMembers: ReturnType<typeof createEvidence>,
method: ReturnType<typeof inspect>["method"],
) => ({
static_members: staticMembers,
method: {
token: method.token,
signature_sha256: method.signature.raw_sha256,
normalized_il_sha256: method.body.normalized_il_sha256,
},
requested_effect: "instrumentation" as const,
host: {
os: "linux" as const,
clr_family: "dotnet" as const,
architecture: "x86_64" as const,
},
bounds: {
timeout_ms: 5_000,
max_threads: 32,
max_output_bytes: 65_536,
allow_network: false as const,
allow_ui: false as const,
},
});
const inspect = (bytes: Buffer, path: string) => {
const target = managedPeFixtureTarget(bytes, path);
const result = inspectManagedMembersBytes(bytes, target);
const method = result.methods[0];
if (method === undefined) throw new Error("fixture has no method");
return {
result,
method,
evidence: createEvidence(target, MANAGED_STATIC_PROVIDER, {
operation: "inspect_managed_members",
parameters: {},
result,
rawResult: null,
limitations: result.limitations,
}),
};
};