58 lines
2.1 KiB
TypeScript
58 lines
2.1 KiB
TypeScript
import { execFile } from "node:child_process";
|
|||
|
|
import { writeFile } from "node:fs/promises";
|
||
|
|
import { join } from "node:path";
|
||
|
|
import { promisify } from "node:util";
|
||
|
|
|
||
|
|
import { expect, it } from "vitest";
|
||
|
|
|
||
|
|
import { parseEvidence } from "../../../src/domain/evidence.js";
|
||
|
|
import { javascriptApplicationAnalysisResultSchema } from "../../../src/domain/javascript/javascriptApplicationAnalysis.js";
|
||
|
|
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
|
||
|
|
|
||
|
|
const execute = promisify(execFile);
|
||
|
|
|
||
|
|
it("reports partial JavaScript request targets through the public CLI", async () => {
|
||
|
|
const root = await createTestTempDirectory("rea-js-partial-endpoints-cli-");
|
||
|
|
await writeFile(
|
||
|
|
join(root, "main.js"),
|
||
|
|
"fetch(target); fetch('target'); fetch(`https://${hosts['a@b']}/items/${id}`); function other(target) { fetch(target); }",
|
||
|
|
);
|
||
|
|
const { stdout } = await execute(
|
||
|
|
process.execPath,
|
||
|
|
["scripts/rea.mjs", "analyze-javascript-application", root, "--json"],
|
||
|
|
{ cwd: process.cwd(), maxBuffer: 16 * 1024 * 1024 },
|
||
|
|
);
|
||
|
|
const result = javascriptApplicationAnalysisResultSchema.parse(
|
||
|
|
parseEvidence(JSON.parse(stdout)).normalized_result,
|
||
|
|
);
|
||
|
|
const endpoints = result.graph.nodes.filter(
|
||
|
|
({ kind }) => kind === "endpoint",
|
||
|
|
);
|
||
|
|
const partial = endpoints.flatMap(({ observations, node_id }) =>
|
||
|
|
observations
|
||
|
|
.filter(({ properties }) => properties.resolution === "partial")
|
||
|
|
.map((observation) => ({ node_id, ...observation })),
|
||
|
|
);
|
||
|
|
|
||
|
|
expect(partial.map(({ properties }) => properties.value).sort()).toEqual([
|
||
|
|
"`https://${hosts['a@b']}/items/${id}`",
|
||
|
|
"target",
|
||
|
|
"target",
|
||
|
|
]);
|
||
|
|
expect(new Set(partial.map(({ node_id }) => node_id)).size).toBe(3);
|
||
|
|
expect(
|
||
|
|
partial.find(({ properties }) => properties.value === "target")?.evidence,
|
||
|
|
).toMatchObject({
|
||
|
|
authority: "ast-static-analysis",
|
||
|
|
state: "observed",
|
||
|
|
limitations: [expect.stringContaining("not an exact literal")],
|
||
|
|
});
|
||
|
|
expect(
|
||
|
|
endpoints.some(({ observations }) =>
|
||
|
|
observations.some(
|
||
|
|
({ properties }) =>
|
||
|
|
properties.value === "target" && properties.resolution === undefined,
|
||
|
|
),
|
||
|
|
),
|
||
|
|
).toBe(true);
|
||
|
|
}, 20_000);
|