fix(javascript): report EventSource and sendBeacon URLs as network endpoints (#3044)
Co-authored-by: xpeng5278-web <330743750+xpeng5278-web@users.noreply.github.com>
This commit is contained in:
parent
242e2b0001
commit
bbf0638e88
|
|
@ -0,0 +1,40 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { analyzeJavaScriptStaticSource } from "./javascriptStaticAnalysis.js";
|
||||
|
||||
const endpoints = (source: string) =>
|
||||
analyzeJavaScriptStaticSource(source).endpoints.map(
|
||||
({ kind, value, mechanism }) => ({ kind, value, mechanism }),
|
||||
);
|
||||
|
||||
describe("server-sent event endpoints", () => {
|
||||
it("reports EventSource URLs like WebSocket URLs", () => {
|
||||
expect(
|
||||
endpoints(`
|
||||
new WebSocket("wss://chat.example/ws");
|
||||
new EventSource("/api/chat/stream");
|
||||
new window.EventSource("https://chat.example/events", { withCredentials: true });
|
||||
`),
|
||||
).toEqual([
|
||||
{
|
||||
kind: "network",
|
||||
value: "wss://chat.example/ws",
|
||||
mechanism: "call:WebSocket",
|
||||
},
|
||||
{
|
||||
kind: "network",
|
||||
value: "/api/chat/stream",
|
||||
mechanism: "call:EventSource",
|
||||
},
|
||||
{
|
||||
kind: "network",
|
||||
value: "https://chat.example/events",
|
||||
mechanism: "call:window.EventSource",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("keeps a dynamic EventSource URL unreported", () => {
|
||||
expect(endpoints("new EventSource(url);")).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { analyzeJavaScriptStaticSource } from "./javascriptStaticAnalysis.js";
|
||||
|
||||
const endpoints = (source: string) =>
|
||||
analyzeJavaScriptStaticSource(source).endpoints.map(
|
||||
({ kind, value, mechanism }) => ({ kind, value, mechanism }),
|
||||
);
|
||||
|
||||
describe("beacon endpoints", () => {
|
||||
it("reports navigator.sendBeacon URLs", () => {
|
||||
expect(
|
||||
endpoints(`
|
||||
navigator.sendBeacon("/api/telemetry", payload);
|
||||
window.navigator.sendBeacon("https://metrics.example/collect");
|
||||
`),
|
||||
).toEqual([
|
||||
{
|
||||
kind: "network",
|
||||
value: "/api/telemetry",
|
||||
mechanism: "call:navigator.sendBeacon",
|
||||
},
|
||||
{
|
||||
kind: "network",
|
||||
value: "https://metrics.example/collect",
|
||||
mechanism: "call:window.navigator.sendBeacon",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("keeps a dynamic beacon URL unreported", () => {
|
||||
expect(endpoints("navigator.sendBeacon(url, payload);")).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
|
@ -554,7 +554,13 @@ export const endpointArgument = (
|
|||
receiverFact?: JavaScriptOpenReceiverFact,
|
||||
): string | undefined => {
|
||||
if (receiverFact === "window") return undefined;
|
||||
if (name === "fetch" || name.endsWith(".fetch") || name === "WebSocket")
|
||||
if (
|
||||
name === "fetch" ||
|
||||
name.endsWith(".fetch") ||
|
||||
name === "WebSocket" ||
|
||||
name === "EventSource" ||
|
||||
name.endsWith(".EventSource")
|
||||
)
|
||||
return stringValue(args[0]);
|
||||
if (name.endsWith(".open"))
|
||||
return xhrOpenUrl(name, args[0], args[1], receiverFact);
|
||||
|
|
@ -574,6 +580,9 @@ export const endpointArgument = (
|
|||
? undefined
|
||||
: value;
|
||||
}
|
||||
// navigator.sendBeacon(url, data) queues a POST to its first argument.
|
||||
if (name === "sendBeacon" || name.endsWith(".sendBeacon"))
|
||||
return stringValue(args[0]);
|
||||
if (name.endsWith("loadURL")) return stringValue(args[0]);
|
||||
return undefined;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue