fix(javascript): keep ASAR-named files without an ASAR header opaque (#2347)
Inventory expands an ASAR-named filesystem file only when its bytes are an ASAR. JavaScript reconstruction expanded it on the suffix alone, so a directory holding any other file named *.asar failed the whole analysis with an invalid ASAR header. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
This commit is contained in:
parent
84ec40f1af
commit
dd4bfed614
|
|
@ -37,6 +37,7 @@ interface ExpectedFile {
|
|||
|
||||
interface ExpectedContainer {
|
||||
readonly hash_status: ArtifactOccurrence["hash_status"];
|
||||
readonly format: ArtifactOccurrence["artifact_format"];
|
||||
readonly inventory: JavaScriptArtifactContainer | null;
|
||||
}
|
||||
|
||||
|
|
@ -219,6 +220,9 @@ const visitReader = async (
|
|||
"integrity",
|
||||
`Nested ASAR was not integrity-verified: ${path}`,
|
||||
);
|
||||
// Inventory expands an ASAR-named file only when its bytes are an
|
||||
// ASAR. One it recorded as ordinary bytes has no members to read.
|
||||
if (container.format !== "asar") continue;
|
||||
const inventory = container.inventory;
|
||||
if (inventory === null)
|
||||
throw new ArtifactReaderFailure(
|
||||
|
|
@ -395,6 +399,7 @@ const expectedInventory = (
|
|||
if (isNestedAsar)
|
||||
containers.set(occurrence.logical_path, {
|
||||
hash_status: occurrence.hash_status,
|
||||
format: occurrence.artifact_format,
|
||||
inventory: null,
|
||||
});
|
||||
continue;
|
||||
|
|
@ -412,6 +417,7 @@ const expectedInventory = (
|
|||
if (isNestedAsar)
|
||||
containers.set(occurrence.logical_path, {
|
||||
hash_status: occurrence.hash_status,
|
||||
format: occurrence.artifact_format,
|
||||
inventory: {
|
||||
path: occurrence.logical_path,
|
||||
sha256: node.sha256,
|
||||
|
|
|
|||
|
|
@ -105,6 +105,34 @@ it("keeps a contradicted nested ASAR opaque during JavaScript reconstruction", a
|
|||
expect(result.graph.coverage.omitted_count).toBeNull();
|
||||
});
|
||||
|
||||
it("keeps an ASAR-named file without an ASAR header opaque during JavaScript reconstruction", async () => {
|
||||
const root = await createTestTempDirectory("rea-opaque-asar-name-");
|
||||
await writeFile(join(root, "main.js"), "export const outer = true;\n");
|
||||
// Inventory records this file as ordinary bytes and does not expand it.
|
||||
await writeFile(join(root, "ordinary.asar"), "ordinary bytes");
|
||||
|
||||
const snapshot = await scanCanonicalArtifactInventory(root, {});
|
||||
const reader = createJavaScriptArtifactReader(root, "directory");
|
||||
try {
|
||||
const read = await readJavaScriptArtifactFiles(reader, snapshot);
|
||||
expect(read.files.map(({ path }) => path)).toEqual(["main.js"]);
|
||||
expect(read.containers).toEqual([]);
|
||||
} finally {
|
||||
await reader.close();
|
||||
}
|
||||
|
||||
const analyzed = await analyzeJavaScriptApplication({
|
||||
input_path: root,
|
||||
format: "directory",
|
||||
});
|
||||
if (!analyzed.ok) throw analyzed.error;
|
||||
const result = javascriptApplicationAnalysisResultSchema.parse(
|
||||
analyzed.value.normalized_result,
|
||||
);
|
||||
expect(result.statistics.nested_asar_containers).toBe(0);
|
||||
expect(result.integrity_contradictions).toEqual([]);
|
||||
});
|
||||
|
||||
it("retains semantic resource limits alongside recorded integrity contradictions", async () => {
|
||||
const { archive } = await createStrippedAsarAddon([
|
||||
{ path: "app.js", contents: primitiveCandidateExpansionSource() },
|
||||
|
|
|
|||
Loading…
Reference in New Issue