fix(javascript): preserve ESM path intent and artifact confinement (#2700)

* fix(javascript): preserve legacy ESM directory intent

* fix(javascript): normalize legacy ESM URL directory requests

* fix(javascript): retain invalid package URL evidence

* test(apple): bound cold archive fixture compilation

* test(release): scope preflight schema to selected jobs

* fix(javascript): preserve package URL admission and target facts

* fix(javascript): validate package target structure before URL lookup

* fix(javascript): preserve surrogate identity in structural package URLs

* fix(javascript): isolate structural package URL identities

* fix(javascript): resolve paths after opaque ancestors normalize away

* fix(javascript): confine legacy URLs and retain target provenance

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
This commit is contained in:
Rohit Ghumareandmorluto authored and GitHub committed 2026-10-23 02:34:28 +08:00
1 parent 92a9591a41
commit 6714fb1d02
3 files changed
+89 -4

No files matched your search

@@ -1096,10 +1096,19 @@ const resolveLegacyEsmSubpath = (
directory: string,
subpath: string,
): CandidateResolution => {
const declarationRejection = rejectDeclaration(
stripQueryAndFragment(htmlUrlText(subpath)),
);
const subpathPath = stripQueryAndFragment(htmlUrlText(subpath));
const declarationRejection = rejectDeclaration(subpathPath);
if (declarationRejection !== null) return declarationRejection;
let depth = directory === "." ? 0 : directory.split("/").length;
for (const segment of subpathPath.split("/")) {
if (segment === "..") {
if (depth === 0)
return unresolvedCandidate("rejected", [
"The resolved candidate escapes the canonical artifact root.",
]);
depth--;
} else if (segment !== ".") depth++;
}
const metadataUrl = packageMetadataUrl(
posix.join(directory, "package.json"),
subpath,
@@ -1208,7 +1217,9 @@ const resolveExportTarget = (
const candidate = confineCandidate(decoded);
if (typeof candidate !== "string") return withTargetSource(candidate);
if (target.lookupLimitation !== undefined)
return unresolvedCandidate("unavailable", [target.lookupLimitation]);
return withTargetSource(
unresolvedCandidate("unavailable", [target.lookupLimitation]),
);
return (
resolveFileCandidates(input, [candidate]) ??
withTargetSource(exactPackageTargetNotFound(candidate, mapKind))
@@ -9,6 +9,7 @@ import { expect } from "vitest";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
import { cliTest } from "../../support/cli/cliFixture.js";
import { analyzeJavaScriptDirectory } from "../../support/cli/javascriptApplication.js";
import { writeFixtureFiles } from "../../support/javascriptApplicationFixture.js";
type PackageSpecifierCase = {
readonly specifier: string;
@@ -382,3 +383,62 @@ cliTest.for(["CLI", "stdio MCP"] as const)(
);
},
);
cliTest.for(["CLI", "stdio MCP"] as const)(
"confines legacy package traversal before URL normalization through %s",
async (surface, { cli }) => {
const root = await createTestTempDirectory("rea-package-root-traversal-");
const cases = [
{ specifier: "legacy/../../outside.js", status: "resolved" },
{
specifier: "legacy/../../outside.js?cache=/../../rea-artifact/#/..",
status: "resolved",
},
{ specifier: "legacy//../../../outside.js", status: "resolved" },
{
specifier: "legacy/../../../rea-artifact/outside.js",
status: "rejected",
},
{
specifier: "legacy/../../../../rea-artifact/outside.js",
status: "rejected",
},
{
specifier: "legacy/../.\t./.\n./rea-artifact/outside.js?cache=1#entry",
status: "rejected",
},
] as const;
const source = cases
.map(({ specifier }) => `import ${JSON.stringify(specifier)};`)
.join("\n");
await writeFixtureFiles(root, {
"main.mjs": source,
"outside.js": "export default 1;",
"node_modules/legacy/package.json": "{}",
});
const { graph } = await analyzeJavaScriptDirectory(surface, cli, root);
for (const { specifier, status } of cases)
expect(graph.edges).toContainEqual(
expect.objectContaining({
relation: "imports",
properties: expect.objectContaining({
specifier,
resolution_status: status,
resolved_path: status === "resolved" ? "outside.js" : null,
}),
evidence: expect.objectContaining({
...(status === "rejected"
? {
limitations: expect.arrayContaining([
"The resolved candidate escapes the canonical artifact root.",
]),
}
: {}),
artifact: expect.objectContaining({
sha256: createHash("sha256").update(source).digest("hex"),
}),
}),
}),
);
},
);
@@ -232,6 +232,13 @@ cliTest.for(["CLI", "stdio MCP"] as const)(
request.status === "root-legacy"
? fileStatus
: request.status;
const mapKind = request.specifier.startsWith("#")
? "imports"
: "exports";
const selectedTarget =
request.specifier === "mapped/structuralReentry"
? targets.structuralReentry.value
: targets.feature.value;
expect(graph.edges).toContainEqual(
expect.objectContaining({
relation: "imports",
@@ -249,6 +256,13 @@ cliTest.for(["CLI", "stdio MCP"] as const)(
status === "unavailable" && request.status !== "unavailable"
? expect.arrayContaining([
expect.stringContaining("unpaired UTF-16 surrogate"),
...(request.status === "relative"
? [
expect.stringContaining(
`${mapKind} target ${JSON.stringify(selectedTarget)}:`,
),
]
: []),
])
: expect.not.arrayContaining([
expect.stringContaining("unpaired UTF-16 surrogate"),