Add rea environment-serve <manifest.json> --evidence <capture.json> [--host] [--port]: it loads an environment-manifest view and the capture Evidence it was projected from, refuses a manifest whose parent evidence id does not match the capture, builds one MCP tool per manifest tool and serves them over streamable HTTP beside an environment card at /.well-known/agent-env.json and a data plane at /agentenv that refuses every method. Each tool call replays the retained record whose path and query values best match the arguments, cites the record ordinal and evidence id, marks replayed content as untrusted target content, and truncates bodies over 256 KiB with a flag. Nothing executes the captured application. Refs morluto/rea#4933 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
156 lines
7.9 KiB
TypeScript
156 lines
7.9 KiB
TypeScript
import { registerCaptureCommands } from "./cli/captureCommands.js";
|
|
import { registerSignalCommands } from "./cli/signalCommands.js";
|
|
import { registerWasmCommands } from "./cli/wasmCommands.js";
|
|
import { snapshotEnvironment } from "./process/snapshotEnvironment.js";
|
|
import { createDirectAnalysis } from "./composition/directAnalysis.js";
|
|
import { registerEvmCommands } from "./cli/evmCommands.js";
|
|
import { registerGoCommands } from "./cli/goCommands.js";
|
|
import { registerRustCommands } from "./cli/rustCommands.js";
|
|
import { registerSqliteCommands } from "./cli/sqliteCommands.js";
|
|
import { registerAnalysisViewCommands } from "./cli/analysisViewCommands.js";
|
|
import { registerBinaryDiagnosticsCommands } from "./cli/binaryDiagnosticsCommands.js";
|
|
import { registerFridaCommands } from "./cli/fridaCommands.js";
|
|
import type { FridaInstrumentationPort } from "./application/frida/FridaInstrumentationPort.js";
|
|
import { Cli } from "incur";
|
|
import { normalizeCliArguments } from "./cliOutput.js";
|
|
|
|
import { createLogger, parseLogLevel } from "./logger.js";
|
|
import { projectAnalysisError } from "./domain/analysisErrorProjection.js";
|
|
import { PRODUCT_IDENTITY } from "./identity.js";
|
|
import { npxRegistrationCommand } from "./application/ClientRegistrationIdentity.js";
|
|
import { registerSetupCommands } from "./cli/setupCommands.js";
|
|
import { registerCoreAnalysisCommands } from "./cli/coreAnalysisCommands.js";
|
|
import { registerUtilityCommands } from "./cli/utilityCommands.js";
|
|
import { registerArtifactCommands } from "./cli/artifactCommands.js";
|
|
import { registerManagedCommands } from "./cli/managedCommands.js";
|
|
import { registerFirmwareCommands } from "./cli/firmwareCommands.js";
|
|
import { registerAndroidCommands } from "./cli/androidCommands.js";
|
|
import { registerApktoolCommands } from "./cli/apktoolCommands.js";
|
|
import { registerPcapCommands } from "./cli/pcapCommands.js";
|
|
import { registerFlutterCommands } from "./cli/flutterCommands.js";
|
|
import { registerJebCommands } from "./cli/jebCommands.js";
|
|
import { registerAdbCommands } from "./cli/adbCommands.js";
|
|
import { registerEvidenceCommands } from "./cliEvidenceCommands.js";
|
|
import { registerEnvironmentCommands } from "./cli/environmentCommands.js";
|
|
import { registerProcessCommands } from "./cli/processCommands.js";
|
|
import { registerBrowserCommands } from "./cli/browserCommands.js";
|
|
import { registerWebScriptCommands } from "./cli/webScriptCommands.js";
|
|
import { registerWebModuleCommands } from "./cli/webModuleCommands.js";
|
|
import { registerWebSourceLocationCommands } from "./cli/webSourceLocationCommands.js";
|
|
import { registerWebRuntimeCommands } from "./cli/webRuntimeCommands.js";
|
|
import { registerWebNetworkCaptureCommands } from "./cli/webNetworkCaptureCommands.js";
|
|
import { registerJavaScriptRecoveryCommands } from "./cli/javascriptRecoveryCommands.js";
|
|
import { registerAdvancedBrowserCommands } from "./cli/browserAdvancedCommands.js";
|
|
import { registerBrowserScenarioCommands } from "./cliBrowserScenarioCommands.js";
|
|
import { registerElectronCommands } from "./cli/electronCommands.js";
|
|
import { registerJavaScriptRuntimeObservationCommands } from "./cliJavaScriptRuntimeCommands.js";
|
|
import { registerApplicationCommands } from "./cli/applicationCommands.js";
|
|
import { presentOmittableDefaults } from "./cli/omittableDefaults.js";
|
|
import type { CliInstance } from "./cli/types.js";
|
|
import {
|
|
streamCliCommandResults,
|
|
type CliResultOutput,
|
|
} from "./cli/cliResultOutput.js";
|
|
import { registerReverseEngineeringCommands } from "./cli/reverseEngineeringCommands.js";
|
|
import { registerCutterCommands } from "./cli/cutterCommands.js";
|
|
|
|
/** Describe CLI settings that are invalid before any command runs, as MCP does. */
|
|
export const cliConfigurationError = (
|
|
selectedEnvironment: Readonly<Record<string, string | undefined>>,
|
|
): string | undefined => {
|
|
const value = selectedEnvironment.REA_LOG_LEVEL;
|
|
if (value === undefined) return undefined;
|
|
const level = parseLogLevel(value);
|
|
return level.ok ? undefined : projectAnalysisError(level.error).message;
|
|
};
|
|
|
|
/**
|
|
* Build the one-shot Incur CLI without starting Hopper at import time.
|
|
* Analysis commands acquire and close their own sessions; bare `mcp` and
|
|
* `--mcp` are intercepted by the executable dispatcher before this module loads.
|
|
*/
|
|
export const createCli = (
|
|
selectedEnvironment: Readonly<
|
|
Record<string, string | undefined>
|
|
> = process.env,
|
|
resultOutput?: CliResultOutput,
|
|
fridaInstrumentation?: FridaInstrumentationPort,
|
|
): CliInstance => {
|
|
const environment = snapshotEnvironment(selectedEnvironment);
|
|
const analysis = createDirectAnalysis(environment);
|
|
// The executable reports an invalid level through cliConfigurationError.
|
|
const level =
|
|
environment.REA_LOG_LEVEL === undefined
|
|
? undefined
|
|
: parseLogLevel(environment.REA_LOG_LEVEL);
|
|
const logger = createLogger(
|
|
"cli",
|
|
level?.ok === true ? level.value : "silent",
|
|
);
|
|
const cli = Cli.create(PRODUCT_IDENTITY.cliBinary, {
|
|
version: PRODUCT_IDENTITY.packageVersion,
|
|
description: "Reverse engineer anything from your terminal or agent.",
|
|
mcp: {
|
|
command: npxRegistrationCommand().join(" "),
|
|
instructions:
|
|
"Ask what software, artifact, protocol, or behavior the user wants to understand, then choose the available investigation capabilities that can produce evidence.",
|
|
},
|
|
sync: false,
|
|
update: {
|
|
// Incur's update:false only suppresses notices. Reject its explicit
|
|
// installer so ambiguous flags cannot bypass REA's verified workflow.
|
|
install: () => {
|
|
throw new Error(
|
|
"Use 'rea update' to update the identified installation. The '--update' alias accepts only global output flags.",
|
|
);
|
|
},
|
|
},
|
|
});
|
|
|
|
registerSetupCommands(cli, logger, environment);
|
|
registerReverseEngineeringCommands(cli, logger, environment);
|
|
registerCutterCommands(cli, logger, environment);
|
|
registerCoreAnalysisCommands(cli, logger, analysis.runDirectAnalysis);
|
|
registerUtilityCommands(cli, logger, environment, analysis);
|
|
registerWasmCommands(cli, logger, environment);
|
|
registerCaptureCommands(cli, logger, environment);
|
|
registerSignalCommands(cli, logger, environment);
|
|
registerEvmCommands(cli, logger, environment);
|
|
registerGoCommands(cli, logger);
|
|
registerRustCommands(cli, logger);
|
|
registerSqliteCommands(cli, logger, environment);
|
|
registerArtifactCommands(cli, logger, analysis.runProviderAnalysis);
|
|
registerManagedCommands(cli, logger, analysis.runProviderAnalysis);
|
|
registerAndroidCommands(cli, logger, environment);
|
|
registerApktoolCommands(cli, logger, environment);
|
|
registerPcapCommands(cli, logger, environment);
|
|
registerFlutterCommands(cli, logger);
|
|
registerJebCommands(cli, logger, environment);
|
|
registerAdbCommands(cli, logger, environment);
|
|
registerFirmwareCommands(cli, logger, environment);
|
|
registerBinaryDiagnosticsCommands(cli, logger, environment);
|
|
registerAnalysisViewCommands(cli, logger);
|
|
registerFridaCommands(cli, logger, fridaInstrumentation);
|
|
registerEvidenceCommands(cli, logger);
|
|
registerEnvironmentCommands(cli, logger, environment);
|
|
registerProcessCommands(cli, logger, environment);
|
|
registerBrowserCommands(cli, logger);
|
|
registerWebScriptCommands(cli, logger);
|
|
registerWebModuleCommands(cli, logger, environment);
|
|
registerWebSourceLocationCommands(cli, logger, environment);
|
|
registerWebRuntimeCommands(cli, logger);
|
|
registerWebNetworkCaptureCommands(cli, logger, environment);
|
|
registerJavaScriptRecoveryCommands(cli, logger, environment);
|
|
registerAdvancedBrowserCommands(cli, logger);
|
|
registerBrowserScenarioCommands(cli, logger, environment);
|
|
registerElectronCommands(cli, logger, environment);
|
|
registerJavaScriptRuntimeObservationCommands(cli, logger);
|
|
registerApplicationCommands(cli, logger);
|
|
presentOmittableDefaults(cli);
|
|
if (resultOutput !== undefined) streamCliCommandResults(cli, resultOutput);
|
|
const serve = cli.serve.bind(cli);
|
|
cli.serve = (arguments_ = process.argv.slice(2), options) =>
|
|
serve(normalizeCliArguments(arguments_), options);
|
|
return cli;
|
|
};
|