* feat: add Frida instrumentation support * fix: resolve Frida CI checks * test: cover Frida contract validation branches * docs: link Frida instrumentation guide * fix(frida): handle cancellation cleanup safely * fix(frida): address PR review findings * fix(frida): preserve resume and message observations * fix(ci): use canonical registry for rolldown * fix(frida): declare foreign code effects * fix(frida): retain failed startup resources for cleanup retries Keep failed startup session and spawn handles owned until detach, resume, and remote lease cleanup complete. Serialize retries and release each remote reference once. Await CLI provider cleanup while preserving the primary failure and any completed observations. Add regressions for retained startup resources, concurrent cleanup, shared remote leases, and CLI cleanup outcomes. Validation: 41 focused tests pass on the PR head and its latest-main integration; serial static and docs checks pass. Real Linux Frida 17.23.2 workflows and the native spawn/controlled-failure cleanup probe pass. Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing) --------- Co-authored-by: N0zoM1z0 <[email protected]>
125 lines
6.3 KiB
TypeScript
125 lines
6.3 KiB
TypeScript
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 { 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 { 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 { registerJebCommands } from "./cli/jebCommands.js";
|
|
import { registerAdbCommands } from "./cli/adbCommands.js";
|
|
import { registerEvidenceCommands } from "./cliEvidenceCommands.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/streamedJsonOutput.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,
|
|
});
|
|
|
|
registerSetupCommands(cli, logger, environment);
|
|
registerCoreAnalysisCommands(cli, logger, analysis.runDirectAnalysis);
|
|
registerUtilityCommands(cli, logger, environment, analysis);
|
|
registerWasmCommands(cli, logger, environment);
|
|
registerEvmCommands(cli, logger, environment);
|
|
registerGoCommands(cli, logger);
|
|
registerArtifactCommands(cli, logger, analysis.runProviderAnalysis);
|
|
registerManagedCommands(cli, logger, analysis.runProviderAnalysis);
|
|
registerAndroidCommands(cli, logger, environment);
|
|
registerApktoolCommands(cli, logger, environment);
|
|
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);
|
|
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);
|
|
return cli;
|
|
};
|