Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
19a770a705 | ||
|
|
5fd9f4ad60 |
@@ -24,6 +24,20 @@ describe("Electron option evidence", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("does not read an audio or video preload attribute as a preload script", () => {
|
||||
const analysis = analyzeJavaScriptStaticSource(`
|
||||
jsx("audio", { controls: true, preload: "metadata", src });
|
||||
(0, React.createElement)(\`video\`, { preload: "auto" });
|
||||
jsx("webview", { preload: "./guest.js" });
|
||||
const options = { preload: "./preload.js" };
|
||||
`);
|
||||
|
||||
expect(analysis.role_paths.map(({ path }) => path)).toEqual([
|
||||
"./guest.js",
|
||||
"./preload.js",
|
||||
]);
|
||||
});
|
||||
|
||||
it("keeps values unknown when a later computed key can override them", () => {
|
||||
const analysis = analyzeJavaScriptStaticSource(`
|
||||
new BrowserWindow({ webPreferences: { preload: "./maybe.js" }, [key]: null });
|
||||
|
||||
@@ -65,6 +65,8 @@ export const inspectCall = (
|
||||
addReference(context, { node, kind: "service-worker", specifier: first });
|
||||
inspectEndpointCall(node, name, first, context);
|
||||
inspectStorageCall(node, name, first, context);
|
||||
if (first === "audio" || first === "video")
|
||||
noteMediaElementPreloads(node, accumulator);
|
||||
if (name.endsWith("loadFile") && first !== undefined)
|
||||
addLocatedFinding(context, {
|
||||
collection: accumulator.roles,
|
||||
@@ -95,6 +97,23 @@ export const inspectCall = (
|
||||
});
|
||||
};
|
||||
|
||||
// Element factories such as jsx("audio", props) and createElement("video",
|
||||
// props) carry the HTML media `preload` hint ("none", "metadata", "auto"),
|
||||
// which never names an Electron preload script.
|
||||
const noteMediaElementPreloads = (
|
||||
node: JavaScriptCallLike,
|
||||
accumulator: AnalysisAccumulator,
|
||||
): void => {
|
||||
const props = node.arguments[1];
|
||||
if (!t.isObjectExpression(props)) return;
|
||||
for (const property of props.properties)
|
||||
if (
|
||||
t.isObjectProperty(property) &&
|
||||
semanticStaticPropertyName(property.key, property.computed) === "preload"
|
||||
)
|
||||
accumulator.mediaElementPreloads.add(property);
|
||||
};
|
||||
|
||||
const requireCallSpecifier = (
|
||||
node: JavaScriptCallLike,
|
||||
name: string,
|
||||
@@ -201,6 +220,7 @@ export const inspectRoleProperty = (
|
||||
context: FindingContext,
|
||||
): void => {
|
||||
if (semanticStaticPropertyName(node.key, node.computed) !== "preload") return;
|
||||
if (context.accumulator.mediaElementPreloads.has(node)) return;
|
||||
const path = staticPath(node.value);
|
||||
if (path === undefined) return;
|
||||
addLocatedFinding(context, {
|
||||
|
||||
@@ -47,6 +47,8 @@ export interface JavaScriptAnalysisAccumulator {
|
||||
readonly utilityProcesses: LocatedJavaScriptFinding<ElectronUtilityProcessFinding>[];
|
||||
readonly nativeAddonBindings: LocatedJavaScriptFinding<ElectronNativeAddonBindingFinding>[];
|
||||
readonly moduleRangeIndex: JavaScriptModuleRangeIndex;
|
||||
/** `preload` attributes of audio and video elements, which are not scripts. */
|
||||
readonly mediaElementPreloads: WeakSet<t.Node>;
|
||||
readonly seen: Set<string>;
|
||||
visitedNodes: number;
|
||||
unknownFindings: number;
|
||||
@@ -111,6 +113,7 @@ export const createJavaScriptAnalysisAccumulator = (
|
||||
utilityProcesses: [],
|
||||
nativeAddonBindings: [],
|
||||
moduleRangeIndex: new JavaScriptModuleRangeIndex(sourceLength),
|
||||
mediaElementPreloads: new WeakSet(),
|
||||
seen: new Set(),
|
||||
visitedNodes: 0,
|
||||
unknownFindings: 0,
|
||||
|
||||
Reference in New Issue
Block a user