From 4c52731051845ba56023fe748b9c9e436ab62de8 Mon Sep 17 00:00:00 2001 From: Gustavo Madeira Santana Date: Tue, 14 Apr 2026 21:15:43 -0400 Subject: [PATCH] fix(ci): parse quoted pnpm snapshot keys --- scripts/pre-commit/pnpm-audit-prod.mjs | 39 +++++++++++++++++++++++++- test/scripts/pnpm-audit-prod.test.ts | 29 +++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/scripts/pre-commit/pnpm-audit-prod.mjs b/scripts/pre-commit/pnpm-audit-prod.mjs index 155a87b7b51..0b974452329 100644 --- a/scripts/pre-commit/pnpm-audit-prod.mjs +++ b/scripts/pre-commit/pnpm-audit-prod.mjs @@ -170,8 +170,45 @@ function parseInlineYamlMap(rawValue) { return result; } +function findYamlMappingSeparator(line) { + let quote = null; + let depth = 0; + + for (let index = 0; index < line.length; index += 1) { + const character = line[index]; + if (quote) { + if (character === quote) { + quote = null; + } + continue; + } + if (character === "'" || character === '"') { + quote = character; + continue; + } + if (character === "{" || character === "[" || character === "(") { + depth += 1; + continue; + } + if (character === "}" || character === "]" || character === ")") { + depth = Math.max(0, depth - 1); + continue; + } + if (character !== ":" || depth !== 0) { + continue; + } + + const nextCharacter = line[index + 1]; + if (nextCharacter === undefined || /\s/u.test(nextCharacter)) { + return index; + } + } + + return -1; +} + function parseYamlMappingLine(line) { - const separatorIndex = line.indexOf(":"); + const separatorIndex = findYamlMappingSeparator(line); if (separatorIndex === -1) { return null; } diff --git a/test/scripts/pnpm-audit-prod.test.ts b/test/scripts/pnpm-audit-prod.test.ts index f25b36375e2..8487f906f0d 100644 --- a/test/scripts/pnpm-audit-prod.test.ts +++ b/test/scripts/pnpm-audit-prod.test.ts @@ -105,6 +105,35 @@ snapshots: }); }); + it("resolves quoted snapshot keys that contain tarball URLs", () => { + const lockfile = `lockfileVersion: '9.0' + +importers: + .: + dependencies: + wrapper: + version: 1.0.0 + +snapshots: + wrapper@1.0.0: + dependencies: + libsignal: '@whiskeysockets/libsignal-node@https://codeload.github.com/whiskeysockets/libsignal-node/tar.gz/abc123' + '@whiskeysockets/libsignal-node@https://codeload.github.com/whiskeysockets/libsignal-node/tar.gz/abc123': + dependencies: + curve25519-js: 0.0.4 + curve25519-js@0.0.4: {} +`; + + const payload = createBulkAdvisoryPayload(collectProdResolvedPackagesFromLockfile(lockfile)); + expect(payload).toEqual({ + "@whiskeysockets/libsignal-node": [ + "https://codeload.github.com/whiskeysockets/libsignal-node/tar.gz/abc123", + ], + "curve25519-js": ["0.0.4"], + wrapper: ["1.0.0"], + }); + }); + it("filters advisory findings by minimum severity", () => { const findings = filterFindingsBySeverity( {