mirror of
https://github.com/morluto/rea.git
synced 2026-11-12 17:59:08 +00:00
fix(audit): keep a declared .map from reading as a linker map
A script's sourceMappingURL=assets.map was dropped because the name already looked like a map. A malformed assets.map then settled as a linker map, so both source-map checks read not_observed and native.debug_companions reported an exposure the release does not ship. Keep a generic .map name as a declared target and read it as a JavaScript map, in either scan order, so it stays unresolved.
This commit is contained in:
2 files changed
+36
-3
No files matched your search
@@ -2631,6 +2631,32 @@ describe("ReleaseExposureReader member identity", () => {
|
||||
},
|
||||
);
|
||||
|
||||
it.each([
|
||||
["app.js", { embedded: 0, unparsed: 1, skipped: 0 }],
|
||||
["z.js", { embedded: 0, unparsed: 0, skipped: 1 }],
|
||||
])(
|
||||
"keeps a malformed assets.map that %s declares unresolved",
|
||||
async (script, expected) => {
|
||||
const root = await createTestTempDirectory("rea-release-generic-map-");
|
||||
await writeFile(
|
||||
join(root, script),
|
||||
"const value = 1;\n//# sourceMappingURL=assets.map\n",
|
||||
);
|
||||
await writeFile(join(root, "assets.map"), "not a map\n");
|
||||
const scanned = await inspect(root);
|
||||
expect(scanned.source_maps).toMatchObject(expected);
|
||||
expect(scanned.debug_companions.paths).toEqual([]);
|
||||
},
|
||||
);
|
||||
|
||||
it("keeps an undeclared malformed assets.map a linker map", async () => {
|
||||
const root = await createTestTempDirectory("rea-release-linker-map-");
|
||||
await writeFile(join(root, "assets.map"), "not a map\n");
|
||||
const scanned = await inspect(root);
|
||||
expect(scanned.source_maps).toMatchObject({ embedded: 0, skipped: 0 });
|
||||
expect(scanned.debug_companions.paths).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("counts a declared map target that never ships as skipped", async () => {
|
||||
const root = await createTestTempDirectory("rea-release-missing-map-");
|
||||
await writeFile(
|
||||
|
||||
@@ -987,8 +987,11 @@ const examineMapMember = async (
|
||||
member: MemberView,
|
||||
): Promise<boolean> => {
|
||||
// A member a script names or an owner marks as a map is a JavaScript map
|
||||
// whatever it is called.
|
||||
const declared = member.logical.toLowerCase().endsWith(".map")
|
||||
// whatever it is called. Only an undeclared `.map` may be a linker map.
|
||||
const undeclared =
|
||||
member.logical.toLowerCase().endsWith(".map") &&
|
||||
!state.mapTargets.has(memberLocationKey(member.location));
|
||||
const declared = undeclared
|
||||
? member
|
||||
: { ...member, logical: `${member.logical}.js.map` };
|
||||
const loaded = await examineMap(state, declared);
|
||||
@@ -1380,7 +1383,9 @@ const noteLocalMapReference = (
|
||||
}
|
||||
if (/^[a-z][a-z0-9+.-]+:/iu.test(url)) return;
|
||||
const path = url.replace(/[?#].*$/su, "");
|
||||
if (path.length === 0 || isSourceMap(path, "file")) return;
|
||||
// A generic `.map` name stays a target: only the declaration tells it from a
|
||||
// linker map.
|
||||
if (path.length === 0 || isJavaScriptSourceMapName(path)) return;
|
||||
let decoded: string;
|
||||
try {
|
||||
decoded = decodeURIComponent(path);
|
||||
@@ -1398,6 +1403,8 @@ const noteLocalMapReference = (
|
||||
*/
|
||||
const noteMapTarget = (state: ScanState, location: string): void => {
|
||||
const target = memberLocationKey(location);
|
||||
// A map read before its declaration may have settled as a linker map.
|
||||
if (state.companionPaths.delete(location)) state.skippedMaps += 1;
|
||||
if (state.examinedMaps.has(target) || state.mapTargets.has(target)) return;
|
||||
if (state.examinedLocations.has(target)) {
|
||||
state.skippedMaps += 1;
|
||||
|
||||
Reference in new issue
Block a user