fix(javascript): preserve runtime path bytes and Electron ownership (#4941)

* fix(javascript): preserve literal percent runtime paths

* fix(javascript): ignore resolve prefixes before the final anchor

* fix(electron): retain application roots for loadFile declarations

* fix(electron): resolve loadFile from enclosing application package

* fix(electron): retain outer application root across package scopes

* fix(electron): derive application ownership from inventoried packages

* fix(electron): retain resolved package entrypoint ownership

* fix(electron): preserve competing application ownership

* fix(electron): retain invalid and omitted runtime ownership

* fix(electron): preserve omitted module ownership and runtime paths

* fix(electron): preserve proven roots before confining page paths

* fix(electron): retain possible owners behind missing imports

* fix(electron): distinguish absent imports and owned page candidates

* fix(electron): keep unavailable JSON out of owner gaps

* fix(electron): retain exact loader formats and default entry status

* fix(electron): retain unavailable entrypoint ownership candidates

* test(ghidra): preserve Windows Node probe prerequisites

* test(ghidra): assert cancellation during profile shutdown

* fix(electron): separate examined imports from frontend ownership

* fix(electron): retain unavailable directory entrypoint owners

* test(jeb): retain Linux ownership prerequisite in isolation

* fix(javascript): retain unchecked loader ownership and literal main paths

* fix(javascript): preserve runtime paths and call-site module aliases

* fix(javascript): bound module alias traversal and preserve projections

* fix(javascript): retain host module and nested artifact path boundaries

* fix(javascript): preserve ESM and archive module loader provenance

* test(javascript): distinguish unmapped containers from missing exports

* fix: retain default module aliases and Electron builtin imports

* fix: preserve host file URL and inward ASAR ownership

* fix: preserve CommonJS file URL classification in CI fixtures

* fix: retain bound module loaders and Windows entrypoint uncertainty

* fix: retain ASAR uncertainty and invalidate changed Electron app roots

* fix(javascript): retain ownership uncertainty across loader boundaries

* fix(javascript): preserve loader sources and bound alias queries

* fix(javascript): retain destructured loader sources

* fix(javascript): preserve loader uncertainty at resolution boundaries

* fix(javascript): preserve callable and package launch ownership

* fix(javascript): preserve captured values across member reads

* test(process): assert tagged filesystem cancellation failures

* fix(javascript): preserve inventory bases and invocation read timing

* fix(javascript): preserve ownership across indirect and unread loads

* test(javascript): order fixture directory creation on Windows

* test(javascript): share ordered filesystem fixture writer

* fix(javascript): unify loader provenance and package validation

* fix(javascript): preserve captured Node require loader values

* fix(javascript): preserve loader invocation authority

* fix(javascript): verify generic loader invocation authority

* fix(javascript): preserve conditional loader method alternatives

* fix(javascript): require proven factories for source association

* fix(javascript): honor replaced Electron app path setters

* fix(javascript): prove path and assignment source ownership

* fix(javascript): retain native delegate eligibility through shared writes

* fix(process): settle stale baseline errors after confirmed absence

* fix(javascript): preserve assignment and path boundary evidence

* fix(javascript): prove source-directory resolve anchors

* fix: preserve application path provenance and portable schemas

* fix(javascript): retain CommonJS exported setter effects

* fix: isolate Linux identity observations and retain native module exports

* fix(javascript): preserve published app and helper provenance

* fix(javascript): normalize typed stores and native path fixtures
This commit is contained in:
ShuaixinHuang authored and GitHub committed 2026-10-20 17:25:19 +08:00
1 parent d532b18123
commit e9fc8fb30c
149 files changed
+16881 -988

No files matched your search

@@ -50,8 +50,9 @@ import {
import { semanticTopLevelEffectFollowsCapture } from "./javascriptSemanticMutationInitializers.js";
import {
semanticFactoryLoaderMemberAt,
semanticFactoryRequireLoaderAt,
semanticRequireLoaderAt,
semanticRequireCallAt,
semanticModuleRequireCallAt,
semanticModuleRequireReceiver,
} from "./javascriptSemanticRequireOrigin.js";
type JavaScriptCallLike =
@@ -69,7 +70,13 @@ export const inspectCall = (
const { accumulator } = context;
const name = calleeName(node.callee);
const first = stringValue(node.arguments[0]);
const requireCall = requireCallSpecifier(node, bindings, context);
const deferredModuleRequire =
semanticModuleRequireReceiver(node) !== undefined ||
semanticModuleRequireCallAt(node, bindings, false);
if (deferredModuleRequire) accumulator.pendingModuleRequireCalls.push(node);
const requireCall = deferredModuleRequire
? null
: requireCallSpecifier(node, bindings, context);
if (requireCall !== null)
addReference(context, {
node,
@@ -249,43 +256,37 @@ const requireCallSpecifier = (
bindings: JavaScriptSemanticAnalysisState,
context: FindingContext,
): { readonly specifier: string | undefined } | null => {
const bareRequire = t.isIdentifier(node.callee, { name: "require" });
if (bareRequire) {
const loader = semanticRequireLoaderAt(
node,
bindings,
context.accumulator.factoryRequireBindingIds,
);
if (loader === "local") return null;
if (loader === "unknown") context.accumulator.unknownFindings += 1;
return {
specifier:
loader === "unknown" ? undefined : argumentValue(node.arguments[0]),
};
}
const factoryLoader = semanticFactoryRequireLoaderAt(
const call = semanticRequireCallAt(
node,
bindings,
context.accumulator.factoryRequireBindingIds,
);
if (factoryLoader === "factory-loader")
return {
specifier: argumentValue(
node.arguments[
t.isMemberExpression(unwrapJavaScriptExpression(node.callee).node) ||
t.isOptionalMemberExpression(
unwrapJavaScriptExpression(node.callee).node,
)
? 1
: 0
],
),
};
if (factoryLoader === "unknown") {
if (call === undefined || call.loader === "local") return null;
if (call.loader === "unknown" || !call.sourceRelative) {
context.accumulator.unknownFindings += 1;
return { specifier: undefined };
}
return null;
return { specifier: argumentValue(call.arguments?.[0]) };
};
/** Examine member-loader receivers only after shared alias mutation facts settle. */
export const finishModuleRequireCalls = (
context: FindingContext,
bindings: JavaScriptSemanticAnalysisState,
): void => {
for (const node of context.accumulator.pendingModuleRequireCalls) {
const call = requireCallSpecifier(node, bindings, context);
if (call !== null)
addReference(context, {
node,
kind: "require",
specifier: call.specifier,
});
}
context.accumulator.pendingModuleRequireCalls.length = 0;
context.accumulator.references.sort(
(left, right) => left.offset - right.offset,
);
};
const chunkLoadSpecifier = (
@@ -760,7 +761,7 @@ export const inspectRoleProperty = (
): void => {
if (semanticStaticPropertyName(node.key, node.computed) !== "preload") return;
if (context.accumulator.mediaElementPreloads.has(node)) return;
const path = staticPath(node.value);
const path = staticPath(node.value, context.nodePathResolve);
if (path === undefined) return;
addLocatedFinding(context, {
collection: context.accumulator.roles,
@@ -769,7 +770,10 @@ export const inspectRoleProperty = (
value: {
role: "preload",
path,
resolution_context: staticPathResolutionContext(node.value),
resolution_context: staticPathResolutionContext(
node.value,
context.nodePathResolve,
),
mechanism: "property:preload",
module_key: null,
location: range(node),