fix(javascript): trace wrapped Electron IPC paths in large bundles (#1874)

Co-authored-by: David <17119984+fengdwx@users.noreply.github.com>
This commit is contained in:
DavidandDavid authored and GitHub committed 2026-10-12 09:28:59 +08:00
1 parent d93fbda390
commit 87b9793c53
46 files changed
+3213 -355

No files matched your search

@@ -1,4 +1,5 @@
import * as t from "@babel/types";
import { collectElectronWrappedCallPaths } from "./electronWrappedCallPaths.js";
import {
ELECTRON_IDENTITY_LIMITATION,
ELECTRON_MODULE,
@@ -27,6 +28,7 @@ import {
} from "./javascriptStaticAnalysisCalls.js";
import {
inspectBundlerRegistration,
inspectBundlerBootstrap,
inspectEsbuildWrapper,
} from "./javascriptStaticAnalysisBundler.js";
import { finalizeLocatedFindings } from "./javascriptStaticAnalysisFindings.js";
@@ -38,6 +40,7 @@ import {
import type { JavaScriptStaticAnalysis } from "./javascriptStaticAnalysisTypes.js";
import {
classifyParsedJavaScriptElectronBindingsSteps,
indexJavaScriptBindingsSteps,
classifyParsedJavaScriptRpcClientRootsSteps,
classifyParsedJavaScriptOpenReceivers,
type JavaScriptOpenReceiverFact,
@@ -90,6 +93,13 @@ export function* analyzeParsedJavaScriptStaticSourceSteps(
electronBindings,
rpcScan: createJavaScriptRpcScan(source, clientRoots),
});
const bindings = yield* indexJavaScriptBindingsSteps(file.program);
accumulator.electronCallPaths = collectElectronWrappedCallPaths(
file.program,
bindings,
source,
accumulator,
);
addSourceMapDirectives(source, file.comments ?? [], accumulator);
return finalizeStaticAnalysis(source, file, accumulator);
}
@@ -114,6 +124,16 @@ const finalizeStaticAnalysis = (
): JavaScriptStaticAnalysis => {
const parserErrors = file.errors.length;
const limitations = [
...(accumulator.electronCallPaths?.length
? [
"Bundled Electron call paths use static argument and closure substitutions. Conditions, ambient helper overrides, runtime reachability and arbitrary side effects remain unproven.",
]
: []),
...(accumulator.electronCallPathLimitReached
? [
"Electron wrapper expansion reached its resource budget (1000000 visits/substitutions or depth 128); additional paths remain unknown.",
]
: []),
...(parserErrors === 0
? []
: [
@@ -162,6 +182,9 @@ const finalizeStaticAnalysis = (
source_map_urls: accumulator.sourceMaps,
vendors: detectVendors(source),
electron: {
...(accumulator.electronCallPaths?.length
? { call_paths: accumulator.electronCallPaths }
: {}),
browser_windows: finalizeLocatedFindings(
accumulator.browserWindows,
accumulator.moduleRangeIndex,
@@ -198,6 +221,7 @@ const inspectNode = (
const { source, accumulator } = findings;
inspectElectronStaticNode(node, findings);
if (t.isCallExpression(node)) {
inspectBundlerBootstrap(source, node, accumulator);
inspectBundlerRegistration(source, node, accumulator);
inspectEsbuildWrapper(source, node, accumulator);
inspectCall(source, node, findings);