feat(dotnet): add managed runtime correlation planning

This commit is contained in:
N0zoM1z0
2026-07-16 19:01:07 +08:00
committed by N0zoM1z0
parent 2b75fcfaac
commit 5f66cfd57a
149 changed files with 2034 additions and 365 deletions
+79 -1
View File
@@ -9,6 +9,10 @@ import { inspectManagedArtifactBytes } from "../dist/dotnet/ManagedArtifactInspe
import { inspectManagedMembersBytes } from "../dist/dotnet/ManagedMemberInspector.js";
import { inspectManagedNativeBoundariesBytes } from "../dist/dotnet/ManagedNativeBoundaryInspector.js";
import { compareManagedMemberPaths } from "../dist/application/ManagedMemberComparisonService.js";
import { planManagedRuntimeCorrelationEvidence } from "../dist/application/ManagedRuntimeCorrelationService.js";
import { createPermissionAuthority } from "../dist/application/PermissionAuthority.js";
import { MANAGED_STATIC_PROVIDER } from "../dist/application/InvestigationProviders.js";
import { createEvidence } from "../dist/domain/evidence.js";
import {
alternateMvid,
buildManagedPeFixture,
@@ -178,6 +182,78 @@ try {
assert.equal(obfuscatedMembers.types.items[0]?.full_name, "Fixture.ꙮType");
assert.equal(obfuscatedMembers.methods.items[0]?.name, "λ⛧");
assert.equal(obfuscatedMembers.fields.items[0]?.name, "字段");
const runtimeExecutable = join(workspace, "dotnet");
await writeFile(runtimeExecutable, "#!/bin/sh\n");
const runtimeCeiling = {
capability: "managed_runtime",
roots: [workspace],
executables: [runtimeExecutable],
environment_names: [],
network: "none",
mount: false,
};
const runtimeAuthority = await createPermissionAuthority(
[runtimeCeiling],
[
{
...runtimeCeiling,
grant_id: "administrator:managed_runtime",
lifetime: "administrator",
operation_identity: null,
expires_at: null,
},
],
);
assert.equal(runtimeAuthority.ok, true);
const runtimeMethod = obfuscatedMembers.methods.items[0];
assert.ok(runtimeMethod);
const runtimePlan = await planManagedRuntimeCorrelationEvidence(
{
policy: {
enabled: true,
roots: [workspace],
executablePath: runtimeExecutable,
},
authority: runtimeAuthority.value,
},
{
static_members: createEvidence(undefined, MANAGED_STATIC_PROVIDER, {
operation: "inspect_managed_members",
parameters: { path: obfuscated.path },
result: obfuscatedMembers,
rawResult: null,
limitations: obfuscatedMembers.limitations,
}),
method: {
token: runtimeMethod.token,
signature_sha256: runtimeMethod.signature.raw_sha256,
normalized_il_sha256: runtimeMethod.body.normalized_il_sha256,
},
requested_effect: "debugger",
host: {
os: "linux",
clr_family: "dotnet",
architecture: "x86_64",
},
bounds: {
timeout_ms: 5_000,
max_threads: 32,
max_output_bytes: 65_536,
allow_network: false,
allow_ui: false,
},
},
);
assert.equal(runtimePlan.ok, true);
assert.equal(runtimePlan.value.normalized_result.executed, false);
assert.equal(
runtimePlan.value.normalized_result.authority_model.capability,
"managed_runtime",
);
assert.equal(
runtimePlan.value.normalized_result.effect_taxonomy.uses_debugger,
true,
);
const left = await fixture("token-drift-left.exe", {
methodName: "StableSemanticSlice",
@@ -235,18 +311,20 @@ try {
process.stdout.write(
`${JSON.stringify({
verified: 7,
verified: 8,
managedSurfaces: [
"inspect_managed_artifact",
"inspect_managed_members",
"inspect_managed_native_boundaries",
"compare_managed_members",
"plan_managed_runtime_correlation",
],
coverage: [
"modern-dotnet-anycpu",
"dotnet-framework-x86-pinvoke",
"x64-ready-to-run-native-body",
"unicode-obfuscated-identifiers",
"runtime-correlation-admission-plan",
"mvid-and-token-drift",
"not-managed",
"malformed-metadata",
+51 -1
View File
@@ -265,6 +265,56 @@ try {
managedMembers.normalized_result?.methods?.total !== 1
)
throw new Error("packaged managed member CLI failed");
const managedMethod = managedMembers.normalized_result.methods.items[0];
const managedRuntimePlanInput = {
static_members: managedMembers,
method: {
token: managedMethod.token,
signature_sha256: managedMethod.signature.raw_sha256,
normalized_il_sha256: managedMethod.body.normalized_il_sha256,
},
requested_effect: "attach",
host: {
os: "linux",
clr_family: "dotnet",
architecture: "x86_64",
},
bounds: {
timeout_ms: 5_000,
max_threads: 32,
max_output_bytes: 65_536,
allow_network: false,
allow_ui: false,
},
};
const managedRuntimePlan = json(
await run(
cli,
[
"plan-managed-runtime-correlation",
JSON.stringify(managedRuntimePlanInput),
"--json",
],
{
...environment,
REA_MANAGED_RUNTIME_ENABLED: "true",
REA_MANAGED_RUNTIME_ROOTS_JSON: JSON.stringify([workspace]),
REA_MANAGED_RUNTIME_EXECUTABLE_PATH: process.execPath,
},
),
);
if (
managedRuntimePlan.operation !== "plan_managed_runtime_correlation" ||
managedRuntimePlan.provider?.id !== "rea-dotnet-workflows" ||
managedRuntimePlan.normalized_result?.executed !== false ||
managedRuntimePlan.normalized_result?.authority_model?.capability !==
"managed_runtime" ||
managedRuntimePlan.normalized_result?.effect_taxonomy?.attaches_process !==
true ||
managedRuntimePlan.normalized_result?.effect_taxonomy
?.invokes_target_code !== false
)
throw new Error("packaged managed runtime-correlation CLI failed");
const managedBoundaries = json(
await run(
cli,
@@ -844,7 +894,7 @@ try {
}
process.stdout.write(
`${JSON.stringify({ cli: true, analysisCli: true, artifactCli: true, managedCli: true, evidenceCli: true, incurMcpCommand: "npx -y rea-agents mcp", doctor: "platform-appropriate", setup: supportedSetupHost ? "planned-then-idempotent" : "unsupported-host-rejected", setupPlanReadOnly: supportedSetupHost, existingHopperPreserved: supportedSetupHost, clients: supportedSetupHost ? 3 : 0, backupReadback: supportedSetupHost, failureRecovery: supportedSetupHost, configSymlinkLifecycle: supportedSetupHost, skill: supportedSetupHost, mcpTools: TOOL_CONTRACTS.length, mcpPrompts: prompts.names.length, promptCompletion: true, promptCompletionLifecycle: true, evidenceMcp: true, targetFree: true, targetLifecycle: true, boundedRegexBridge: true })}\n`,
`${JSON.stringify({ cli: true, analysisCli: true, artifactCli: true, managedCli: true, managedRuntimePlanCli: true, evidenceCli: true, incurMcpCommand: "npx -y rea-agents mcp", doctor: "platform-appropriate", setup: supportedSetupHost ? "planned-then-idempotent" : "unsupported-host-rejected", setupPlanReadOnly: supportedSetupHost, existingHopperPreserved: supportedSetupHost, clients: supportedSetupHost ? 3 : 0, backupReadback: supportedSetupHost, failureRecovery: supportedSetupHost, configSymlinkLifecycle: supportedSetupHost, skill: supportedSetupHost, mcpTools: TOOL_CONTRACTS.length, mcpPrompts: prompts.names.length, promptCompletion: true, promptCompletionLifecycle: true, evidenceMcp: true, targetFree: true, targetLifecycle: true, boundedRegexBridge: true })}\n`,
);
} finally {
if (tarball) await rm(join(root, tarball), { force: true });