Files
rea/src/domain/webBundleAnalyzer.test.ts
T
morluto fbfdb6abe9 fix(javascript): distinguish Map lookups from network endpoints
Resolve unchanged Map operations through shared binding, capture, mutation,
and ambient escape facts. Reuse that proof in application and captured
bundle analysis; unresolved get/delete receivers remain inferred candidates.

Preserve repeated native operations without manufacturing receiver escapes.
Retain uncertainty for real escapes, opaque eval, and changed constructor
adder hooks. Converge stored aliases at the producing boundary.

Adapt the JavaScript changes from #4863, excluding its Linux resource fix.
Add captured-bundle parity, repeated-operation and constructor-hook coverage.

Fixes #4853
Co-authored-by: abdooo2235 <abdalrhmantheiv15@gmail.com>
2026-10-18 08:25:06 +08:00

1338 lines
44 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { webPageInspectionSchema } from "./browserObservationSchemas.js";
import { analyzeJavaScriptStaticSource } from "./javascript/javascriptStaticAnalysis.js";
import { analyzeCapturedWebBundle } from "./webBundleAnalyzer.js";
import { webBundleAnalysisSchema } from "./webBundleAnalysis.js";
import { createWebTextArtifact } from "./webContentArtifact.js";
const origin = "https://app.example.test";
it("retains standalone GraphQL Source operations in captured scripts", () => {
const result = analyzeCapturedWebBundle(
inspection(`
const source = {
body: "query GetUser { user { id } }",
locationOffset: { line: 1, column: 1 },
};
`),
);
expect(result.observations.endpoints).toEqual([
expect.objectContaining({ value: "GetUser", mechanism: "graphql:query" }),
]);
});
it.each([
{
kind: "recovered",
source: "function legacy(a, a) { return a; } fetch('/partial');",
parsed: 2,
failures: 0,
reason: "recovered",
endpoints: ["/partial", "/complete"],
},
{
kind: "failed",
source: "function broken( {",
parsed: 1,
failures: 1,
reason: "could not be parsed",
endpoints: ["/complete"],
},
])(
"attributes $kind parse uncertainty only to its affected source",
({ source, parsed, failures, reason, endpoints }) => {
const captured = inspection(source);
const good = inspection("fetch('/complete');").scripts.items[0];
if (good === undefined) throw new Error("Missing valid script fixture");
captured.scripts.items.push({ ...good, script_key: "valid-script" });
captured.scripts.total += 1;
const result = analyzeCapturedWebBundle(captured);
expect(result.completeness).toMatchObject({
status: "partial",
parsed_scripts: parsed,
parse_failures: failures,
});
expect(result.unknowns).toContainEqual({
dimension: "javascript_ast",
reason: expect.stringContaining(reason),
affected_script_keys: [captured.scripts.items[0]?.script_key],
});
expect(result.observations.endpoints.map(({ value }) => value)).toEqual(
endpoints,
);
},
);
it.each([
[
"const records = new Map(); const alias = records; alias.get('/accounts');",
false,
],
["new Map().delete('/accounts');", false],
[
"const records = new Map(); records.get('/accounts'); records.delete('/accounts');",
false,
],
[
"const records = new Map(); records.get = fetch; records.get('/accounts');",
true,
],
[
"Object.getPrototypeOf = () => Map.prototype; Object.getPrototypeOf({}).get = fetch; new Map().get('/accounts');",
true,
],
["client.get('/accounts');", true],
["eval('Map.prototype.get = fetch'); new Map().get('/accounts');", true],
] as const)(
"shares Map receiver certainty with application analysis: %s",
(source, candidate) => {
const input = source + " fetch('/network');";
const result = analyzeCapturedWebBundle(inspection(input));
expect(result.observations.endpoints.map(({ value }) => value)).toEqual([
"/network",
]);
expect(
result.inferences
.filter(({ kind }) => kind === "endpoint_candidate")
.map(({ value }) => value),
).toEqual(candidate ? ["/accounts"] : []);
const staticResult = analyzeJavaScriptStaticSource(input);
expect(
staticResult.endpoints
.map(({ value, interpretation }) => [value, interpretation ?? null])
.sort(),
).toEqual(
candidate
? [
["/accounts", "candidate"],
["/network", null],
]
: [["/network", null]],
);
},
);
describe("web bundle analyzer", () => {
it("extracts graph, route, endpoint, vendor, and WebMCP evidence", () => {
const source = `
import { createApp } from "./chunk.js?token=secret";
const lazy = import("./lazy.js");
const routes = [{ path: "/users/:id?token=secret" }];
fetch("/api/users?authorization=secret");
document.modelContext.registerTool({
name: "lookup-user",
description: "Untrusted page declaration",
inputSchema: {
type: "object",
properties: {
userId: { type: "string" },
verbose: { type: "boolean" }
}
}
});
const __webpack_require__ = () => createApp(routes, lazy);
`;
const result = analyzeCapturedWebBundle(inspection(source));
expect(result.observations.chunks.edges).toEqual(
expect.arrayContaining([
expect.objectContaining({
kind: "static_import",
specifier: "./chunk.js?token=secret",
resolved_url: `${origin}/assets/chunk.js?token=secret`,
}),
expect.objectContaining({
kind: "dynamic_import",
specifier: "./lazy.js",
}),
]),
);
expect(result.observations.routes).toEqual([
expect.objectContaining({ value: "/users/:id?token=secret" }),
]);
expect(result.observations.endpoints).toEqual([
expect.objectContaining({
value: "/api/users?authorization=secret",
}),
]);
expect(result.observations.webmcp_declarations).toEqual([
expect.objectContaining({
name: "lookup-user",
trust: "page-declared-untrusted",
schema_property_names: ["userId", "verbose"],
}),
]);
expect(result.inferences).toEqual(
expect.arrayContaining([
expect.objectContaining({ value: "webpack", confidence: "high" }),
expect.objectContaining({ value: "Vue" }),
]),
);
expect(JSON.stringify(result)).toContain("authorization=secret");
expect(result.completeness.status).toBe("complete");
});
it("reports parser gaps without imposing a finding cap", () => {
const malformed = inspection("function broken( {");
const failed = analyzeCapturedWebBundle(malformed);
expect(failed.completeness).toMatchObject({
status: "partial",
parse_failures: 1,
});
expect(failed.unknowns[0]?.dimension).toBe("javascript_ast");
const analyzed = analyzeCapturedWebBundle(
inspection("fetch('/one'); fetch('/two'); fetch('/three');"),
);
expect(analyzed.observations.endpoints).toHaveLength(3);
expect(analyzed.completeness.status).toBe("complete");
});
it("analyzes AST nodes after the former fixed node ceiling", () => {
const source = `${";".repeat(250_001)}fetch('/last');`;
const result = analyzeCapturedWebBundle(inspection(source));
expect(result.observations.endpoints).toContainEqual(
expect.objectContaining({ value: "/last" }),
);
expect(result.completeness.visited_ast_nodes).toBeGreaterThan(250_000);
expect(result.completeness.status).toBe("complete");
});
it("retains complete long chunk and WebMCP declaration text", () => {
const specifier = `./${"chunk".repeat(1_000)}.js`;
const name = "tool".repeat(100);
const description = "untrusted declaration ".repeat(150);
const propertyName = "property".repeat(100);
const result = analyzeCapturedWebBundle(
inspection(`
import "${specifier}";
document.modelContext.registerTool({
name: "${name}",
description: "${description}",
inputSchema: { properties: { "${propertyName}": { type: "string" } } }
});
`),
);
expect(result.observations.chunks.edges[0]?.specifier).toBe(specifier);
expect(result.observations.webmcp_declarations[0]).toMatchObject({
name,
description,
schema_property_names: [propertyName],
trust: "page-declared-untrusted",
});
});
});
describe("web bundle source-map coverage", () => {
it("reports unavailable source maps as partial without dropping requested maps", () => {
const analysis = analyzeCapturedWebBundle(inspection("export {};"), {
status: "unavailable",
requested: 1,
processed: 1,
items: [
{
script_key: `scr_${"1".repeat(64)}`,
declared_url: "https://app.example.test/app.js.map",
effective_url: null,
status: "fetch_failed",
artifact: null,
original_sources: [],
original_module_edges: [],
mappings: [],
limitation: "Source-map fetch failed.",
},
],
});
expect(analysis.completeness.status).toBe("partial");
expect(analysis.unknowns).toContainEqual({
dimension: "source_maps",
reason:
"One or more requested source maps were unavailable or incomplete",
affected_script_keys: [`scr_${"1".repeat(64)}`],
});
});
it("keeps map-less captured source complete when no maps were requested", () => {
const analysis = analyzeCapturedWebBundle(inspection("export {};"), {
status: "not_requested",
requested: 0,
processed: 0,
items: [],
});
expect(analysis.completeness.status).toBe("complete");
expect(analysis.unknowns).toEqual([]);
});
it("rejects inconsistent source-map coverage counts", () => {
const result = analyzeCapturedWebBundle(inspection("export {};"));
expect(
webBundleAnalysisSchema.safeParse({
...result,
observations: {
...result.observations,
source_maps: {
...result.observations.source_maps,
requested: 1,
},
},
}).success,
).toBe(false);
});
});
describe("web bundle static-analysis parity", () => {
it("recognizes endpoints through nested dynamic receivers like static analysis", () => {
const result = analyzeCapturedWebBundle(
inspection('window[recv].fetch("/nested-fetch");'),
);
expect(result.observations.endpoints).toContainEqual(
expect.objectContaining({ value: "/nested-fetch" }),
);
});
it("reads open endpoints only from XMLHttpRequest method and URL pairs", () => {
const result = analyzeCapturedWebBundle(
inspection(`
xhr.open("GET", "/xhr-get");
xhr.open("post", "https://xhr.example.test/submit");
dav.open("PROPFIND", "/dav/");
fs.open("/tmp/data.txt", "r", done);
window.open("https://help.example.test/", "_blank");
xhr.open(method, "/dynamic-method");
fs.open(path, "r", done);
window.open(url, "_blank");
window.open(url, "/preview");
globalThis.open(url, "./frame");
document.open("text/html", "/replace");
parent.open("GET", "/parent-xhr");
self.open("post", "/self-xhr");
top.open("GET", "/top-target");
opener.open("GET", "/opener-target");
frames.open("GET", "/frames-target");
globalThis.open("GET", "/global-target");
document.open("GET", "/document-target");
const parentWindow = parent;
parentWindow.open("GET", "/alias-target");
{
const parent = new XMLHttpRequest();
parent.open(method, "/shadowed-parent-xhr");
}
xhr.open(method, "api/relative");
fs.open(path, "w+", done);
popup.open(url, "_TOP");
`),
);
expect(
result.observations.endpoints.map(({ value }) => value).sort(),
).toEqual([
"/dav/",
"/dynamic-method",
"/shadowed-parent-xhr",
"/xhr-get",
"https://xhr.example.test/submit",
]);
expect(result.inferences).toContainEqual(
expect.objectContaining({
kind: "endpoint_candidate",
value: "api/relative",
confidence: "low",
}),
);
});
});
describe("web bundle API classification parity", () => {
it("reads storage open versions as storage rather than endpoints in both analyzers", () => {
const source = `
indexedDB.open(databaseName, "2");
window.indexedDB.open(databaseName, "/v3");
indexedDB.open("APP", "4");
indexedDB.open("GET", "/storage-named-xhr");
`;
expect(
analyzeCapturedWebBundle(inspection(source)).observations.endpoints.map(
({ value }) => value,
),
).toEqual(["/storage-named-xhr"]);
const analysis = analyzeJavaScriptStaticSource(source);
expect(analysis.endpoints.map(({ value }) => value)).toEqual([
"/storage-named-xhr",
]);
expect(analysis.storage.map(({ kind }) => kind)).toEqual([
"indexed-db",
"indexed-db",
"indexed-db",
"indexed-db",
]);
});
it("uses lexical receiver facts for overloaded open calls", () => {
const result = analyzeCapturedWebBundle(
inspection(`
const popup = window;
popup.open(url, "/preview");
{
const indexedDB = { open() {} };
indexedDB.open("PROPFIND", "/dav");
indexedDB.open(databaseName, "2");
}
const xhr = new XMLHttpRequest();
xhr.open(method, "/api");
`),
);
expect(
result.observations.endpoints.map(({ value }) => value).sort(),
).toEqual(["/api", "/dav"]);
});
it("classifies optional and one-hop aliased open calls", () => {
const source = `
const popup = window;
popup?.open(url, "/preview");
const idb = indexedDB;
idb.open(databaseName, "2");
const xhr = new XMLHttpRequest();
xhr?.open(method, "/api");
`;
const bundle = analyzeCapturedWebBundle(inspection(source));
expect(bundle.observations.endpoints.map(({ value }) => value)).toEqual([
"/api",
]);
const staticAnalysis = analyzeJavaScriptStaticSource(source);
expect(staticAnalysis.endpoints.map(({ value }) => value)).toEqual([
"/api",
]);
expect(staticAnalysis.storage.map(({ kind }) => kind)).toEqual([
"indexed-db",
]);
});
it("keeps HTTP-method-named reads of provable keyed collections out of endpoints", () => {
const result = analyzeCapturedWebBundle(
inspection(`
axios.get("https://api.example.test/users");
api.get("users");
client.delete("cache-key");
new Map().get("map-key");
new URLSearchParams(location.search).get("q");
new Headers(init).delete("x-trace");
new FormData(form).get("file");
response.headers.get("content-type");
request?.headers.delete("cookie");
new URL(location.href).searchParams.get("page");
api.headers.post("/v1/headers");
api.searchParams.request("/search");
new Headers().get("/users");
api.headers.get("https://api.example.test/headers");
api.searchParams.delete("../search");
`),
);
expect(
result.observations.endpoints.map(({ value }) => value).sort(),
).toEqual(["/search", "/v1/headers"]);
expect(
result.inferences
.filter(({ kind }) => kind === "endpoint_candidate")
.map(({ value }) => value)
.sort(),
).toEqual([
"../search",
"/users",
"cache-key",
"https://api.example.test/headers",
"https://api.example.test/users",
"users",
]);
});
it("keeps undici header-store reads out of endpoint observations", () => {
const result = analyzeCapturedWebBundle(
inspection(`
response.headersList.get("location", true);
request.headersList.delete("authorization");
request.headersList.get("/header-list");
api.get("/api/users");
`),
);
expect(result.observations.endpoints).toEqual([]);
expect(
result.inferences
.filter(({ kind }) => kind === "endpoint_candidate")
.map(({ value }) => value),
).toEqual(["/header-list", "/api/users"]);
});
});
describe("web bundle explicit request reference forms", () => {
it("recognizes URL, path, query and fragment forms after excluding lookup receivers", () => {
const references = [
"http://api.example.test/users",
"https://api.example.test/users?q=1#part",
"ws://api.example.test/events",
"wss://api.example.test/events",
"http:api.example.test/users",
"https:api.example.test/users?q=1&tag=a&tag=b#part",
"https:api.example.test:443/a/../b?x=a+b&x=two#part",
"ws:api.example.test/events",
"wss:api.example.test/events",
"HtTpS:/api.example.test/users",
String.raw`https:\api.example.test\users`,
"https://[invalid",
"//api.example.test/users",
"/api/users",
"./users",
"../users",
"?",
"?page=2&tag=a&tag=b#section",
"#",
"#section",
"#frag?tag=a&tag=b",
];
const ambiguous = [
"",
".",
"..",
"users",
"%23section",
"%3Fpage=2",
" #section",
" https:api.example.test/users",
"https:",
"http:?page=2",
"ws:#section",
"https:[invalid",
"https:api.example.test:99999",
"ftp:api.example.test/users",
"file:/users",
"data:text/plain,users",
];
const source = `
${references.map((value) => `api.get(${JSON.stringify(value)});`).join("\n")}
${ambiguous.map((value) => `api.get(${JSON.stringify(value)});`).join("\n")}
xhr.open(method, "?view=1");
xhr.open(method, "#view=1");
xhr.open("GET", "#literal=1");
xhr.open(method, "https:api.example.test/xhr");
request("POST", target);
snackBar.open(message, "X");
new Map().get("?map-key");
new Map().get("#map-key");
new Map().get("https:api.example.test/map-key");
new Headers().delete("?header-key");
new Headers().delete("#header-key");
new URLSearchParams().get("?parameter-key");
new URLSearchParams().get("#parameter-key");
response.headers.get("?response-key");
response.headers.get("#response-key");
const config = vscode.workspace.getConfiguration("git");
config.get("?setting");
config.get("#setting");
config.get("https:api.example.test/setting");
window.open(url, "?window-target");
window.open(url, "#window-target");
indexedDB.open(name, "?database-version");
indexedDB.open(name, "#database-version");
caches.open(name, "#cache-name");
fs.open(path, "r");
`;
const expected = [
"?view=1",
"#view=1",
"#literal=1",
"https:api.example.test/xhr",
].sort();
const expectedCandidates = [
...references,
...ambiguous,
"POST",
"X",
].sort();
const web = analyzeCapturedWebBundle(inspection(source));
expect(web.observations.endpoints.map(({ value }) => value).sort()).toEqual(
expected,
);
expect(
web.inferences
.filter(({ kind }) => kind === "endpoint_candidate")
.map(({ value }) => value)
.sort(),
).toEqual(expectedCandidates);
const analyzed = analyzeJavaScriptStaticSource(source);
expect(
analyzed.endpoints
.filter(({ interpretation }) => interpretation === undefined)
.map(({ value }) => value)
.sort(),
).toEqual(expected);
expect(
analyzed.endpoints
.filter(({ interpretation }) => interpretation === "candidate")
.map(({ value }) => value)
.sort(),
).toEqual(expectedCandidates);
});
});
describe("web bundle endpoint candidate classification", () => {
it("keeps ambiguous HTTP-method arguments as candidates instead of endpoint observations", () => {
const source = `
fetch("login");
api.get("/api/users");
api.get("users");
form.get("passwordControl");
translate.get("ADDRESS_ADDED");
cookieService.put("token", value);
http.request("POST", target);
snackBar.open(message, "X");
xhr.open(method, "login");
xhr.open("GET", "ping");
`;
const result = analyzeCapturedWebBundle(inspection(source));
expect(
result.observations.endpoints.map(({ value }) => value).sort(),
).toEqual(["login", "ping"]);
const candidates = result.inferences.filter(
({ kind }) => kind === "endpoint_candidate",
);
expect(candidates.map(({ value }) => value).sort()).toEqual([
"/api/users",
"ADDRESS_ADDED",
"POST",
"X",
"login",
"passwordControl",
"token",
"users",
]);
expect(
candidates.every(
({ confidence, basis }) =>
confidence === "low" &&
basis.length === 1 &&
basis[0]?.artifact_sha256 ===
createWebTextArtifact(source, "text/javascript").sha256 &&
basis[0]?.line !== null &&
basis[0]?.detector.startsWith("call:"),
),
).toBe(true);
const staticEndpoints = analyzeJavaScriptStaticSource(source).endpoints;
expect(
staticEndpoints
.filter(({ interpretation }) => interpretation === "candidate")
.map(({ value }) => value)
.sort(),
).toEqual(candidates.map(({ value }) => value).sort());
expect(
staticEndpoints
.filter(({ interpretation }) => interpretation === undefined)
.map(({ value }) => value)
.sort(),
).toEqual(result.observations.endpoints.map(({ value }) => value).sort());
expect(webBundleAnalysisSchema.parse(result)).toEqual(result);
});
it("deduplicates repeated candidate sites while keeping script, value and detector identity", () => {
const source = `${'form.get("name");\n'.repeat(5_000)}translate.get("name");\nform.get("other");`;
const captured = inspection(source);
const first = captured.scripts.items[0];
if (first === undefined) throw new Error("Missing captured script fixture");
const secondKey = `scr_${"2".repeat(64)}`;
const result = analyzeCapturedWebBundle({
...captured,
scripts: {
total: 2,
items: [
first,
{
...first,
script_key: secondKey,
url: `${origin}/assets/second.js`,
},
],
},
});
const candidates = result.inferences.filter(
({ kind }) => kind === "endpoint_candidate",
);
expect(candidates).toHaveLength(6);
for (const scriptKey of [first.script_key, secondKey]) {
const local = candidates.filter(
({ basis }) => basis[0]?.script_key === scriptKey,
);
expect(
local.map(({ value, basis }) => [value, basis[0]?.detector]),
).toEqual([
["name", "call:form.get:unverified-network-receiver"],
["name", "call:translate.get:unverified-network-receiver"],
["other", "call:form.get:unverified-network-receiver"],
]);
expect(local[0]?.basis[0]).toMatchObject({
line: 1,
column: 0,
artifact_sha256: createWebTextArtifact(source, "text/javascript")
.sha256,
});
}
expect(result.observations.endpoints).toEqual([]);
expect(result.capture.source_artifacts).toHaveLength(2);
expect(result.completeness).toMatchObject({
status: "complete",
parsed_scripts: 2,
});
expect(result.limitations).toContain(
'Endpoint candidates are deduplicated by script, value and detector; basis retains only the first matching source coordinate. They are not a complete call-site inventory or a runtime occurrence count. completeness.status="complete" describes examination of captured source, not a call-site census.',
);
});
});
describe("web bundle configuration and navigation parity", () => {
it("keeps configuration setting reads out of endpoints in both analyzers", () => {
const source = `
import vscodeDefault from "vscode";
vscodeDefault.workspace.getConfiguration("git").get("default-setting");
vscode.workspace.getConfiguration("git").get("autofetch");
workspace.getConfiguration("git").get("enabled", true);
const config = vscode.workspace.getConfiguration("git");
config.get("autofetchPeriod", 180);
config.get("/v1/settings");
let c = Mt.workspace.getConfiguration("git", uri), l = c.get("timeline.date");
let changed = vscode.workspace.getConfiguration("git");
changed = api;
changed.get("reassigned");
const maybe = flag ? vscode.workspace.getConfiguration("git") : api;
maybe.get("conditional");
{
const config = api;
config.get("shadowed");
}
api.get("users");
const client = getConfiguration("/api/v1");
client.get("accounts");
http.getConfiguration(baseUrl).get("orders");
{
const workspace = { getConfiguration: () => api };
workspace.getConfiguration("/api").get("local-users");
}
{
const vscode = { workspace: { getConfiguration: () => api } };
vscode.workspace.getConfiguration("/api").get("local-orders");
}
`;
const expected = [
"/v1/settings",
"accounts",
"conditional",
"local-orders",
"local-users",
"orders",
"reassigned",
"shadowed",
"users",
];
const web = analyzeCapturedWebBundle(inspection(source));
expect(web.observations.endpoints).toEqual([]);
expect(
web.inferences
.filter(({ kind }) => kind === "endpoint_candidate")
.map(({ value }) => value)
.sort(),
).toEqual(expected);
expect(
analyzeJavaScriptStaticSource(source)
.endpoints.map(({ value }) => value)
.sort(),
).toEqual(expected);
});
it("classifies proven VS Code extension state reads as non-endpoints", () => {
const reads = `
context.globalState.get("lastVersion");
this.workspaceState.get("closedRepositories", []);
context?.globalState.get("onboarded");
context.globalState.get("/v1/state");
context.secrets.get("token");
api.get("users");
`;
const analyze = (source: string) => {
const web = analyzeCapturedWebBundle(inspection(source));
const staticAnalysis = analyzeJavaScriptStaticSource(source);
return {
web: {
endpoints: web.observations.endpoints
.map(({ value }) => value)
.sort(),
candidates: web.inferences
.filter(({ kind }) => kind === "endpoint_candidate")
.map(({ value }) => value)
.sort(),
},
application: {
endpoints: staticAnalysis.endpoints
.filter(({ interpretation }) => interpretation === undefined)
.map(({ value }) => value)
.sort(),
candidates: staticAnalysis.endpoints
.filter(({ interpretation }) => interpretation === "candidate")
.map(({ value }) => value)
.sort(),
},
};
};
const proven = {
endpoints: [],
candidates: ["/v1/state", "token", "users"],
};
expect(analyze(`const vscode = require("vscode");${reads}`)).toEqual({
web: proven,
application: proven,
});
expect(analyze(`import * as vscode from "vscode";${reads}`)).toEqual({
web: proven,
application: proven,
});
const unproven = {
endpoints: [],
candidates: [
"/v1/state",
"closedRepositories",
"lastVersion",
"onboarded",
"token",
"users",
],
};
expect(analyze(`const vscode = require("./vscode");${reads}`)).toEqual({
web: unproven,
application: unproven,
});
});
it("recognizes loadURL endpoints like static analysis", () => {
const result = analyzeCapturedWebBundle(
inspection('window.win.loadURL("https://embedded.test/app");'),
);
expect(result.observations.endpoints).toContainEqual(
expect.objectContaining({ value: "https://embedded.test/app" }),
);
});
});
describe("web bundle artifact metadata", () => {
it("preserves long provider media types in artifact summaries", () => {
const result = analyzeCapturedWebBundle(inspection("export {};"));
const mediaType = `application/${"x".repeat(300)}`;
const artifact = result.capture.source_artifacts[0] ?? {
sha256: "0".repeat(64),
bytes: 0,
media_type: "application/javascript",
charset: "utf-8" as const,
text_available: true as const,
};
expect(
webBundleAnalysisSchema.parse({
...result,
capture: {
...result.capture,
source_artifacts: [{ ...artifact, media_type: mediaType }],
},
}).capture.source_artifacts[0]?.media_type,
).toBe(mediaType);
});
});
describe("deep captured web bundle syntax", () => {
it("retains evidence after a parser-admitted deep property chain", () => {
const source = `const value = root${".next".repeat(12_000)};\nimport "./last.js";\nfetch("/after");`;
const result = analyzeCapturedWebBundle(inspection(source));
expect(result.completeness).toMatchObject({
status: "complete",
parsed_scripts: 1,
parse_failures: 0,
});
expect(result.observations.chunks.edges).toContainEqual(
expect.objectContaining({
kind: "static_import",
specifier: "./last.js",
resolved_url: `${origin}/assets/last.js`,
location: expect.objectContaining({ line: 2, column: 0 }),
}),
);
expect(result.observations.endpoints).toContainEqual(
expect.objectContaining({
value: "/after",
location: expect.objectContaining({ line: 3, column: 0 }),
}),
);
});
});
const inspection = (source: string) =>
webPageInspectionSchema.parse({
browser: {
product: "Fake Chrome",
protocol_version: "1.3",
revision: "1",
user_agent: "fake",
js_version: "1",
},
target: {
target_id: "page-1",
type: "page",
title: "App",
url: `${origin}/app`,
origin,
attached: false,
},
capture_window: {
started_at: "2026-07-14T00:00:00.000Z",
ended_at: "2026-07-14T00:00:01.000Z",
observation_ms: 1_000,
},
completeness: {
status: "attach_limited",
conditions: ["attach_limited"],
policy_filtered_sections: [],
attach_limited_sections: ["network_requests"],
truncated_sections: [],
unavailable_sections: [],
excluded: [],
dropped_events: {
scripts: 0,
network_requests: 0,
console_events: 0,
websocket_connections: 0,
websocket_frames: 0,
webmcp_tools: 0,
timeline_events: 0,
total: 0,
},
},
frames: [],
dom: { total_nodes: 0, nodes: [] },
accessibility: {
total_nodes: 0,
text_capture: {
status: "not_approved",
retained_bytes: 0,
excluded_fields: 0,
},
nodes: [],
},
scripts: {
total: 1,
items: [
{
script_key: `scr_${"1".repeat(64)}`,
url: `${origin}/assets/app.js`,
origin,
cdp_hash: "hash",
length: Buffer.byteLength(source),
is_module: true,
language: "JavaScript",
source_map_url: null,
resource_reconciliation: {
status: "unmatched",
reason: "no_exact_sanitized_url",
},
source: {
included: true,
artifact: createWebTextArtifact(source, "text/javascript"),
},
},
],
},
resources: [],
network: {
requests: [],
websocket_connections: [],
coverage_started_at: "2026-07-14T00:00:00.000Z",
prior_activity_available: false,
},
console: {
events: [],
coverage_started_at: "2026-07-14T00:00:00.000Z",
prior_activity_available: false,
},
workers: [],
metadata: {
responses: [],
dom_urls: [],
agent_hints: [],
excluded_dom_urls: 0,
headers_allowlisted: true,
},
storage: {
origin,
usage_bytes: null,
quota_bytes: null,
local_storage_keys: [],
session_storage_keys: [],
indexed_db_names: [],
cache_names: [],
values_redacted: true,
},
limitations: [],
});
it("recognizes expression-free template literals as route properties", () => {
const result = analyzeCapturedWebBundle(
inspection(`
const routes = [
{ path: \`score-board\`, component: ScoreBoard },
{ route: \`administration\`, component: Admin },
{ path: \`/user/\${name}\`, component: Dynamic },
];
`),
);
expect(result.observations.routes.map(({ value }) => value)).toEqual([
"score-board",
"administration",
]);
});
it("uses the shared parser for decorated captured scripts", () => {
const result = analyzeCapturedWebBundle(
inspection(`@sealed class Widget {} fetch('/decorated');`),
);
expect(result.completeness).toMatchObject({
status: "complete",
parsed_scripts: 1,
parse_failures: 0,
});
expect(result.observations.endpoints).toEqual([
expect.objectContaining({ value: "/decorated" }),
]);
});
it("keeps bare module locations unresolved without inventing URL-relative paths", () => {
const result = analyzeCapturedWebBundle(
inspection(`
import "package-name";
import("@scope/package");
require("package-name");
import "./actual.js";
importScripts("worker.js");
`),
);
for (const specifier of ["package-name", "@scope/package"])
expect(
result.observations.chunks.edges
.filter((edge) => edge.specifier === specifier)
.every((edge) => edge.resolved_url === null),
).toBe(true);
expect(
result.observations.chunks.edges.find(
(edge) => edge.specifier === "./actual.js",
)?.resolved_url,
).toBe(`${origin}/assets/actual.js`);
expect(
result.observations.chunks.edges.find(
(edge) => edge.specifier === "worker.js",
)?.resolved_url,
).toBe(`${origin}/assets/worker.js`);
});
it("retains each literal importScripts argument in source order", () => {
const result = analyzeCapturedWebBundle(
inspection(
'importScripts("first.js", dynamicValue, "second.js", "first.js");',
),
);
expect(
result.observations.chunks.edges
.filter(({ kind }) => kind === "worker_import")
.map(({ specifier }) => specifier),
).toEqual(["first.js", "second.js"]);
});
describe("web metadata key semantics", () => {
it("keeps computed metadata keys and overwrite order conservative", () => {
const result = analyzeCapturedWebBundle(
inspection(`
const path = "description";
const routes = [{ [path]: "/not-a-route" }, { ["path"]: "/real" }];
document.modelContext.registerTool({
name: "old", name: "new",
inputSchema: { properties: { [name]: {}, literal: {} } }
});
document.modelContext.registerTool({ name: "old", ...dynamic });
document.modelContext.registerTool({ name: "old", [name]: "dynamic" });
document.modelContext.registerTool({ name: "old", get name() {} });
document.modelContext.registerTool({ ...dynamic, ["name"]: "restored" });
document.modelContext.registerTool({ name: "valid", [""]: 0 });
`),
);
expect(result.observations.routes.map(({ value }) => value)).toEqual([
"/real",
]);
expect(result.observations.webmcp_declarations).toEqual([
expect.objectContaining({
name: "new",
schema_property_names: ["literal"],
}),
expect.objectContaining({ name: null }),
expect.objectContaining({ name: "restored" }),
expect.objectContaining({ name: "valid" }),
]);
});
it("projects only exact input schema property names", () => {
const result = analyzeCapturedWebBundle(
inspection(`
document.modelContext.registerTool({
name: "literal",
inputSchema: {
type: "object",
properties: { type: {}, properties: {}, "": {}, [dynamicKey]: {}, ...dynamicProperties }
}
});
document.modelContext.registerTool({ name: "missing properties", inputSchema: { type: "object" } });
document.modelContext.registerTool({ name: "dynamic properties", inputSchema: { properties: dynamicProperties } });
document.modelContext.registerTool({ name: "null properties", inputSchema: { properties: null } });
document.modelContext.registerTool({ name: "missing schema" });
document.modelContext.registerTool({ name: "dynamic schema", inputSchema: schema });
document.modelContext.registerTool({ name: "null schema", inputSchema: null });
document.modelContext.registerTool({ name: "spread schema", inputSchema: { ...schema } });
document.modelContext.registerTool({
name: "computed literal keys",
["inputSchema"]: { ["properties"]: { [""]: {}, ["literal"]: {}, [dynamicKey]: {} } }
});
`),
);
expect(
result.observations.webmcp_declarations.map(
({ name, schema_property_names }) => ({ name, schema_property_names }),
),
).toEqual([
{ name: "literal", schema_property_names: ["", "properties", "type"] },
{ name: "missing properties", schema_property_names: [] },
{ name: "dynamic properties", schema_property_names: [] },
{ name: "null properties", schema_property_names: [] },
{ name: "missing schema", schema_property_names: [] },
{ name: "dynamic schema", schema_property_names: [] },
{ name: "null schema", schema_property_names: [] },
{ name: "spread schema", schema_property_names: [] },
{ name: "computed literal keys", schema_property_names: ["", "literal"] },
]);
});
});
it("retains WebMCP declarations through optional member and call chaining", () => {
const result = analyzeCapturedWebBundle(
inspection(`
document.modelContext?.registerTool({ name: "optional member" });
document.modelContext.registerTool?.({ name: "optional call" });
`),
);
expect(result.observations.webmcp_declarations).toEqual([
expect.objectContaining({
name: "optional member",
trust: "page-declared-untrusted",
}),
expect.objectContaining({
name: "optional call",
trust: "page-declared-untrusted",
}),
]);
});
it("reads expression-free template dynamic imports as chunk edges", () => {
const result = analyzeCapturedWebBundle(
inspection(`
import(\`./lazy.js\`);
import("./quoted.js");
import(\`./\${name}.js\`);
`),
);
expect(result.observations.chunks.edges).toEqual([
expect.objectContaining({
kind: "dynamic_import",
specifier: "./lazy.js",
resolved_url: `${origin}/assets/lazy.js`,
}),
expect.objectContaining({
kind: "dynamic_import",
specifier: "./quoted.js",
}),
]);
});
it("does not infer call names from dynamic computed identifiers", () => {
const result = analyzeCapturedWebBundle(
inspection(`
const fetch = "render";
const require = "render";
const registerTool = "render";
window[fetch]("/render-only");
window[require]("./not-a-module.js");
document.modelContext[registerTool]({ name: "not-a-tool" });
`),
);
expect(result.observations.endpoints).toEqual([]);
expect(result.observations.chunks.edges).toEqual([]);
expect(result.observations.webmcp_declarations).toEqual([]);
});
it("retains direct and literal computed call names", () => {
const result = analyzeCapturedWebBundle(
inspection(`
window.fetch("/direct");
window["fetch"]("/literal");
window[receiver].fetch("/nested-receiver");
window.require("./direct.js");
window["require"]("./literal.js");
document.modelContext["registerTool"]({ name: "literal-tool" });
`),
);
expect(result.observations.endpoints.map(({ value }) => value)).toEqual([
"/direct",
"/literal",
"/nested-receiver",
]);
expect(
result.observations.chunks.edges.map(({ specifier }) => specifier),
).toEqual(["./direct.js", "./literal.js"]);
expect(result.observations.webmcp_declarations).toEqual([
expect.objectContaining({ name: "literal-tool" }),
]);
});
it("requires WebMCP receiver and method names to occupy exact member segments", () => {
const result = analyzeCapturedWebBundle(
inspection(`
navigator.modelContext.registerTool({ name: "navigator" });
local.modelContext.registerTool({ name: "exact nested" });
const appmodelContext = { registerTool() {} };
appmodelContext.registerTool({ name: "receiver suffix" });
const app = { analyticsmodelContext: { registerTool() {} } };
app.analyticsmodelContext.registerTool({ name: "nested suffix" });
window["modelContext.registerTool"]({ name: "dotted property" });
window["modelContext"].registerTool({ name: "computed receiver" });
`),
);
expect(result.observations.webmcp_declarations).toEqual([
expect.objectContaining({ name: "navigator" }),
expect.objectContaining({ name: "exact nested" }),
expect.objectContaining({ name: "computed receiver" }),
]);
});
it("recognizes tRPC procedures and named GraphQL operations in captured scripts", () => {
const result = analyzeCapturedWebBundle(
inspection(`
const n = createTRPCClient({ links: [httpBatchLink({ url: "/api/trpc" })] });
e.invoice.list.useQuery({ competencia: "2026-09" });
n.empresa.byCnpj.query("00000000000191");
const q = "query ListarNotas($competencia: String!) { notas { id } }";
this.client.query({ query: q });
`),
);
expect(
result.observations.endpoints.map(({ value, mechanism }) => ({
value,
mechanism,
})),
).toEqual([
{ value: "/api/trpc", mechanism: "trpc:link:httpBatchLink" },
{ value: "invoice.list", mechanism: "trpc:procedure:useQuery" },
{ value: "empresa.byCnpj", mechanism: "trpc:procedure:query" },
{ value: "ListarNotas", mechanism: "graphql:query" },
]);
});
it("keeps RPC lexical identity and bundled factory recognition in captured scripts", () => {
const longOperation = "Operation" + "x".repeat(512);
const document =
"#" +
"comment".repeat(700) +
"\nquery " +
longOperation +
" { users { id } }";
const result = analyzeCapturedWebBundle(
inspection(`
function first() { const c = createTRPCClient({}); }
function unrelated(c) { c.users.query("select 1"); }
const c = (0, t.createTRPCClient)({ links: [(0, t.httpBatchLink)({ url: "/api/rpc" })] });
c.posts.query();
const doc = ${JSON.stringify(document)};
`),
);
expect(
result.observations.endpoints.map(({ value, mechanism }) => ({
value,
mechanism,
})),
).toEqual([
{ value: "/api/rpc", mechanism: "trpc:link:httpBatchLink" },
{ value: "posts", mechanism: "trpc:procedure:query" },
{ value: longOperation, mechanism: "graphql:query" },
]);
expect(result.completeness.status).toBe("complete");
});
it("retains distinct WebMCP descriptions and names while deduplicating equivalent properties", () => {
const result = analyzeCapturedWebBundle(
inspection(`
document.modelContext.registerTool({ name: "lookup", description: "first", inputSchema: { properties: { alpha: {} } } });
document.modelContext.registerTool({ name: "lookup", description: "second", inputSchema: { properties: { alpha: {} } } });
document.modelContext.registerTool({ name: "equivalent", inputSchema: { properties: { alpha: {}, beta: {} } } });
document.modelContext.registerTool({ name: "equivalent", inputSchema: { properties: { beta: {}, alpha: {}, alpha: {} } } });
document.modelContext.registerTool({ description: "unnamed" });
document.modelContext.registerTool({ name: "", description: "unnamed" });
`),
);
expect(
result.observations.webmcp_declarations.map(
({ name, description, schema_property_names }) => ({
name,
description,
schema_property_names,
}),
),
).toEqual([
{
name: "lookup",
description: "first",
schema_property_names: ["alpha"],
},
{
name: "lookup",
description: "second",
schema_property_names: ["alpha"],
},
{
name: "equivalent",
description: null,
schema_property_names: ["alpha", "beta"],
},
{ name: null, description: "unnamed", schema_property_names: [] },
{ name: "", description: "unnamed", schema_property_names: [] },
]);
expect(result.observations.webmcp_declarations[2]?.location).toEqual({
script_key: `scr_${"1".repeat(64)}`,
line: 4,
column: 6,
});
expect(
result.observations.webmcp_declarations.every(
({ trust }) => trust === "page-declared-untrusted",
),
).toBe(true);
});