trawly 0.0.2 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/commands/add.ts","../src/sources/osv.ts","../src/scanner.ts","../src/extractors/npm-package-lock.ts","../src/extractors/pnpm-lock.ts","../src/extractors/yarn-lock.ts","../src/types.ts","../src/installer/pm-detect.ts","../src/installer/runner.ts","../src/installer/spec-parser.ts","../src/installer/version-resolver.ts","../src/reporters/json.ts","../src/reporters/table.ts","../src/reporters/banner.ts"],"sourcesContent":["import { Command, InvalidArgumentError } from \"commander\";\nimport kleur from \"kleur\";\nimport { reportAdd, runAdd } from \"./commands/add.js\";\nimport {\n buildInstallCommand,\n buildRemoveCommand,\n detectPackageManager,\n type PackageManager,\n} from \"./installer/pm-detect.js\";\nimport { runPackageManager } from \"./installer/runner.js\";\nimport { reportJson } from \"./reporters/json.js\";\nimport { reportTable } from \"./reporters/table.js\";\nimport { meetsThreshold, ScanInputError, scanProject } from \"./scanner.js\";\nimport type { FailOnLevel } from \"./types.js\";\n\nconst FAIL_ON_VALUES: FailOnLevel[] = [\n \"critical\",\n \"high\",\n \"moderate\",\n \"low\",\n \"none\",\n];\nconst FORMAT_VALUES = [\"table\", \"json\"] as const;\ntype Format = (typeof FORMAT_VALUES)[number];\n\nconst PM_VALUES: PackageManager[] = [\"npm\", \"pnpm\", \"yarn\", \"bun\"];\n\nconst EXIT = {\n ok: 0,\n findings: 1,\n operational: 2,\n invalidInput: 3,\n} as const;\n\nfunction parseFailOn(value: string): FailOnLevel {\n if (!FAIL_ON_VALUES.includes(value as FailOnLevel)) {\n throw new InvalidArgumentError(\n `must be one of: ${FAIL_ON_VALUES.join(\", \")}`,\n );\n }\n return value as FailOnLevel;\n}\n\nfunction parseFormat(value: string): Format {\n if (!FORMAT_VALUES.includes(value as Format)) {\n throw new InvalidArgumentError(\n `must be one of: ${FORMAT_VALUES.join(\", \")}`,\n );\n }\n return value as Format;\n}\n\nfunction parsePm(value: string): PackageManager {\n if (!PM_VALUES.includes(value as PackageManager)) {\n throw new InvalidArgumentError(`must be one of: ${PM_VALUES.join(\", \")}`);\n }\n return value as PackageManager;\n}\n\nconst TRAWLY_VERSION = \"0.1.0\";\n\nconst program = new Command();\n\nprogram\n .name(\"trawly\")\n .description(\n \"Dependency sanity scanner. Checks installed npm packages against the OSV advisory database.\",\n )\n .version(TRAWLY_VERSION)\n .enablePositionalOptions()\n .exitOverride((err) => {\n if (err.code === \"commander.helpDisplayed\" || err.code === \"commander.help\") {\n process.exit(EXIT.ok);\n }\n if (err.code === \"commander.version\") process.exit(EXIT.ok);\n process.exit(EXIT.invalidInput);\n });\n\nprogram\n .command(\"scan\", { isDefault: true })\n .description(\n \"Scan a project and gate on findings. Exits non-zero when --fail-on is met. Use `inspect` for a log-only run.\",\n )\n .argument(\"[path]\", \"Project directory to scan\", \".\")\n .option(\n \"--lockfile <path>\",\n \"Explicit path to a lockfile (package-lock.json, pnpm-lock.yaml, or yarn.lock)\",\n )\n .option(\n \"--format <format>\",\n \"Output format: table | json\",\n parseFormat,\n \"table\" as Format,\n )\n .option(\n \"--fail-on <level>\",\n `Exit non-zero when a finding meets this severity (${FAIL_ON_VALUES.join(\"|\")})`,\n parseFailOn,\n \"high\" as FailOnLevel,\n )\n .option(\"--prod\", \"Only scan production dependencies (excludes dev)\")\n .option(\"--include-dev\", \"Include dev dependencies (default)\")\n .option(\"--no-cache\", \"Bypass any local cache\")\n .option(\n \"-v, --details\",\n \"Show one row per advisory (full table). Default groups by package.\",\n )\n .option(\n \"-q, --summary\",\n \"Show only the one-line severity summary. Mutually exclusive with --details.\",\n )\n .action(async (path: string, opts: ScanCliOptions) => {\n await runScanCommand(path, opts, { gate: true });\n });\n\nprogram\n .command(\"inspect\")\n .description(\n \"Scan a project and print findings without gating. Always exits 0 unless an operational error occurs. Use `scan` for CI gating.\",\n )\n .argument(\"[path]\", \"Project directory to scan\", \".\")\n .option(\n \"--lockfile <path>\",\n \"Explicit path to a lockfile (package-lock.json, pnpm-lock.yaml, or yarn.lock)\",\n )\n .option(\n \"--format <format>\",\n \"Output format: table | json\",\n parseFormat,\n \"table\" as Format,\n )\n .option(\"--prod\", \"Only scan production dependencies (excludes dev)\")\n .option(\"--include-dev\", \"Include dev dependencies (default)\")\n .option(\"--no-cache\", \"Bypass any local cache\")\n .option(\n \"-v, --details\",\n \"Show one row per advisory (full table). Default groups by package.\",\n )\n .option(\n \"-q, --summary\",\n \"Show only the one-line severity summary. Mutually exclusive with --details.\",\n )\n .action(async (path: string, opts: InspectCliOptions) => {\n await runScanCommand(\n path,\n { ...opts, failOn: \"none\" as FailOnLevel },\n { gate: false },\n );\n });\n\nprogram\n .command(\"add\")\n .description(\n \"Resolve, scan, and install packages. Vulnerable packages are blocked; clean ones are forwarded to your package manager.\",\n )\n .argument(\"<args...>\", \"Packages to add (e.g. next vitest@1) : PM flags after the first package are passed through\")\n .option(\n \"--fail-on <level>\",\n `Block install when a finding meets this severity (${FAIL_ON_VALUES.join(\"|\")})`,\n parseFailOn,\n \"high\" as FailOnLevel,\n )\n .option(\n \"--pm <name>\",\n `Force a package manager (${PM_VALUES.join(\"|\")}). Auto-detected by default.`,\n parsePm,\n )\n .option(\n \"--allow-vulnerable\",\n \"Install even if vulnerabilities are found (still prints findings).\",\n )\n .passThroughOptions()\n .action(async (args: string[], opts: AddCliOptions) => {\n await executeAdd(args, opts);\n });\n\nprogram\n .command(\"install\")\n .alias(\"i\")\n .description(\n \"Run the project's package manager install. With package args, behaves like `add` (gates on vulnerabilities). With none, forwards directly.\",\n )\n .argument(\"[args...]\", \"Optional packages to add\")\n .option(\n \"--fail-on <level>\",\n `Block install when a finding meets this severity (${FAIL_ON_VALUES.join(\"|\")})`,\n parseFailOn,\n \"high\" as FailOnLevel,\n )\n .option(\n \"--pm <name>\",\n `Force a package manager (${PM_VALUES.join(\"|\")})`,\n parsePm,\n )\n .option(\"--allow-vulnerable\", \"Install even if vulnerabilities are found.\")\n .passThroughOptions()\n .action(async (args: string[], opts: AddCliOptions) => {\n if (args.length === 0) {\n // Bare install: pure passthrough.\n const pm = detectPackageManager({ override: opts.pm });\n const command = buildInstallCommand(pm, []);\n process.stdout.write(\n kleur.gray(`> ${command.bin} ${command.args.join(\" \")}\\n`),\n );\n try {\n const code = await runPackageManager(command);\n process.exit(code);\n } catch (err) {\n printErr(`trawly: ${(err as Error).message}`);\n process.exit(EXIT.operational);\n }\n }\n await executeAdd(args, opts);\n });\n\nprogram\n .command(\"remove\")\n .alias(\"uninstall\")\n .description(\n \"Remove packages by delegating to the project's package manager (no scan).\",\n )\n .argument(\"<args...>\", \"Packages to remove\")\n .option(\n \"--pm <name>\",\n `Force a package manager (${PM_VALUES.join(\"|\")})`,\n parsePm,\n )\n .passThroughOptions()\n .action(async (args: string[], opts: { pm?: PackageManager }) => {\n const pm = detectPackageManager({ override: opts.pm });\n const { specs, flags } = splitArgs(args);\n const command = buildRemoveCommand(pm, specs, flags);\n process.stdout.write(\n kleur.gray(`> ${command.bin} ${command.args.join(\" \")}\\n`),\n );\n try {\n const code = await runPackageManager(command);\n process.exit(code);\n } catch (err) {\n printErr(`trawly: ${(err as Error).message}`);\n process.exit(EXIT.operational);\n }\n });\n\ninterface ScanCliOptions {\n lockfile?: string;\n format: Format;\n failOn: FailOnLevel;\n prod?: boolean;\n includeDev?: boolean;\n cache?: boolean;\n details?: boolean;\n summary?: boolean;\n}\n\ntype InspectCliOptions = Omit<ScanCliOptions, \"failOn\">;\n\ninterface AddCliOptions {\n failOn: FailOnLevel;\n pm?: PackageManager;\n allowVulnerable?: boolean;\n}\n\nasync function runScanCommand(\n path: string,\n opts: ScanCliOptions,\n { gate }: { gate: boolean },\n): Promise<void> {\n if (opts.prod && opts.includeDev) {\n printErr(\"Cannot combine --prod and --include-dev. Choose one.\");\n process.exit(EXIT.invalidInput);\n }\n if (opts.details && opts.summary) {\n printErr(\"Cannot combine --details and --summary. Choose one.\");\n process.exit(EXIT.invalidInput);\n }\n\n try {\n const result = await scanProject({\n cwd: path,\n lockfile: opts.lockfile,\n includeDev: opts.includeDev,\n prodOnly: opts.prod,\n cache: opts.cache,\n });\n\n if (opts.format === \"json\") {\n process.stdout.write(`${reportJson(result)}\\n`);\n } else {\n const view = opts.summary\n ? \"summary\"\n : opts.details\n ? \"details\"\n : \"grouped\";\n const brand = process.stdout.isTTY === true;\n process.stdout.write(`${reportTable(result, { view, brand })}\\n`);\n }\n\n if (result.errors.length > 0) {\n process.exit(EXIT.operational);\n }\n\n if (!gate) {\n if (opts.format !== \"json\" && result.findings.length > 0) {\n process.stdout.write(\n `${kleur.gray(\n \"ℹ inspect mode: exiting 0 regardless of findings. Run `trawly scan` to gate CI.\",\n )}\\n`,\n );\n }\n process.exit(EXIT.ok);\n }\n\n if (meetsThreshold(result.findings, opts.failOn)) {\n if (opts.format !== \"json\") {\n process.stderr.write(\n `${kleur.red(\n `× Failing because at least one finding meets --fail-on=${opts.failOn}.`,\n )}\\n${kleur.gray(\n \" Run `trawly inspect` to log without exiting non-zero, or `trawly scan --fail-on=none` to disable the gate.\",\n )}\\n`,\n );\n }\n process.exit(EXIT.findings);\n }\n process.exit(EXIT.ok);\n } catch (err) {\n if (err instanceof ScanInputError) {\n printErr(err.message);\n process.exit(EXIT.invalidInput);\n }\n printErr(`trawly: ${(err as Error).message}`);\n process.exit(EXIT.operational);\n }\n}\n\nasync function executeAdd(args: string[], opts: AddCliOptions): Promise<void> {\n try {\n const result = await runAdd(args, {\n failOn: opts.failOn,\n pm: opts.pm,\n allowVulnerable: opts.allowVulnerable,\n });\n process.stdout.write(reportAdd(result));\n\n if (result.errored.length > 0) process.exit(EXIT.operational);\n if (result.pmExitCode !== undefined && result.pmExitCode !== 0) {\n process.exit(result.pmExitCode);\n }\n if (result.blocked.length > 0) process.exit(EXIT.findings);\n process.exit(EXIT.ok);\n } catch (err) {\n printErr(`trawly: ${(err as Error).message}`);\n process.exit(EXIT.operational);\n }\n}\n\nfunction splitArgs(args: string[]): { specs: string[]; flags: string[] } {\n const specs: string[] = [];\n const flags: string[] = [];\n for (const a of args) {\n if (a.startsWith(\"-\")) flags.push(a);\n else specs.push(a);\n }\n return { specs, flags };\n}\n\nfunction printErr(msg: string): void {\n process.stderr.write(`${kleur.red(msg)}\\n`);\n}\n\nawait program.parseAsync(process.argv);\n","import kleur from \"kleur\";\nimport { queryOsv } from \"../sources/osv.js\";\nimport { compareFindings, summarize } from \"../scanner.js\";\nimport { SEVERITY_RANK } from \"../types.js\";\nimport type { Finding, PackageInstance, Severity } from \"../types.js\";\nimport {\n buildAddCommand,\n detectPackageManager,\n type PackageManager,\n} from \"../installer/pm-detect.js\";\nimport { runPackageManager } from \"../installer/runner.js\";\nimport {\n parseSpec,\n partitionArgs,\n type ParsedSpec,\n type UnsupportedReason,\n} from \"../installer/spec-parser.js\";\nimport {\n resolveVersion,\n VersionResolveError,\n type ResolvedVersion,\n} from \"../installer/version-resolver.js\";\n\nexport interface AddOptions {\n cwd?: string;\n pm?: PackageManager;\n failOn: Severity | \"none\";\n allowVulnerable?: boolean;\n fetchImpl?: typeof fetch;\n /** Test seam: replace the real spawn with a stub. */\n runner?: typeof runPackageManager;\n}\n\nexport interface AddResult {\n /** Specs we sent to the package manager. */\n installed: ResolvedSpec[];\n /** Specs we refused to install. */\n blocked: BlockedSpec[];\n /** Specs we couldn't analyze (git, file, url, alias). */\n skipped: SkippedSpec[];\n /** Specs that failed registry resolution. */\n errored: ErroredSpec[];\n /** All findings collected, sorted. */\n findings: Finding[];\n /** Exit code from the PM, or undefined if we never ran it. */\n pmExitCode?: number;\n}\n\ninterface ResolvedSpec {\n spec: ParsedSpec;\n resolved: ResolvedVersion;\n findings: Finding[];\n}\n\ninterface BlockedSpec extends ResolvedSpec {\n reason: \"vulnerable\";\n}\n\ninterface SkippedSpec {\n spec: ParsedSpec;\n reason: UnsupportedReason;\n}\n\ninterface ErroredSpec {\n spec: ParsedSpec;\n message: string;\n}\n\nexport async function runAdd(\n args: string[],\n options: AddOptions,\n): Promise<AddResult> {\n const { specs, flags } = partitionArgs(args);\n\n const skipped: SkippedSpec[] = [];\n const resolvable: ParsedSpec[] = [];\n for (const spec of specs) {\n if (spec.unsupported) {\n skipped.push({ spec, reason: spec.unsupported });\n } else {\n resolvable.push(spec);\n }\n }\n\n const resolved: ResolvedSpec[] = [];\n const errored: ErroredSpec[] = [];\n await Promise.all(\n resolvable.map(async (spec) => {\n try {\n const r = await resolveVersion(spec.name, spec.requested, {\n fetchImpl: options.fetchImpl,\n });\n resolved.push({ spec, resolved: r, findings: [] });\n } catch (err) {\n const message =\n err instanceof VersionResolveError\n ? err.message\n : `Registry error: ${(err as Error).message}`;\n errored.push({ spec, message });\n }\n }),\n );\n\n let findings: Finding[] = [];\n if (resolved.length > 0) {\n const instances: PackageInstance[] = resolved.map((r) => ({\n name: r.spec.name,\n version: r.resolved.version,\n ecosystem: \"npm\",\n path: r.spec.raw,\n direct: true,\n dev: false,\n optional: false,\n }));\n try {\n findings = await queryOsv(instances, { fetchImpl: options.fetchImpl });\n } catch (err) {\n // If OSV is unreachable we cannot make a safe call; treat as a hard error\n // for every resolvable spec rather than silently letting installs through.\n const message = `OSV query failed: ${(err as Error).message}`;\n for (const r of resolved) errored.push({ spec: r.spec, message });\n resolved.length = 0;\n }\n }\n\n for (const f of findings) {\n const owner = resolved.find(\n (r) => r.spec.name === f.packageName && r.resolved.version === f.installedVersion,\n );\n if (owner) owner.findings.push(f);\n }\n\n const blocked: BlockedSpec[] = [];\n const installed: ResolvedSpec[] = [];\n for (const r of resolved) {\n if (shouldBlock(r.findings, options)) {\n blocked.push({ ...r, reason: \"vulnerable\" });\n } else {\n installed.push(r);\n }\n }\n\n findings.sort(compareFindings);\n\n let pmExitCode: number | undefined;\n if (installed.length > 0) {\n const pm = detectPackageManager({ override: options.pm, cwd: options.cwd });\n const cmd = buildAddCommand(\n pm,\n installed.map((r) => r.spec.raw),\n flags,\n );\n process.stdout.write(\n kleur.gray(`> ${cmd.bin} ${cmd.args.join(\" \")}\\n`),\n );\n const runner = options.runner ?? runPackageManager;\n pmExitCode = await runner(cmd, { cwd: options.cwd });\n }\n\n return { installed, blocked, skipped, errored, findings, pmExitCode };\n}\n\nexport function reportAdd(result: AddResult): string {\n const lines: string[] = [];\n\n if (result.skipped.length > 0) {\n for (const s of result.skipped) {\n lines.push(\n kleur.yellow(\n `~ Skipped ${s.spec.raw}: ${describeUnsupported(s.reason)} (cannot scan; not forwarded to install)`,\n ),\n );\n }\n }\n\n if (result.errored.length > 0) {\n for (const e of result.errored) {\n lines.push(kleur.red(`! ${e.spec.raw}: ${e.message}`));\n }\n }\n\n if (result.blocked.length > 0) {\n for (const b of result.blocked) {\n const sev = summarize(b.findings);\n const counts = describeSeverityCounts(sev);\n lines.push(\n kleur.red(\n `✗ Blocked ${b.spec.name}@${b.resolved.version}: ${counts}`,\n ),\n );\n if (b.resolved.source === \"fallback-latest\") {\n lines.push(\n kleur.gray(\n ` (scanned latest because we don't resolve semver ranges yet; you asked for \"${b.resolved.requested}\")`,\n ),\n );\n }\n for (const f of b.findings) {\n lines.push(\n ` - [${colorSeverity(f.severity)}] ${f.id} : ${f.summary}`,\n );\n if (f.fixedVersions.length > 0) {\n lines.push(kleur.gray(` fixed in: ${f.fixedVersions.join(\", \")}`));\n }\n if (f.url) lines.push(kleur.gray(` ${f.url}`));\n }\n }\n }\n\n if (result.installed.length > 0) {\n const names = result.installed\n .map((r) => `${r.spec.name}@${r.resolved.version}`)\n .join(\", \");\n lines.push(kleur.green(`✓ Installing: ${names}`));\n } else if (result.blocked.length > 0) {\n lines.push(\n kleur.red(\"Nothing installed : all requested packages were blocked.\"),\n );\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction shouldBlock(findings: Finding[], options: AddOptions): boolean {\n if (options.allowVulnerable) return false;\n if (options.failOn === \"none\") return false;\n const threshold = SEVERITY_RANK[options.failOn];\n return findings.some((f) => SEVERITY_RANK[f.severity] >= threshold);\n}\n\nfunction describeUnsupported(reason: UnsupportedReason): string {\n switch (reason) {\n case \"git\":\n return \"git specs cannot be scanned against OSV\";\n case \"url\":\n return \"URL specs cannot be scanned against OSV\";\n case \"file\":\n return \"local file specs cannot be scanned against OSV\";\n case \"alias\":\n return \"npm aliases are not supported in v1\";\n case \"workspace\":\n return \"workspace protocol specs are not scanned\";\n case \"invalid\":\n return \"could not parse spec\";\n }\n}\n\nfunction describeSeverityCounts(summary: Record<Severity, number>): string {\n const parts: string[] = [];\n for (const sev of [\"critical\", \"high\", \"moderate\", \"low\", \"unknown\"] as Severity[]) {\n if (summary[sev] > 0) parts.push(`${summary[sev]} ${sev}`);\n }\n return parts.length === 0 ? \"no advisories\" : `${parts.join(\", \")} advisor${total(summary) === 1 ? \"y\" : \"ies\"}`;\n}\n\nfunction total(summary: Record<Severity, number>): number {\n return Object.values(summary).reduce((a, b) => a + b, 0);\n}\n\nfunction colorSeverity(sev: Severity): string {\n switch (sev) {\n case \"critical\":\n return kleur.bold().red(sev);\n case \"high\":\n return kleur.red(sev);\n case \"moderate\":\n return kleur.yellow(sev);\n case \"low\":\n return kleur.cyan(sev);\n case \"unknown\":\n return kleur.gray(sev);\n }\n}\n\n// Re-exports so tests can poke at the parsed spec type.\nexport { parseSpec };\n","import type { Finding, PackageInstance, Severity } from \"../types.js\";\n\nconst OSV_QUERYBATCH_URL = \"https://api.osv.dev/v1/querybatch\";\nconst OSV_VULN_URL = \"https://api.osv.dev/v1/vulns\";\nconst QUERY_CHUNK_SIZE = 500;\nconst REQUEST_TIMEOUT_MS = 15_000;\nconst MAX_RETRIES = 2;\n\ninterface OsvQueryBatchResponse {\n results: Array<{ vulns?: Array<{ id: string; modified?: string }> }>;\n}\n\ninterface OsvSeverity {\n type: string;\n score: string;\n}\n\ninterface OsvAffectedRange {\n type: string;\n events: Array<{ introduced?: string; fixed?: string; last_affected?: string }>;\n}\n\ninterface OsvAffectedPackage {\n package?: { ecosystem?: string; name?: string };\n ranges?: OsvAffectedRange[];\n versions?: string[];\n}\n\ninterface OsvVulnDetail {\n id: string;\n summary?: string;\n details?: string;\n references?: Array<{ type?: string; url?: string }>;\n severity?: OsvSeverity[];\n database_specific?: { severity?: string };\n affected?: OsvAffectedPackage[];\n}\n\nexport interface OsvQueryDeps {\n fetchImpl?: typeof fetch;\n}\n\ninterface UniquePackage {\n name: string;\n version: string;\n}\n\n/**\n * Build the deduplicated list of unique name@version pairs to query OSV with.\n */\nexport function dedupeForQuery(\n packages: PackageInstance[],\n): UniquePackage[] {\n const seen = new Set<string>();\n const out: UniquePackage[] = [];\n for (const pkg of packages) {\n const key = `${pkg.name}@${pkg.version}`;\n if (seen.has(key)) continue;\n seen.add(key);\n out.push({ name: pkg.name, version: pkg.version });\n }\n return out;\n}\n\n/**\n * Query OSV for the given installed packages and return one Finding per\n * (advisory, affected package instance) pair.\n */\nexport async function queryOsv(\n packages: PackageInstance[],\n deps: OsvQueryDeps = {},\n): Promise<Finding[]> {\n const fetchImpl = deps.fetchImpl ?? fetch;\n const unique = dedupeForQuery(packages);\n if (unique.length === 0) return [];\n\n const idsByPackage = new Map<string, Set<string>>();\n for (const chunk of chunked(unique, QUERY_CHUNK_SIZE)) {\n const body = {\n queries: chunk.map((q) => ({\n package: { ecosystem: \"npm\", name: q.name },\n version: q.version,\n })),\n };\n const res = await postJson<OsvQueryBatchResponse>(\n fetchImpl,\n OSV_QUERYBATCH_URL,\n body,\n );\n res.results.forEach((result, i) => {\n const q = chunk[i];\n if (!q) return;\n const key = `${q.name}@${q.version}`;\n if (!result.vulns || result.vulns.length === 0) return;\n const ids = idsByPackage.get(key) ?? new Set<string>();\n for (const v of result.vulns) ids.add(v.id);\n idsByPackage.set(key, ids);\n });\n }\n\n const allIds = new Set<string>();\n for (const ids of idsByPackage.values()) {\n for (const id of ids) allIds.add(id);\n }\n\n const detailsById = new Map<string, OsvVulnDetail>();\n for (const id of allIds) {\n try {\n const detail = await getJson<OsvVulnDetail>(\n fetchImpl,\n `${OSV_VULN_URL}/${encodeURIComponent(id)}`,\n );\n detailsById.set(id, detail);\n } catch {\n // Skip missing/broken records; we still have the id reported below.\n }\n }\n\n const findings: Finding[] = [];\n for (const pkg of packages) {\n const key = `${pkg.name}@${pkg.version}`;\n const ids = idsByPackage.get(key);\n if (!ids) continue;\n for (const id of ids) {\n const detail = detailsById.get(id);\n findings.push(buildFinding(pkg, id, detail));\n }\n }\n return findings;\n}\n\nfunction buildFinding(\n pkg: PackageInstance,\n id: string,\n detail: OsvVulnDetail | undefined,\n): Finding {\n const severity = detail ? parseSeverity(detail) : \"unknown\";\n const summary = detail?.summary ?? detail?.details ?? id;\n return {\n id,\n source: \"osv\",\n type: \"vulnerability\",\n severity,\n packageName: pkg.name,\n installedVersion: pkg.version,\n summary: truncate(summary, 240),\n url: pickAdvisoryUrl(detail) ?? `https://osv.dev/vulnerability/${id}`,\n fixedVersions: detail ? collectFixedVersions(detail, pkg.name) : [],\n affectedPaths: [pkg.path],\n };\n}\n\nexport function parseSeverity(detail: OsvVulnDetail): Severity {\n // GHSA records expose a normalized severity in database_specific.severity.\n const dbSpecific = detail.database_specific?.severity?.toLowerCase();\n if (\n dbSpecific === \"critical\" ||\n dbSpecific === \"high\" ||\n dbSpecific === \"moderate\" ||\n dbSpecific === \"low\"\n ) {\n return dbSpecific;\n }\n if (dbSpecific === \"medium\") return \"moderate\";\n\n const cvss = detail.severity?.find((s) => s.type?.startsWith(\"CVSS_\"));\n if (cvss) {\n const score = parseCvssScore(cvss.score);\n if (score === undefined) return \"unknown\";\n if (score >= 9.0) return \"critical\";\n if (score >= 7.0) return \"high\";\n if (score >= 4.0) return \"moderate\";\n if (score > 0) return \"low\";\n }\n return \"unknown\";\n}\n\nfunction parseCvssScore(vector: string): number | undefined {\n const direct = Number.parseFloat(vector);\n if (!Number.isNaN(direct) && vector.trim() !== \"\") return direct;\n // Some entries store the full CVSS vector string; we don't compute it here.\n return undefined;\n}\n\nfunction pickAdvisoryUrl(detail: OsvVulnDetail | undefined): string | undefined {\n if (!detail?.references) return undefined;\n const advisory = detail.references.find((r) => r.type === \"ADVISORY\");\n return advisory?.url ?? detail.references[0]?.url;\n}\n\nexport function collectFixedVersions(\n detail: OsvVulnDetail,\n packageName: string,\n): string[] {\n const out = new Set<string>();\n for (const aff of detail.affected ?? []) {\n if (aff.package?.name && aff.package.name !== packageName) continue;\n for (const range of aff.ranges ?? []) {\n for (const event of range.events ?? []) {\n if (event.fixed) out.add(event.fixed);\n }\n }\n }\n return [...out];\n}\n\nfunction* chunked<T>(items: T[], size: number): Generator<T[]> {\n for (let i = 0; i < items.length; i += size) {\n yield items.slice(i, i + size);\n }\n}\n\nasync function postJson<T>(\n fetchImpl: typeof fetch,\n url: string,\n body: unknown,\n): Promise<T> {\n return withRetry(async () => {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n try {\n const res = await fetchImpl(url, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n if (!res.ok) {\n throw new HttpError(`OSV ${res.status}: ${res.statusText}`, res.status);\n }\n return (await res.json()) as T;\n } finally {\n clearTimeout(timer);\n }\n });\n}\n\nasync function getJson<T>(fetchImpl: typeof fetch, url: string): Promise<T> {\n return withRetry(async () => {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n try {\n const res = await fetchImpl(url, { signal: controller.signal });\n if (!res.ok) {\n throw new HttpError(`OSV ${res.status}: ${res.statusText}`, res.status);\n }\n return (await res.json()) as T;\n } finally {\n clearTimeout(timer);\n }\n });\n}\n\nclass HttpError extends Error {\n constructor(message: string, public readonly status: number) {\n super(message);\n }\n}\n\nasync function withRetry<T>(fn: () => Promise<T>): Promise<T> {\n let lastErr: unknown;\n for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {\n try {\n return await fn();\n } catch (err) {\n lastErr = err;\n if (!isRetryable(err) || attempt === MAX_RETRIES) break;\n await new Promise((r) => setTimeout(r, 250 * 2 ** attempt));\n }\n }\n throw lastErr;\n}\n\nfunction isRetryable(err: unknown): boolean {\n if (err instanceof HttpError) return err.status >= 500;\n // AbortError (timeout) and network errors are retryable.\n return true;\n}\n\nfunction truncate(s: string, max: number): string {\n if (s.length <= max) return s;\n return `${s.slice(0, max - 1)}…`;\n}\n","import { existsSync, statSync } from \"node:fs\";\nimport { basename, resolve, join } from \"node:path\";\nimport { parseNpmPackageLock } from \"./extractors/npm-package-lock.js\";\nimport { parsePnpmLock } from \"./extractors/pnpm-lock.js\";\nimport { parseYarnLock } from \"./extractors/yarn-lock.js\";\nimport { queryOsv } from \"./sources/osv.js\";\nimport { SEVERITY_RANK } from \"./types.js\";\nimport type {\n Finding,\n PackageInstance,\n ScanError,\n ScanLockfileOptions,\n ScanProjectOptions,\n ScanResult,\n Severity,\n} from \"./types.js\";\n\nexport async function scanProject(\n options: ScanProjectOptions = {},\n): Promise<ScanResult> {\n const cwd = resolve(options.cwd ?? process.cwd());\n const lockfilePath = options.lockfile\n ? resolve(cwd, options.lockfile)\n : detectLockfile(cwd);\n\n if (!lockfilePath) {\n throw new ScanInputError(\n `No supported lockfile found in ${cwd}. Pass --lockfile or run in a directory with package-lock.json, pnpm-lock.yaml, or yarn.lock.`,\n );\n }\n\n return scanLockfile({\n lockfilePath,\n includeDev: options.includeDev,\n prodOnly: options.prodOnly,\n fetchImpl: options.fetchImpl,\n });\n}\n\nexport async function scanLockfile(\n options: ScanLockfileOptions,\n): Promise<ScanResult> {\n const { lockfilePath } = options;\n if (!existsSync(lockfilePath)) {\n throw new ScanInputError(`Lockfile does not exist: ${lockfilePath}`);\n }\n const stat = statSync(lockfilePath);\n if (!stat.isFile()) {\n throw new ScanInputError(`Lockfile path is not a file: ${lockfilePath}`);\n }\n\n const allInstances = parseLockfile(lockfilePath);\n const instances = filterInstances(allInstances, options);\n const errors: ScanError[] = [];\n\n let findings: Finding[] = [];\n try {\n findings = await queryOsv(instances, { fetchImpl: options.fetchImpl });\n } catch (err) {\n errors.push({\n message: \"Failed to query OSV advisory database\",\n cause: (err as Error).message,\n });\n }\n\n findings.sort(compareFindings);\n\n return {\n scannedAt: new Date().toISOString(),\n packagesScanned: instances.length,\n findings,\n summary: summarize(findings),\n errors,\n };\n}\n\nexport class ScanInputError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ScanInputError\";\n }\n}\n\nconst LOCKFILE_CANDIDATES = [\n \"pnpm-lock.yaml\",\n \"yarn.lock\",\n \"package-lock.json\",\n \"npm-shrinkwrap.json\",\n] as const;\n\nfunction detectLockfile(cwd: string): string | undefined {\n for (const file of LOCKFILE_CANDIDATES) {\n const candidate = join(cwd, file);\n if (existsSync(candidate)) return candidate;\n }\n return undefined;\n}\n\nfunction parseLockfile(lockfilePath: string): PackageInstance[] {\n const name = basename(lockfilePath);\n if (name === \"pnpm-lock.yaml\") return parsePnpmLock(lockfilePath);\n if (name === \"yarn.lock\") return parseYarnLock(lockfilePath);\n if (name === \"package-lock.json\" || name === \"npm-shrinkwrap.json\") {\n return parseNpmPackageLock(lockfilePath);\n }\n throw new ScanInputError(\n `Unsupported lockfile name: ${name}. Supported: package-lock.json, npm-shrinkwrap.json, pnpm-lock.yaml, yarn.lock.`,\n );\n}\n\nfunction filterInstances(\n instances: PackageInstance[],\n options: { includeDev?: boolean; prodOnly?: boolean },\n): PackageInstance[] {\n const includeDev = options.prodOnly ? false : options.includeDev !== false;\n if (includeDev) return instances;\n return instances.filter((p) => !p.dev);\n}\n\nexport function compareFindings(a: Finding, b: Finding): number {\n const sev = SEVERITY_RANK[b.severity] - SEVERITY_RANK[a.severity];\n if (sev !== 0) return sev;\n if (a.packageName !== b.packageName) {\n return a.packageName.localeCompare(b.packageName);\n }\n if (a.installedVersion !== b.installedVersion) {\n return a.installedVersion.localeCompare(b.installedVersion);\n }\n return a.id.localeCompare(b.id);\n}\n\nexport function summarize(findings: Finding[]): Record<Severity, number> {\n const summary: Record<Severity, number> = {\n critical: 0,\n high: 0,\n moderate: 0,\n low: 0,\n unknown: 0,\n };\n for (const f of findings) summary[f.severity]++;\n return summary;\n}\n\n/**\n * Returns true when any finding meets or exceeds the given severity threshold.\n * \"none\" means never fail.\n */\nexport function meetsThreshold(\n findings: Finding[],\n threshold: Severity | \"none\",\n): boolean {\n if (threshold === \"none\") return false;\n const min = SEVERITY_RANK[threshold];\n return findings.some((f) => SEVERITY_RANK[f.severity] >= min);\n}\n","import { readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { PackageInstance } from \"../types.js\";\n\ninterface NpmLockEntry {\n version?: string;\n resolved?: string;\n integrity?: string;\n dev?: boolean;\n devOptional?: boolean;\n optional?: boolean;\n peer?: boolean;\n link?: boolean;\n // Present on the root (\"\") entry only.\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n optionalDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n}\n\ninterface NpmLockfile {\n name?: string;\n lockfileVersion?: number;\n packages?: Record<string, NpmLockEntry>;\n}\n\n/**\n * Parse an npm `package-lock.json` (v2 or v3) and return one\n * PackageInstance per node in the `packages` map.\n *\n * The empty-string key represents the root project and is skipped.\n */\nexport function parseNpmPackageLock(filePath: string): PackageInstance[] {\n const absolute = resolve(filePath);\n const raw = readFileSync(absolute, \"utf8\");\n let parsed: NpmLockfile;\n try {\n parsed = JSON.parse(raw) as NpmLockfile;\n } catch (err) {\n throw new Error(\n `Failed to parse ${absolute}: ${(err as Error).message}`,\n );\n }\n\n if (parsed.lockfileVersion !== 2 && parsed.lockfileVersion !== 3) {\n throw new Error(\n `Unsupported npm lockfileVersion ${String(\n parsed.lockfileVersion,\n )} in ${absolute}. Only v2 and v3 are supported.`,\n );\n }\n\n const packages = parsed.packages;\n if (!packages || typeof packages !== \"object\") {\n throw new Error(\n `Lockfile ${absolute} has no \"packages\" map; cannot extract installed versions.`,\n );\n }\n\n const directDeps = collectDirectDependencyNames(packages[\"\"] ?? {});\n const instances: PackageInstance[] = [];\n\n for (const [path, entry] of Object.entries(packages)) {\n if (path === \"\") continue;\n if (entry.link) continue; // workspace symlink, not a real install\n const name = packagePathToName(path);\n if (!name) continue;\n if (!entry.version) continue;\n\n instances.push({\n name,\n version: entry.version,\n ecosystem: \"npm\",\n path,\n direct: directDeps.has(name) && isTopLevelInstance(path),\n dev: Boolean(entry.dev || entry.devOptional),\n optional: Boolean(entry.optional || entry.devOptional),\n resolved: entry.resolved,\n integrity: entry.integrity,\n });\n }\n\n return instances;\n}\n\nfunction collectDirectDependencyNames(rootEntry: NpmLockEntry): Set<string> {\n const names = new Set<string>();\n for (const key of [\n \"dependencies\",\n \"devDependencies\",\n \"optionalDependencies\",\n \"peerDependencies\",\n ] as const) {\n const block = rootEntry[key];\n if (!block) continue;\n for (const name of Object.keys(block)) names.add(name);\n }\n return names;\n}\n\n/**\n * \"node_modules/foo\" -> \"foo\"\n * \"node_modules/@scope/bar\" -> \"@scope/bar\"\n * \"node_modules/foo/node_modules/bar\" -> \"bar\"\n */\nexport function packagePathToName(path: string): string | null {\n const marker = \"node_modules/\";\n const idx = path.lastIndexOf(marker);\n if (idx === -1) return null;\n const tail = path.slice(idx + marker.length);\n if (!tail) return null;\n if (tail.startsWith(\"@\")) {\n const firstSlash = tail.indexOf(\"/\");\n if (firstSlash === -1) return null;\n const secondSlash = tail.indexOf(\"/\", firstSlash + 1);\n return secondSlash === -1 ? tail : tail.slice(0, secondSlash);\n }\n const next = tail.indexOf(\"/\");\n return next === -1 ? tail : tail.slice(0, next);\n}\n\n/** A direct-install path has exactly one `node_modules/` segment. */\nfunction isTopLevelInstance(path: string): boolean {\n const first = path.indexOf(\"node_modules/\");\n if (first === -1) return false;\n return path.indexOf(\"node_modules/\", first + 1) === -1;\n}\n","import { readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport yaml from \"js-yaml\";\nimport type { PackageInstance } from \"../types.js\";\n\ninterface PnpmDepRef {\n specifier?: string;\n version?: string;\n}\n\ntype PnpmImporterDeps = Record<string, string | PnpmDepRef>;\n\ninterface PnpmImporter {\n dependencies?: PnpmImporterDeps;\n devDependencies?: PnpmImporterDeps;\n optionalDependencies?: PnpmImporterDeps;\n}\n\ninterface PnpmPackageEntry {\n resolution?: { integrity?: string; tarball?: string };\n name?: string;\n version?: string;\n dev?: boolean;\n optional?: boolean;\n}\n\ninterface PnpmLockfile {\n lockfileVersion?: number | string;\n importers?: Record<string, PnpmImporter>;\n packages?: Record<string, PnpmPackageEntry>;\n // v6 root-level deps when no importers section\n dependencies?: PnpmImporterDeps;\n devDependencies?: PnpmImporterDeps;\n optionalDependencies?: PnpmImporterDeps;\n}\n\nconst SUPPORTED_MAJOR_VERSIONS = new Set([6, 9]);\n\nexport function parsePnpmLock(filePath: string): PackageInstance[] {\n const absolute = resolve(filePath);\n const raw = readFileSync(absolute, \"utf8\");\n let parsed: PnpmLockfile;\n try {\n parsed = (yaml.load(raw) ?? {}) as PnpmLockfile;\n } catch (err) {\n throw new Error(\n `Failed to parse ${absolute}: ${(err as Error).message}`,\n );\n }\n\n const versionRaw = parsed.lockfileVersion;\n const major = parseLockfileMajor(versionRaw);\n if (major === null || !SUPPORTED_MAJOR_VERSIONS.has(major)) {\n throw new Error(\n `Unsupported pnpm lockfileVersion ${String(versionRaw)} in ${absolute}. Supported: 6.x, 9.x.`,\n );\n }\n\n const packages = parsed.packages;\n if (!packages || typeof packages !== \"object\") {\n throw new Error(\n `Lockfile ${absolute} has no \"packages\" map; cannot extract installed versions.`,\n );\n }\n\n const importers = parsed.importers ?? {\n \".\": {\n dependencies: parsed.dependencies,\n devDependencies: parsed.devDependencies,\n optionalDependencies: parsed.optionalDependencies,\n },\n };\n\n const direct = collectDirectFromImporters(importers);\n const instances: PackageInstance[] = [];\n\n for (const [key, entry] of Object.entries(packages)) {\n const parsed = parsePnpmPackageKey(key);\n if (!parsed) continue;\n const name = entry.name ?? parsed.name;\n const version = entry.version ?? parsed.version;\n if (!name || !version) continue;\n\n const isDirect = direct.prod.has(name) || direct.dev.has(name) || direct.optional.has(name);\n const onlyDev = direct.dev.has(name) && !direct.prod.has(name);\n const onlyOptional =\n direct.optional.has(name) && !direct.prod.has(name) && !direct.dev.has(name);\n\n instances.push({\n name,\n version,\n ecosystem: \"npm\",\n path: key,\n direct: isDirect,\n dev: Boolean(entry.dev) || onlyDev,\n optional: Boolean(entry.optional) || onlyOptional,\n resolved: entry.resolution?.tarball,\n integrity: entry.resolution?.integrity,\n });\n }\n\n return instances;\n}\n\nfunction parseLockfileMajor(value: unknown): number | null {\n if (typeof value === \"number\") return Math.trunc(value);\n if (typeof value === \"string\") {\n const num = parseInt(value, 10);\n return Number.isNaN(num) ? null : num;\n }\n return null;\n}\n\ninterface DirectSets {\n prod: Set<string>;\n dev: Set<string>;\n optional: Set<string>;\n}\n\nfunction collectDirectFromImporters(\n importers: Record<string, PnpmImporter>,\n): DirectSets {\n const prod = new Set<string>();\n const dev = new Set<string>();\n const optional = new Set<string>();\n for (const importer of Object.values(importers)) {\n if (!importer) continue;\n addDepNames(importer.dependencies, prod);\n addDepNames(importer.devDependencies, dev);\n addDepNames(importer.optionalDependencies, optional);\n }\n return { prod, dev, optional };\n}\n\nfunction addDepNames(block: PnpmImporterDeps | undefined, into: Set<string>): void {\n if (!block) return;\n for (const name of Object.keys(block)) into.add(name);\n}\n\n/**\n * pnpm v9: \"lodash@4.17.21\", \"@scope/foo@1.2.3\", \"vitest@2.0.0(peer)\"\n * pnpm v6: \"/lodash@4.17.21\", \"/@scope/foo@1.2.3\", \"/vitest@2.0.0(peer)\"\n */\nexport function parsePnpmPackageKey(\n key: string,\n): { name: string; version: string } | null {\n let working = key.startsWith(\"/\") ? key.slice(1) : key;\n // Strip peer-deps suffix (everything from the first paren onward).\n const parenIdx = working.indexOf(\"(\");\n if (parenIdx !== -1) working = working.slice(0, parenIdx);\n\n // Find the @ separating name from version. For scoped names (@scope/foo@x.y.z)\n // we must skip the leading @.\n const startSearch = working.startsWith(\"@\") ? 1 : 0;\n const atIdx = working.indexOf(\"@\", startSearch);\n if (atIdx <= 0) return null;\n const name = working.slice(0, atIdx);\n const version = working.slice(atIdx + 1);\n if (!name || !version) return null;\n return { name, version };\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport yaml from \"js-yaml\";\nimport type { PackageInstance } from \"../types.js\";\n\ninterface YarnEntry {\n specs: string[];\n fields: Record<string, string>;\n}\n\ninterface BerryEntry {\n version?: string;\n resolution?: string;\n checksum?: string;\n // language and linker keys are ignored\n}\n\n/**\n * Parse a yarn lockfile (classic v1 or berry v2+) and return one\n * PackageInstance per resolved entry.\n *\n * Direct/dev flags are inferred by reading the sibling package.json,\n * since yarn lockfiles don't carry that information themselves.\n */\nexport function parseYarnLock(filePath: string): PackageInstance[] {\n const absolute = resolve(filePath);\n const content = readFileSync(absolute, \"utf8\");\n const projectDir = dirname(absolute);\n const directs = readDirectDepsFromPackageJson(projectDir);\n const isBerry = /^__metadata:/m.test(content);\n return isBerry\n ? parseBerry(absolute, content, directs)\n : parseClassic(absolute, content, directs);\n}\n\ninterface DirectSets {\n prod: Set<string>;\n dev: Set<string>;\n optional: Set<string>;\n any: Set<string>;\n}\n\nfunction readDirectDepsFromPackageJson(projectDir: string): DirectSets {\n const result: DirectSets = {\n prod: new Set(),\n dev: new Set(),\n optional: new Set(),\n any: new Set(),\n };\n const pkgPath = join(projectDir, \"package.json\");\n if (!existsSync(pkgPath)) return result;\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf8\")) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n optionalDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n };\n for (const name of Object.keys(pkg.dependencies ?? {})) result.prod.add(name);\n for (const name of Object.keys(pkg.devDependencies ?? {})) result.dev.add(name);\n for (const name of Object.keys(pkg.optionalDependencies ?? {}))\n result.optional.add(name);\n for (const set of [result.prod, result.dev, result.optional]) {\n for (const n of set) result.any.add(n);\n }\n for (const name of Object.keys(pkg.peerDependencies ?? {})) result.any.add(name);\n } catch {\n // malformed package.json: leave sets empty\n }\n return result;\n}\n\n// ---------- yarn classic v1 ----------\n\nfunction parseClassic(\n absolute: string,\n content: string,\n directs: DirectSets,\n): PackageInstance[] {\n const entries = parseClassicEntries(content);\n const instances: PackageInstance[] = [];\n for (const entry of entries) {\n const version = entry.fields.version;\n if (!version) continue;\n const names = uniq(entry.specs.map((s) => parseYarnSpec(s).name).filter(Boolean));\n const name = names[0];\n if (!name) continue;\n const isDirect = names.some((n) => directs.any.has(n));\n const inProd = names.some((n) => directs.prod.has(n));\n const inDev = names.some((n) => directs.dev.has(n));\n const inOpt = names.some((n) => directs.optional.has(n));\n instances.push({\n name,\n version,\n ecosystem: \"npm\",\n path: `${name}@${version}`,\n direct: isDirect,\n dev: inDev && !inProd,\n optional: inOpt && !inProd && !inDev,\n resolved: entry.fields.resolved,\n integrity: entry.fields.integrity,\n });\n }\n void absolute;\n return instances;\n}\n\nexport function parseClassicEntries(content: string): YarnEntry[] {\n const lines = content.split(/\\r?\\n/);\n const entries: YarnEntry[] = [];\n let current: YarnEntry | null = null;\n for (const rawLine of lines) {\n if (rawLine === \"\" || rawLine.trimStart().startsWith(\"#\")) continue;\n if (!/^\\s/.test(rawLine)) {\n // Header line ending with \":\"\n if (current) entries.push(current);\n const header = rawLine.replace(/:\\s*$/, \"\");\n current = { specs: splitClassicSpecs(header), fields: {} };\n continue;\n }\n if (!current) continue;\n // Top-level field for this entry has indent of exactly 2 spaces.\n const indent = rawLine.match(/^ +/)?.[0].length ?? 0;\n if (indent !== 2) continue;\n const trimmed = rawLine.trim();\n const m =\n trimmed.match(/^([^\\s\"]+)\\s+\"((?:[^\"\\\\]|\\\\.)*)\"$/) ??\n trimmed.match(/^([^\\s\"]+)\\s+(\\S+)$/);\n if (m && m[1] !== undefined && m[2] !== undefined) {\n current.fields[m[1]] = m[2];\n }\n }\n if (current) entries.push(current);\n return entries;\n}\n\nfunction splitClassicSpecs(header: string): string[] {\n const out: string[] = [];\n let cur = \"\";\n let inQuote = false;\n for (const ch of header) {\n if (ch === '\"') {\n inQuote = !inQuote;\n continue;\n }\n if (ch === \",\" && !inQuote) {\n const spec = cur.trim();\n if (spec) out.push(spec);\n cur = \"\";\n continue;\n }\n cur += ch;\n }\n const last = cur.trim();\n if (last) out.push(last);\n return out;\n}\n\n// ---------- yarn berry (v2+) ----------\n\nfunction parseBerry(\n absolute: string,\n content: string,\n directs: DirectSets,\n): PackageInstance[] {\n let parsed: Record<string, BerryEntry | unknown>;\n try {\n parsed = (yaml.load(content) ?? {}) as Record<string, BerryEntry | unknown>;\n } catch (err) {\n throw new Error(\n `Failed to parse ${absolute}: ${(err as Error).message}`,\n );\n }\n const instances: PackageInstance[] = [];\n for (const [key, value] of Object.entries(parsed)) {\n if (key === \"__metadata\") continue;\n if (!value || typeof value !== \"object\") continue;\n const entry = value as BerryEntry;\n if (!entry.version) continue;\n const specs = splitClassicSpecs(key);\n const names = uniq(specs.map((s) => parseYarnSpec(s).name).filter(Boolean));\n const name = names[0];\n if (!name) continue;\n const isDirect = names.some((n) => directs.any.has(n));\n const inProd = names.some((n) => directs.prod.has(n));\n const inDev = names.some((n) => directs.dev.has(n));\n const inOpt = names.some((n) => directs.optional.has(n));\n instances.push({\n name,\n version: entry.version,\n ecosystem: \"npm\",\n path: `${name}@${entry.version}`,\n direct: isDirect,\n dev: inDev && !inProd,\n optional: inOpt && !inProd && !inDev,\n resolved: entry.resolution,\n integrity: entry.checksum,\n });\n }\n return instances;\n}\n\n// ---------- shared ----------\n\n/**\n * \"lodash@^4.17.20\" -> { name: \"lodash\", selector: \"^4.17.20\" }\n * \"@scope/foo@^1.0.0\" -> { name: \"@scope/foo\", selector: \"^1.0.0\" }\n * Berry: \"lodash@npm:^4.17.20\" -> { name: \"lodash\", selector: \"^4.17.20\" }\n */\nexport function parseYarnSpec(spec: string): { name: string; selector: string } {\n const startSearch = spec.startsWith(\"@\") ? 1 : 0;\n const atIdx = spec.indexOf(\"@\", startSearch);\n if (atIdx <= 0) return { name: spec, selector: \"\" };\n const name = spec.slice(0, atIdx);\n let selector = spec.slice(atIdx + 1);\n if (selector.startsWith(\"npm:\")) selector = selector.slice(4);\n return { name, selector };\n}\n\nfunction uniq(values: string[]): string[] {\n return Array.from(new Set(values));\n}\n","export type Severity = \"critical\" | \"high\" | \"moderate\" | \"low\" | \"unknown\";\n\nexport type Ecosystem = \"npm\";\n\nexport type FindingType =\n | \"vulnerability\"\n | \"malware\"\n | \"risk-signal\"\n | \"integrity\";\n\nexport const SEVERITY_RANK: Record<Severity, number> = {\n critical: 4,\n high: 3,\n moderate: 2,\n low: 1,\n unknown: 0,\n};\n\nexport interface PackageInstance {\n name: string;\n version: string;\n ecosystem: Ecosystem;\n /** Path within the lockfile's `packages` map (e.g. \"node_modules/foo\"). */\n path: string;\n direct: boolean;\n dev: boolean;\n optional: boolean;\n resolved?: string;\n integrity?: string;\n}\n\nexport interface Finding {\n id: string;\n source: \"osv\";\n type: FindingType;\n severity: Severity;\n packageName: string;\n installedVersion: string;\n summary: string;\n url?: string;\n fixedVersions: string[];\n affectedPaths: string[];\n}\n\nexport interface ScanError {\n message: string;\n cause?: string;\n}\n\nexport interface ScanResult {\n scannedAt: string;\n packagesScanned: number;\n findings: Finding[];\n summary: Record<Severity, number>;\n errors: ScanError[];\n}\n\nexport interface ScanProjectOptions {\n cwd?: string;\n lockfile?: string;\n includeDev?: boolean;\n prodOnly?: boolean;\n cache?: boolean;\n fetchImpl?: typeof fetch;\n}\n\nexport interface ScanLockfileOptions {\n lockfilePath: string;\n includeDev?: boolean;\n prodOnly?: boolean;\n fetchImpl?: typeof fetch;\n}\n\nexport type FailOnLevel = Severity | \"none\";\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport type PackageManager = \"npm\" | \"pnpm\" | \"yarn\" | \"bun\";\n\nexport interface PmCommand {\n /** Binary to spawn, e.g. \"pnpm\". */\n bin: string;\n /** Argv to spawn it with. */\n args: string[];\n}\n\nexport interface DetectOptions {\n /** Override detection. */\n override?: PackageManager;\n /** Project directory. Defaults to cwd. */\n cwd?: string;\n}\n\nconst LOCKFILES: Array<{ file: string; pm: PackageManager }> = [\n { file: \"pnpm-lock.yaml\", pm: \"pnpm\" },\n { file: \"yarn.lock\", pm: \"yarn\" },\n { file: \"bun.lockb\", pm: \"bun\" },\n { file: \"bun.lock\", pm: \"bun\" },\n { file: \"package-lock.json\", pm: \"npm\" },\n { file: \"npm-shrinkwrap.json\", pm: \"npm\" },\n];\n\nexport function detectPackageManager(opts: DetectOptions = {}): PackageManager {\n if (opts.override) return opts.override;\n const cwd = opts.cwd ?? process.cwd();\n\n const fromField = readPackageManagerField(cwd);\n if (fromField) return fromField;\n\n for (const { file, pm } of LOCKFILES) {\n if (existsSync(join(cwd, file))) return pm;\n }\n return \"npm\";\n}\n\nfunction readPackageManagerField(cwd: string): PackageManager | undefined {\n const pkgPath = join(cwd, \"package.json\");\n if (!existsSync(pkgPath)) return undefined;\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf8\")) as {\n packageManager?: string;\n };\n if (typeof pkg.packageManager !== \"string\") return undefined;\n const name = pkg.packageManager.split(\"@\")[0];\n if (name === \"npm\" || name === \"pnpm\" || name === \"yarn\" || name === \"bun\") {\n return name;\n }\n } catch {\n // Malformed package.json : fall back to lockfile detection.\n }\n return undefined;\n}\n\n/**\n * Build the argv to add packages with the chosen package manager.\n * `flags` are user-supplied PM flags (e.g. -D, --save-exact) preserved as-is.\n */\nexport function buildAddCommand(\n pm: PackageManager,\n packages: string[],\n flags: string[],\n): PmCommand {\n switch (pm) {\n case \"npm\":\n return { bin: \"npm\", args: [\"install\", ...flags, ...packages] };\n case \"pnpm\":\n return { bin: \"pnpm\", args: [\"add\", ...flags, ...packages] };\n case \"yarn\":\n return { bin: \"yarn\", args: [\"add\", ...flags, ...packages] };\n case \"bun\":\n return { bin: \"bun\", args: [\"add\", ...flags, ...packages] };\n }\n}\n\nexport function buildInstallCommand(\n pm: PackageManager,\n flags: string[],\n): PmCommand {\n return { bin: pm, args: [\"install\", ...flags] };\n}\n\nexport function buildRemoveCommand(\n pm: PackageManager,\n packages: string[],\n flags: string[],\n): PmCommand {\n switch (pm) {\n case \"npm\":\n return { bin: \"npm\", args: [\"uninstall\", ...flags, ...packages] };\n case \"pnpm\":\n return { bin: \"pnpm\", args: [\"remove\", ...flags, ...packages] };\n case \"yarn\":\n return { bin: \"yarn\", args: [\"remove\", ...flags, ...packages] };\n case \"bun\":\n return { bin: \"bun\", args: [\"remove\", ...flags, ...packages] };\n }\n}\n","import { spawn } from \"node:child_process\";\nimport type { PmCommand } from \"./pm-detect.js\";\n\nexport interface RunOptions {\n cwd?: string;\n}\n\n/**\n * Spawn the package manager with stdio inherited so the user sees the live\n * install output. Resolves with the PM's exit code.\n */\nexport function runPackageManager(\n cmd: PmCommand,\n opts: RunOptions = {},\n): Promise<number> {\n return new Promise((resolve, reject) => {\n const child = spawn(cmd.bin, cmd.args, {\n cwd: opts.cwd,\n stdio: \"inherit\",\n shell: process.platform === \"win32\",\n });\n child.on(\"error\", reject);\n child.on(\"close\", (code) => resolve(code ?? 0));\n });\n}\n","export interface ParsedSpec {\n /** Original argv token, preserved so we can hand it back to the package manager. */\n raw: string;\n /** Bare package name, e.g. \"next\" or \"@types/node\". */\n name: string;\n /**\n * Whatever followed the \"@\" separator: an exact version, a semver range,\n * or a dist-tag like \"latest\" / \"next\". Undefined when the user passed only\n * the package name.\n */\n requested?: string;\n /** Specs we cannot meaningfully scan (git, tarball, file, url, alias). */\n unsupported?: UnsupportedReason;\n}\n\nexport type UnsupportedReason =\n | \"git\"\n | \"url\"\n | \"file\"\n | \"alias\"\n | \"workspace\"\n | \"invalid\";\n\nconst URL_PROTOCOLS = [\"http:\", \"https:\", \"git:\", \"git+ssh:\", \"git+https:\", \"git+http:\"];\n\nexport function parseSpec(raw: string): ParsedSpec {\n const trimmed = raw.trim();\n if (trimmed === \"\") {\n return { raw, name: \"\", unsupported: \"invalid\" };\n }\n\n if (trimmed.startsWith(\"file:\")) return { raw, name: trimmed, unsupported: \"file\" };\n if (trimmed.startsWith(\"workspace:\")) {\n return { raw, name: trimmed, unsupported: \"workspace\" };\n }\n if (URL_PROTOCOLS.some((p) => trimmed.startsWith(p))) {\n const reason = trimmed.includes(\"git\") ? \"git\" : \"url\";\n return { raw, name: trimmed, unsupported: reason };\n }\n // npm aliases: \"alias@npm:real-pkg@1.0\". We can't reliably gate these in v1.\n if (/^[^@/].*@npm:/.test(trimmed) || /^@[^/]+\\/[^@]+@npm:/.test(trimmed)) {\n return { raw, name: trimmed, unsupported: \"alias\" };\n }\n\n // Scoped: \"@scope/name\" or \"@scope/name@version\".\n if (trimmed.startsWith(\"@\")) {\n const slash = trimmed.indexOf(\"/\");\n if (slash === -1) return { raw, name: trimmed, unsupported: \"invalid\" };\n const rest = trimmed.slice(slash + 1);\n const at = rest.indexOf(\"@\");\n if (at === -1) {\n return { raw, name: trimmed };\n }\n const subname = rest.slice(0, at);\n const requested = rest.slice(at + 1);\n if (subname === \"\" || requested === \"\") {\n return { raw, name: trimmed, unsupported: \"invalid\" };\n }\n return { raw, name: `${trimmed.slice(0, slash)}/${subname}`, requested };\n }\n\n const at = trimmed.indexOf(\"@\");\n if (at === -1) return { raw, name: trimmed };\n const name = trimmed.slice(0, at);\n const requested = trimmed.slice(at + 1);\n if (name === \"\" || requested === \"\") {\n return { raw, name: trimmed, unsupported: \"invalid\" };\n }\n return { raw, name, requested };\n}\n\n/**\n * Splits an argv list into recognized package specs and forwarded flags.\n * Anything starting with \"-\" is treated as a flag and preserved untouched.\n */\nexport function partitionArgs(args: string[]): {\n specs: ParsedSpec[];\n flags: string[];\n} {\n const specs: ParsedSpec[] = [];\n const flags: string[] = [];\n for (const arg of args) {\n if (arg.startsWith(\"-\")) {\n flags.push(arg);\n continue;\n }\n specs.push(parseSpec(arg));\n }\n return { specs, flags };\n}\n","const REGISTRY_URL = \"https://registry.npmjs.org\";\nconst REQUEST_TIMEOUT_MS = 15_000;\n\nexport interface ResolveDeps {\n fetchImpl?: typeof fetch;\n registryUrl?: string;\n}\n\nexport interface ResolvedVersion {\n /** Concrete version we'll hand to OSV. */\n version: string;\n /**\n * How we picked it: \"exact\" (user pinned), \"dist-tag\" (latest/next/etc),\n * or \"fallback-latest\" (we couldn't resolve a range so we scanned latest).\n */\n source: \"exact\" | \"dist-tag\" | \"fallback-latest\";\n /** Set when source !== \"exact\" : what the user asked for. */\n requested?: string;\n}\n\ninterface PackumentDistTags {\n latest?: string;\n [tag: string]: string | undefined;\n}\n\ninterface Packument {\n name?: string;\n \"dist-tags\"?: PackumentDistTags;\n versions?: Record<string, unknown>;\n}\n\nconst EXACT_VERSION_RE = /^\\d+\\.\\d+\\.\\d+(?:[-+][\\w.+-]+)?$/;\nconst RANGE_CHARS_RE = /[\\^~><=|\\s*x]/i;\n\n/**\n * Resolve a user-supplied spec to a concrete version we can query OSV with.\n *\n * Strategy (v1):\n * - no version requested → dist-tags.latest\n * - exact version (1.2.3) → use as-is, verified to exist\n * - dist-tag (latest/next/beta) → dist-tags[tag], or fall back to latest\n * - semver range (^1, >=2) → dist-tags.latest with source=\"fallback-latest\"\n *\n * The fallback case is a known limitation: the installed version may differ\n * from what we scanned. The orchestrator surfaces this in its report.\n */\nexport async function resolveVersion(\n name: string,\n requested: string | undefined,\n deps: ResolveDeps = {},\n): Promise<ResolvedVersion> {\n const fetchImpl = deps.fetchImpl ?? fetch;\n const registry = deps.registryUrl ?? REGISTRY_URL;\n const packument = await fetchPackument(fetchImpl, registry, name);\n\n const distTags = packument[\"dist-tags\"] ?? {};\n const latest = distTags.latest;\n\n if (!requested) {\n if (!latest) {\n throw new VersionResolveError(\n `Package ${name} has no \"latest\" dist-tag in the registry.`,\n );\n }\n return { version: latest, source: \"dist-tag\", requested: \"latest\" };\n }\n\n if (EXACT_VERSION_RE.test(requested)) {\n if (packument.versions && !packument.versions[requested]) {\n throw new VersionResolveError(\n `Version ${requested} of ${name} is not published.`,\n );\n }\n return { version: requested, source: \"exact\" };\n }\n\n if (!RANGE_CHARS_RE.test(requested) && distTags[requested]) {\n return {\n version: distTags[requested] as string,\n source: \"dist-tag\",\n requested,\n };\n }\n\n if (!latest) {\n throw new VersionResolveError(\n `Cannot resolve ${name}@${requested}: no \"latest\" dist-tag available to fall back on.`,\n );\n }\n return { version: latest, source: \"fallback-latest\", requested };\n}\n\nexport class VersionResolveError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"VersionResolveError\";\n }\n}\n\nasync function fetchPackument(\n fetchImpl: typeof fetch,\n registry: string,\n name: string,\n): Promise<Packument> {\n const url = `${registry.replace(/\\/$/, \"\")}/${encodePackageName(name)}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n try {\n const res = await fetchImpl(url, {\n signal: controller.signal,\n headers: { accept: \"application/json\" },\n });\n if (res.status === 404) {\n throw new VersionResolveError(`Package ${name} not found in registry.`);\n }\n if (!res.ok) {\n throw new VersionResolveError(\n `Registry ${res.status} for ${name}: ${res.statusText}`,\n );\n }\n return (await res.json()) as Packument;\n } finally {\n clearTimeout(timer);\n }\n}\n\nfunction encodePackageName(name: string): string {\n // Scoped names: \"@scope/name\" → \"@scope%2Fname\"\n if (name.startsWith(\"@\")) {\n const slash = name.indexOf(\"/\");\n if (slash !== -1) {\n return `${encodeURIComponent(name.slice(0, slash))}%2F${encodeURIComponent(name.slice(slash + 1))}`;\n }\n }\n return encodeURIComponent(name);\n}\n","import type { ScanResult } from \"../types.js\";\n\nexport function reportJson(result: ScanResult): string {\n return JSON.stringify(result, null, 2);\n}\n","import kleur from \"kleur\";\nimport {\n type Finding,\n type ScanResult,\n type Severity,\n SEVERITY_RANK,\n} from \"../types.js\";\nimport { renderBanner } from \"./banner.js\";\n\nexport type TableView = \"grouped\" | \"details\" | \"summary\";\n\nexport interface ReportTableOptions {\n /** @deprecated use `view` instead */\n details?: boolean;\n view?: TableView;\n /**\n * When true, renders a boxed `trawly` nameplate at the top in place of the\n * plain `trawly: …` header. CLI sets this only when stdout is a TTY so that\n * piped/CI output stays log-parser friendly.\n */\n brand?: boolean;\n}\n\nconst SEVERITY_COLOR: Record<Severity, (s: string) => string> = {\n critical: (s) => kleur.bold().red(s),\n high: (s) => kleur.red(s),\n moderate: (s) => kleur.yellow(s),\n low: (s) => kleur.cyan(s),\n unknown: (s) => kleur.gray(s),\n};\n\nconst SEVERITY_ORDER: Severity[] = [\n \"critical\",\n \"high\",\n \"moderate\",\n \"low\",\n \"unknown\",\n];\n\ninterface PackageGroup {\n packageName: string;\n installedVersion: string;\n topSeverity: Severity;\n counts: Record<Severity, number>;\n findings: Finding[];\n recommendedFix: string | null;\n}\n\nexport function reportTable(\n result: ScanResult,\n options: ReportTableOptions = {},\n): string {\n const view: TableView = options.view ?? (options.details ? \"details\" : \"grouped\");\n const lines: string[] = [];\n\n if (options.brand) {\n const { metricsLine, timestamp } = headerParts(result);\n lines.push(renderBanner({ metrics: metricsLine, timestamp }));\n } else {\n lines.push(kleur.bold(formatHeader(result)));\n }\n\n if (result.errors.length > 0) {\n for (const err of result.errors) {\n lines.push(\n kleur.red(`! ${err.message}${err.cause ? ` (${err.cause})` : \"\"}`),\n );\n }\n }\n\n if (result.findings.length === 0) {\n lines.push(kleur.green(\"✓ No known advisories found.\"));\n lines.push(\n kleur.gray(\n \" Note: this only checks known advisories. It cannot prove a package is safe.\",\n ),\n );\n return lines.join(\"\\n\");\n }\n\n if (view === \"summary\") {\n lines.push(formatSummary(result.summary));\n lines.push(reminder());\n return lines.join(\"\\n\");\n }\n\n lines.push(\"\");\n lines.push(formatSummary(result.summary));\n lines.push(\"\");\n\n if (view === \"details\") {\n lines.push(formatDetailRows(sortFindings(result.findings)));\n } else {\n const groups = groupByPackage(result.findings);\n lines.push(formatGroupedRows(groups));\n lines.push(\"\");\n lines.push(\n kleur.gray(\"Run `trawly scan --details` to see individual advisories.\"),\n );\n }\n\n lines.push(\"\");\n lines.push(reminder());\n return lines.join(\"\\n\");\n}\n\nfunction formatHeader(result: ScanResult): string {\n const { metricsLine, timestamp } = headerParts(result);\n return `trawly: ${metricsLine} (${timestamp})`;\n}\n\nfunction headerParts(result: ScanResult): {\n metricsLine: string;\n timestamp: string;\n} {\n const vulnerable = new Set(\n result.findings.map((f) => `${f.packageName}@${f.installedVersion}`),\n ).size;\n const advisories = result.findings.length;\n const metricsLine = [\n `${result.packagesScanned} packages`,\n `${vulnerable} vulnerable`,\n `${advisories} ${advisories === 1 ? \"advisory\" : \"advisories\"}`,\n ].join(\" · \");\n return { metricsLine, timestamp: result.scannedAt };\n}\n\nfunction formatSummary(summary: ScanResult[\"summary\"]): string {\n const parts: string[] = [];\n for (const sev of SEVERITY_ORDER) {\n const count = summary[sev];\n if (count === 0) continue;\n parts.push(SEVERITY_COLOR[sev](`${sev}: ${count}`));\n }\n if (parts.length === 0) return kleur.green(\"No findings.\");\n return `Findings : ${parts.join(\" \")}`;\n}\n\nfunction reminder(): string {\n return kleur.gray(\n \"Reminder: trawly reports known advisories only. Absence of findings is not proof of safety.\",\n );\n}\n\nfunction sortFindings(findings: Finding[]): Finding[] {\n return [...findings].sort((a, b) => {\n const sev = SEVERITY_RANK[b.severity] - SEVERITY_RANK[a.severity];\n if (sev !== 0) return sev;\n const name = a.packageName.localeCompare(b.packageName);\n if (name !== 0) return name;\n return a.id.localeCompare(b.id);\n });\n}\n\nfunction groupByPackage(findings: Finding[]): PackageGroup[] {\n const map = new Map<string, PackageGroup>();\n for (const f of findings) {\n const key = `${f.packageName}@${f.installedVersion}`;\n let group = map.get(key);\n if (!group) {\n group = {\n packageName: f.packageName,\n installedVersion: f.installedVersion,\n topSeverity: f.severity,\n counts: { critical: 0, high: 0, moderate: 0, low: 0, unknown: 0 },\n findings: [],\n recommendedFix: null,\n };\n map.set(key, group);\n }\n group.findings.push(f);\n group.counts[f.severity] += 1;\n if (SEVERITY_RANK[f.severity] > SEVERITY_RANK[group.topSeverity]) {\n group.topSeverity = f.severity;\n }\n }\n\n for (const group of map.values()) {\n group.recommendedFix = pickRecommendedFix(group.findings);\n }\n\n return [...map.values()].sort((a, b) => {\n const sev = SEVERITY_RANK[b.topSeverity] - SEVERITY_RANK[a.topSeverity];\n if (sev !== 0) return sev;\n const totalA = a.findings.length;\n const totalB = b.findings.length;\n if (totalA !== totalB) return totalB - totalA;\n return a.packageName.localeCompare(b.packageName);\n });\n}\n\nfunction formatGroupedRows(groups: PackageGroup[]): string {\n const rows: string[][] = [\n [\"PACKAGE\", \"VERSION\", \"SEVERITY\", \"FIX\"],\n ];\n for (const g of groups) {\n rows.push([\n g.packageName,\n g.installedVersion,\n formatSeverityCounts(g.counts),\n g.recommendedFix ? `>=${g.recommendedFix}` : \":\",\n ]);\n }\n return renderTable(rows, (rowIdx, _row, cells) => {\n if (rowIdx === 0) return kleur.bold().underline(cells.join(\" \"));\n return cells.join(\" \");\n });\n}\n\nfunction formatDetailRows(findings: Finding[]): string {\n const rows: string[][] = [\n [\"SEV\", \"PACKAGE\", \"VERSION\", \"ID\", \"FIXED IN\", \"SUMMARY\"],\n ];\n for (const f of findings) {\n rows.push([\n f.severity,\n f.packageName,\n f.installedVersion,\n f.id,\n f.fixedVersions.length ? f.fixedVersions.join(\", \") : \":\",\n truncate(f.summary, 70),\n ]);\n }\n return renderTable(rows, (rowIdx, row, cells) => {\n if (rowIdx === 0) return kleur.bold().underline(cells.join(\" \"));\n const sev = row[0] as Severity;\n const colorize = SEVERITY_COLOR[sev] ?? ((s: string) => s);\n cells[0] = colorize(cells[0]!);\n return cells.join(\" \");\n });\n}\n\nfunction formatSeverityCounts(counts: Record<Severity, number>): string {\n const parts: string[] = [];\n for (const sev of SEVERITY_ORDER) {\n const n = counts[sev];\n if (n === 0) continue;\n parts.push(SEVERITY_COLOR[sev](`${n} ${sev}`));\n }\n return parts.join(\", \");\n}\n\nfunction renderTable(\n rows: string[][],\n format: (rowIdx: number, row: string[], cells: string[]) => string,\n): string {\n const widths = rows[0]!.map((_, col) =>\n Math.max(...rows.map((r) => visibleLength(r[col]!))),\n );\n return rows\n .map((row, i) => {\n const cells = row.map((cell, col) => padEndVisible(cell, widths[col]!));\n return format(i, row, cells);\n })\n .join(\"\\n\");\n}\n\n/**\n * Pick the highest semver-ish value across all fixedVersions in the group.\n * Picking the max guarantees the upgrade clears every known advisory; users\n * can drop into `--details` if they want to evaluate alternative fix lines\n * (e.g. staying on a previous major).\n */\nfunction pickRecommendedFix(findings: Finding[]): string | null {\n const candidates: string[] = [];\n for (const f of findings) {\n for (const v of f.fixedVersions) candidates.push(v);\n }\n if (candidates.length === 0) return null;\n const unique = [...new Set(candidates)];\n unique.sort(compareSemver);\n return unique[unique.length - 1] ?? null;\n}\n\nfunction compareSemver(a: string, b: string): number {\n const pa = parseSemverParts(a);\n const pb = parseSemverParts(b);\n for (let i = 0; i < 3; i++) {\n const diff = (pa[i] ?? 0) - (pb[i] ?? 0);\n if (diff !== 0) return diff;\n }\n return a.localeCompare(b);\n}\n\nfunction parseSemverParts(v: string): number[] {\n const m = v.match(/(\\d+)\\.(\\d+)\\.(\\d+)/);\n if (!m) return [0, 0, 0];\n return [Number(m[1]), Number(m[2]), Number(m[3])];\n}\n\nfunction truncate(s: string, max: number): string {\n if (s.length <= max) return s;\n return `${s.slice(0, max - 1)}…`;\n}\n\n// kleur wraps strings in ANSI escape codes; padEnd needs the visible width.\nconst ANSI_RE = /\\u001B\\[[0-9;]*m/g;\nfunction visibleLength(s: string): number {\n return s.replace(ANSI_RE, \"\").length;\n}\nfunction padEndVisible(s: string, width: number): string {\n const pad = Math.max(0, width - visibleLength(s));\n return s + \" \".repeat(pad);\n}\n","import kleur from \"kleur\";\n\nexport interface BannerProps {\n /** First content row, e.g. \"164 packages · 2 vulnerable · 2 advisories\". */\n metrics: string;\n /** Second content row, typically a scannedAt ISO timestamp. */\n timestamp: string;\n}\n\nconst BORDER = {\n tl: \"┌\",\n tr: \"┐\",\n bl: \"└\",\n br: \"┘\",\n h: \"─\",\n v: \"│\",\n} as const;\n\nconst TITLE = \"trawly\";\nconst SIDE_PAD = 1; // single space between │ and content\nconst MIN_TITLE_FILLER = 4; // ensure at least \"────\" after `─ trawly `\n\nexport function renderBanner(props: BannerProps): string {\n const contentRows = [props.metrics, props.timestamp];\n const titleSegment = ` ${TITLE} `; // \" trawly \"\n const minTitleWidth = 1 + titleSegment.length + MIN_TITLE_FILLER; // ─ + \" trawly \" + ────\n\n const innerWidth = Math.max(\n ...contentRows.map((r) => r.length + SIDE_PAD * 2),\n minTitleWidth,\n );\n\n const top = renderTop(innerWidth);\n const bottom = renderBottom(innerWidth);\n const metricsLine = renderRow(innerWidth, props.metrics, kleur.bold);\n const timestampLine = renderRow(innerWidth, props.timestamp, kleur.gray);\n\n return [top, metricsLine, timestampLine, bottom].join(\"\\n\");\n}\n\nfunction renderTop(innerWidth: number): string {\n const titleSegment = ` ${kleur.bold().cyan(TITLE)} `;\n const titleVisibleLen = TITLE.length + 2; // bold/cyan don't add visible chars\n const fillerCount = innerWidth - 1 - titleVisibleLen; // -1 for the leading \"─\"\n return (\n kleur.gray(BORDER.tl) +\n kleur.gray(BORDER.h) +\n titleSegment +\n kleur.gray(BORDER.h.repeat(Math.max(MIN_TITLE_FILLER, fillerCount))) +\n kleur.gray(BORDER.tr)\n );\n}\n\nfunction renderBottom(innerWidth: number): string {\n return kleur.gray(`${BORDER.bl}${BORDER.h.repeat(innerWidth)}${BORDER.br}`);\n}\n\nfunction renderRow(\n innerWidth: number,\n content: string,\n colorize: (s: string) => string,\n): string {\n const fill = Math.max(0, innerWidth - SIDE_PAD * 2 - content.length);\n return (\n kleur.gray(BORDER.v) +\n \" \".repeat(SIDE_PAD) +\n colorize(content) +\n \" \".repeat(fill + SIDE_PAD) +\n kleur.gray(BORDER.v)\n );\n}\n"],"mappings":"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","names":["kleur","existsSync","resolve","join","readFileSync","resolve","parsed","readFileSync","resolve","yaml","resolve","existsSync","join","existsSync","readFileSync","join","resolve","at","requested","REQUEST_TIMEOUT_MS","kleur","kleur","kleur","truncate","kleur"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/commands/add.ts","../src/fingerprint.ts","../src/sources/osv.ts","../src/scanner.ts","../src/baseline.ts","../src/config.ts","../src/env.ts","../src/extractors/lockfile.ts","../src/extractors/npm-package-lock.ts","../src/extractors/pnpm-lock.ts","../src/extractors/package-json.ts","../src/extractors/yarn-lock.ts","../src/extractors/sbom.ts","../src/ignore.ts","../src/policy.ts","../src/risk.ts","../src/types.ts","../src/installer/pm-detect.ts","../src/installer/runner.ts","../src/installer/spec-parser.ts","../src/installer/version-resolver.ts","../src/env-scan.ts","../src/init.ts","../src/reporters/env-table.ts","../src/reporters/banner.ts","../src/reporters/json.ts","../src/reporters/markdown.ts","../src/version.ts","../src/reporters/sarif.ts","../src/reporters/table.ts","../src/why.ts"],"sourcesContent":["import { mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { Command, InvalidArgumentError } from \"commander\";\nimport kleur from \"kleur\";\nimport { reportAdd, runAdd } from \"./commands/add.js\";\nimport { ConfigError, loadConfig } from \"./config.js\";\nimport { envIssuesMeetThreshold, scanEnv } from \"./env-scan.js\";\nimport { initProject } from \"./init.js\";\nimport {\n buildInstallCommand,\n buildRemoveCommand,\n detectPackageManager,\n type PackageManager,\n} from \"./installer/pm-detect.js\";\nimport { runPackageManager } from \"./installer/runner.js\";\nimport { reportEnvJson, reportEnvTable } from \"./reporters/env-table.js\";\nimport { reportJson } from \"./reporters/json.js\";\nimport { reportMarkdown } from \"./reporters/markdown.js\";\nimport { reportSarif } from \"./reporters/sarif.js\";\nimport { reportTable } from \"./reporters/table.js\";\nimport { resolvePolicy } from \"./policy.js\";\nimport { meetsThreshold, ScanInputError, scanProject } from \"./scanner.js\";\nimport type { FailOnLevel, PolicyPresetName } from \"./types.js\";\nimport { TRAWLY_VERSION } from \"./version.js\";\nimport { explainWhy } from \"./why.js\";\n\nconst FAIL_ON_VALUES: FailOnLevel[] = [\n \"critical\",\n \"high\",\n \"moderate\",\n \"low\",\n \"none\",\n];\nconst FORMAT_VALUES = [\"table\", \"json\", \"markdown\", \"sarif\"] as const;\ntype Format = (typeof FORMAT_VALUES)[number];\nconst ENV_FORMAT_VALUES = [\"table\", \"json\"] as const;\ntype EnvFormat = (typeof ENV_FORMAT_VALUES)[number];\nconst POLICY_VALUES: PolicyPresetName[] = [\"ci\", \"strict\", \"library\", \"app\"];\n\nconst PM_VALUES: PackageManager[] = [\"npm\", \"pnpm\", \"yarn\", \"bun\"];\n\nconst EXIT = {\n ok: 0,\n findings: 1,\n operational: 2,\n invalidInput: 3,\n} as const;\n\nfunction parseFailOn(value: string): FailOnLevel {\n if (!FAIL_ON_VALUES.includes(value as FailOnLevel)) {\n throw new InvalidArgumentError(\n `must be one of: ${FAIL_ON_VALUES.join(\", \")}`,\n );\n }\n return value as FailOnLevel;\n}\n\nfunction parseFormat(value: string): Format {\n if (!FORMAT_VALUES.includes(value as Format)) {\n throw new InvalidArgumentError(\n `must be one of: ${FORMAT_VALUES.join(\", \")}`,\n );\n }\n return value as Format;\n}\n\nfunction parseEnvFormat(value: string): EnvFormat {\n if (!ENV_FORMAT_VALUES.includes(value as EnvFormat)) {\n throw new InvalidArgumentError(\n `must be one of: ${ENV_FORMAT_VALUES.join(\", \")}`,\n );\n }\n return value as EnvFormat;\n}\n\nfunction parsePolicy(value: string): PolicyPresetName {\n if (!POLICY_VALUES.includes(value as PolicyPresetName)) {\n throw new InvalidArgumentError(\n `must be one of: ${POLICY_VALUES.join(\", \")}`,\n );\n }\n return value as PolicyPresetName;\n}\n\nfunction parsePm(value: string): PackageManager {\n if (!PM_VALUES.includes(value as PackageManager)) {\n throw new InvalidArgumentError(`must be one of: ${PM_VALUES.join(\", \")}`);\n }\n return value as PackageManager;\n}\n\nfunction collectOption(value: string, previous: string[] = []): string[] {\n previous.push(value);\n return previous;\n}\n\nconst program = new Command();\n\nprogram\n .name(\"trawly\")\n .description(\n \"Dependency sanity scanner. Checks installed npm packages against the OSV advisory database.\",\n )\n .version(TRAWLY_VERSION)\n .enablePositionalOptions()\n .exitOverride((err) => {\n if (err.code === \"commander.helpDisplayed\" || err.code === \"commander.help\") {\n process.exit(EXIT.ok);\n }\n if (err.code === \"commander.version\") process.exit(EXIT.ok);\n process.exit(EXIT.invalidInput);\n });\n\nprogram\n .command(\"scan\", { isDefault: true })\n .description(\n \"Scan a project and gate on findings. Exits non-zero when --fail-on is met. Use `inspect` for a log-only run.\",\n )\n .argument(\"[path]\", \"Project directory to scan\", \".\")\n .option(\n \"--lockfile <path>\",\n \"Explicit lockfile path. May be repeated.\",\n collectOption,\n )\n .option(\"--sbom <path>\", \"Explicit SPDX/CycloneDX SBOM path. May be repeated.\", collectOption)\n .option(\n \"--format <format>\",\n \"Output format: table | json | markdown | sarif\",\n parseFormat,\n \"table\" as Format,\n )\n .option(\n \"--fail-on <level>\",\n `Exit non-zero when a finding meets this severity (${FAIL_ON_VALUES.join(\"|\")})`,\n parseFailOn,\n )\n .option(\"--config <path>\", \"Path to trawly.toml\")\n .option(\n \"--policy <name>\",\n `Use a built-in policy preset (${POLICY_VALUES.join(\"|\")})`,\n parsePolicy,\n )\n .option(\"--baseline <path>\", \"Only fail on findings not present in this baseline\")\n .option(\"--write-baseline <path>\", \"Write the current active findings baseline\")\n .option(\"--output <path>\", \"Write report output to a file\")\n .option(\"--risk\", \"Enable risk signals\")\n .option(\"--no-risk\", \"Disable risk signals\")\n .option(\"--env\", \"Scan committed .env files for secret-like values\")\n .option(\"--no-env\", \"Disable committed .env file scanning\")\n .option(\"--prod\", \"Only scan production dependencies (excludes dev)\")\n .option(\"--include-dev\", \"Include dev dependencies (default)\")\n .option(\n \"-v, --details\",\n \"Show one row per advisory (full table). Default groups by package.\",\n )\n .option(\n \"-q, --summary\",\n \"Show only the one-line severity summary. Mutually exclusive with --details.\",\n )\n .action(async (path: string, opts: ScanCliOptions, command: Command) => {\n await runScanCommand(path, normalizeScanOptions(opts, command), {\n gate: true,\n });\n });\n\nprogram\n .command(\"inspect\")\n .description(\n \"Scan a project and print findings without gating. Always exits 0 unless an operational error occurs. Use `scan` for CI gating.\",\n )\n .argument(\"[path]\", \"Project directory to scan\", \".\")\n .option(\n \"--lockfile <path>\",\n \"Explicit lockfile path. May be repeated.\",\n collectOption,\n )\n .option(\"--sbom <path>\", \"Explicit SPDX/CycloneDX SBOM path. May be repeated.\", collectOption)\n .option(\n \"--format <format>\",\n \"Output format: table | json | markdown | sarif\",\n parseFormat,\n \"table\" as Format,\n )\n .option(\"--config <path>\", \"Path to trawly.toml\")\n .option(\n \"--policy <name>\",\n `Use a built-in policy preset (${POLICY_VALUES.join(\"|\")})`,\n parsePolicy,\n )\n .option(\"--baseline <path>\", \"Mark findings already present in this baseline\")\n .option(\"--write-baseline <path>\", \"Write the current active findings baseline\")\n .option(\"--output <path>\", \"Write report output to a file\")\n .option(\"--risk\", \"Enable risk signals\")\n .option(\"--no-risk\", \"Disable risk signals\")\n .option(\"--env\", \"Scan committed .env files for secret-like values\")\n .option(\"--no-env\", \"Disable committed .env file scanning\")\n .option(\"--prod\", \"Only scan production dependencies (excludes dev)\")\n .option(\"--include-dev\", \"Include dev dependencies (default)\")\n .option(\n \"-v, --details\",\n \"Show one row per advisory (full table). Default groups by package.\",\n )\n .option(\n \"-q, --summary\",\n \"Show only the one-line severity summary. Mutually exclusive with --details.\",\n )\n .action(async (path: string, opts: InspectCliOptions, command: Command) => {\n await runScanCommand(\n path,\n {\n ...normalizeScanOptions(opts, command),\n failOn: \"none\" as FailOnLevel,\n },\n { gate: false },\n );\n });\n\nprogram\n .command(\"init\")\n .description(\n \"Create trawly.toml and write an initial baseline so CI can focus on new findings.\",\n )\n .argument(\"[path]\", \"Project directory to initialize\", \".\")\n .option(\"--config <path>\", \"Config path to write\", \"trawly.toml\")\n .option(\"--baseline <path>\", \"Baseline path to write\", \"trawly-baseline.json\")\n .option(\n \"--policy <name>\",\n `Initial policy preset (${POLICY_VALUES.join(\"|\")})`,\n parsePolicy,\n \"ci\" as PolicyPresetName,\n )\n .option(\"--overwrite\", \"Overwrite an existing config file\")\n .option(\"--skip-baseline\", \"Do not scan or write a baseline\")\n .action(async (path: string, opts: InitCliOptions) => {\n await runInitCommand(path, opts);\n });\n\nprogram\n .command(\"why\")\n .description(\n \"Explain where a package appears in supported lockfiles.\",\n )\n .argument(\"<package>\", \"Package name to explain\")\n .argument(\"[path]\", \"Project directory to inspect\", \".\")\n .option(\n \"--lockfile <path>\",\n \"Explicit lockfile path. May be repeated.\",\n collectOption,\n )\n .action((packageName: string, path: string, opts: WhyCliOptions) => {\n runWhyCommand(packageName, path, opts);\n });\n\nprogram\n .command(\"add\")\n .description(\n \"Resolve, scan, and install packages. Vulnerable packages are blocked; clean ones are forwarded to your package manager.\",\n )\n .argument(\"<args...>\", \"Packages to add (e.g. next vitest@1) : PM flags after the first package are passed through\")\n .option(\n \"--fail-on <level>\",\n `Block install when a finding meets this severity (${FAIL_ON_VALUES.join(\"|\")})`,\n parseFailOn,\n \"high\" as FailOnLevel,\n )\n .option(\n \"--pm <name>\",\n `Force a package manager (${PM_VALUES.join(\"|\")}). Auto-detected by default.`,\n parsePm,\n )\n .option(\n \"--allow-vulnerable\",\n \"Install even if vulnerabilities are found (still prints findings).\",\n )\n .passThroughOptions()\n .action(async (args: string[], opts: AddCliOptions) => {\n await executeAdd(args, opts);\n });\n\nprogram\n .command(\"install\")\n .alias(\"i\")\n .description(\n \"Run the project's package manager install. With package args, behaves like `add` (gates on vulnerabilities). With none, forwards directly.\",\n )\n .argument(\"[args...]\", \"Optional packages to add\")\n .option(\n \"--fail-on <level>\",\n `Block install when a finding meets this severity (${FAIL_ON_VALUES.join(\"|\")})`,\n parseFailOn,\n \"high\" as FailOnLevel,\n )\n .option(\n \"--pm <name>\",\n `Force a package manager (${PM_VALUES.join(\"|\")})`,\n parsePm,\n )\n .option(\"--allow-vulnerable\", \"Install even if vulnerabilities are found.\")\n .passThroughOptions()\n .action(async (args: string[], opts: AddCliOptions) => {\n if (args.length === 0) {\n // Bare install: pure passthrough.\n const pm = detectPackageManager({ override: opts.pm });\n const command = buildInstallCommand(pm, []);\n process.stdout.write(\n kleur.gray(`> ${command.bin} ${command.args.join(\" \")}\\n`),\n );\n try {\n const code = await runPackageManager(command);\n process.exit(code);\n } catch (err) {\n printErr(`trawly: ${(err as Error).message}`);\n process.exit(EXIT.operational);\n }\n }\n await executeAdd(args, opts);\n });\n\nprogram\n .command(\"env\")\n .description(\n \"Scan for env-file leaks: tracked .env files, missing .gitignore coverage, npm-publish exposure, and secrets in .env.example.\",\n )\n .argument(\"[path]\", \"Project directory to scan\", \".\")\n .option(\n \"--format <format>\",\n \"Output format: table | json\",\n parseEnvFormat,\n \"table\" as EnvFormat,\n )\n .option(\n \"--fail-on <level>\",\n `Exit non-zero when an issue meets this severity (${FAIL_ON_VALUES.join(\"|\")})`,\n parseFailOn,\n \"high\" as FailOnLevel,\n )\n .action(async (path: string, opts: EnvCliOptions) => {\n await runEnvCommand(path, opts);\n });\n\nprogram\n .command(\"remove\")\n .alias(\"uninstall\")\n .description(\n \"Remove packages by delegating to the project's package manager (no scan).\",\n )\n .argument(\"<args...>\", \"Packages to remove\")\n .option(\n \"--pm <name>\",\n `Force a package manager (${PM_VALUES.join(\"|\")})`,\n parsePm,\n )\n .passThroughOptions()\n .action(async (args: string[], opts: { pm?: PackageManager }) => {\n const pm = detectPackageManager({ override: opts.pm });\n const { specs, flags } = splitArgs(args);\n const command = buildRemoveCommand(pm, specs, flags);\n process.stdout.write(\n kleur.gray(`> ${command.bin} ${command.args.join(\" \")}\\n`),\n );\n try {\n const code = await runPackageManager(command);\n process.exit(code);\n } catch (err) {\n printErr(`trawly: ${(err as Error).message}`);\n process.exit(EXIT.operational);\n }\n });\n\ninterface ScanCliOptions {\n lockfile?: string[];\n sbom?: string[];\n format: Format;\n failOn?: FailOnLevel;\n config?: string;\n policy?: PolicyPresetName;\n baseline?: string;\n writeBaseline?: string;\n output?: string;\n risk?: boolean;\n env?: boolean;\n prod?: boolean;\n includeDev?: boolean;\n details?: boolean;\n summary?: boolean;\n}\n\ntype InspectCliOptions = Omit<ScanCliOptions, \"failOn\">;\n\ninterface InitCliOptions {\n config: string;\n baseline: string;\n policy: PolicyPresetName;\n overwrite?: boolean;\n skipBaseline?: boolean;\n}\n\ninterface WhyCliOptions {\n lockfile?: string[];\n}\n\ninterface AddCliOptions {\n failOn: FailOnLevel;\n pm?: PackageManager;\n allowVulnerable?: boolean;\n}\n\ninterface EnvCliOptions {\n format: EnvFormat;\n failOn: FailOnLevel;\n}\n\nfunction normalizeScanOptions<T extends ScanCliOptions | InspectCliOptions>(\n opts: T,\n command: Command,\n): T {\n return {\n ...opts,\n risk: triStateBooleanFlag(command, \"risk\"),\n env: triStateBooleanFlag(command, \"env\"),\n };\n}\n\nfunction triStateBooleanFlag(\n command: Command,\n name: \"risk\" | \"env\",\n): boolean | undefined {\n return command.getOptionValueSource(name) === \"cli\"\n ? (command.getOptionValue(name) as boolean)\n : undefined;\n}\n\nasync function runEnvCommand(\n path: string,\n opts: EnvCliOptions,\n): Promise<void> {\n try {\n const result = await scanEnv({ cwd: path });\n if (opts.format === \"json\") {\n process.stdout.write(`${reportEnvJson(result)}\\n`);\n } else {\n const brand = process.stdout.isTTY === true;\n process.stdout.write(`${reportEnvTable(result, { brand })}\\n`);\n }\n if (result.errors.length > 0) process.exit(EXIT.operational);\n if (envIssuesMeetThreshold(result.issues, opts.failOn)) {\n if (opts.format !== \"json\") {\n process.stderr.write(\n `${kleur.red(\n `× Failing because at least one issue meets --fail-on=${opts.failOn}.`,\n )}\\n`,\n );\n }\n process.exit(EXIT.findings);\n }\n process.exit(EXIT.ok);\n } catch (err) {\n printErr(`trawly: ${(err as Error).message}`);\n process.exit(EXIT.operational);\n }\n}\n\nasync function runScanCommand(\n path: string,\n opts: ScanCliOptions,\n { gate }: { gate: boolean },\n): Promise<void> {\n if (opts.prod && opts.includeDev) {\n printErr(\"Cannot combine --prod and --include-dev. Choose one.\");\n process.exit(EXIT.invalidInput);\n }\n if (opts.details && opts.summary) {\n printErr(\"Cannot combine --details and --summary. Choose one.\");\n process.exit(EXIT.invalidInput);\n }\n\n try {\n const cwd = resolve(path);\n const config = loadConfig(cwd, opts.config).config;\n const policy = resolvePolicy(opts.policy, config.policy);\n const failOn =\n opts.failOn ?? config.failOn ?? policy?.failOn ?? (\"high\" as FailOnLevel);\n const result = await scanProject({\n cwd,\n lockfile: opts.lockfile,\n sbom: opts.sbom,\n config: opts.config,\n policy: opts.policy,\n baseline: opts.baseline,\n writeBaseline: opts.writeBaseline,\n risk: opts.risk,\n env: opts.env,\n includeDev: opts.includeDev,\n prodOnly: opts.prod,\n });\n\n const output = renderReport(result, opts);\n if (opts.output) writeOutput(cwd, opts.output, output);\n else process.stdout.write(`${output}\\n`);\n\n if (result.errors.length > 0) {\n process.exit(EXIT.operational);\n }\n\n if (!gate) {\n if (opts.format === \"table\" && !opts.output && result.findings.length > 0) {\n process.stdout.write(\n `${kleur.gray(\n \"ℹ inspect mode: exiting 0 regardless of findings. Run `trawly scan` to gate CI.\",\n )}\\n`,\n );\n }\n process.exit(EXIT.ok);\n }\n\n if (meetsThreshold(result.findings, failOn)) {\n if (opts.format !== \"json\") {\n process.stderr.write(\n `${kleur.red(\n `× Failing because at least one finding meets --fail-on=${failOn}.`,\n )}\\n${kleur.gray(\n \" Run `trawly inspect` to log without exiting non-zero, or `trawly scan --fail-on=none` to disable the gate.\",\n )}\\n`,\n );\n }\n process.exit(EXIT.findings);\n }\n process.exit(EXIT.ok);\n } catch (err) {\n if (err instanceof ScanInputError || err instanceof ConfigError) {\n printErr(err.message);\n process.exit(EXIT.invalidInput);\n }\n printErr(`trawly: ${(err as Error).message}`);\n process.exit(EXIT.operational);\n }\n}\n\nasync function runInitCommand(\n path: string,\n opts: InitCliOptions,\n): Promise<void> {\n try {\n const result = await initProject({\n cwd: path,\n config: opts.config,\n baseline: opts.baseline,\n policy: opts.policy,\n overwrite: opts.overwrite,\n writeBaseline: !opts.skipBaseline,\n });\n\n const lines: string[] = [];\n lines.push(\n result.configWritten\n ? kleur.green(`✓ Wrote ${result.configPath}`)\n : kleur.gray(`~ Kept existing ${result.configPath}`),\n );\n if (!opts.skipBaseline) {\n if (result.baselineWritten && result.scan?.baseline?.written) {\n lines.push(kleur.green(`✓ Wrote ${result.scan.baseline.written}`));\n lines.push(\n kleur.gray(\n ` Baseline contains ${result.scan.baseline.total} active finding(s). Future scans can fail only on new findings with --baseline=${opts.baseline}.`,\n ),\n );\n } else {\n lines.push(kleur.gray(\"~ Baseline was not written.\"));\n }\n }\n for (const warning of result.warnings) {\n lines.push(kleur.yellow(`~ ${warning}`));\n }\n process.stdout.write(`${lines.join(\"\\n\")}\\n`);\n process.exit(EXIT.ok);\n } catch (err) {\n if (err instanceof ConfigError) {\n printErr(err.message);\n process.exit(EXIT.invalidInput);\n }\n printErr(`trawly: ${(err as Error).message}`);\n process.exit(EXIT.operational);\n }\n}\n\nfunction runWhyCommand(\n packageName: string,\n path: string,\n opts: WhyCliOptions,\n): void {\n try {\n const result = explainWhy(packageName, {\n cwd: path,\n lockfile: opts.lockfile,\n });\n if (result.lockfiles.length === 0) {\n printErr(\n \"No supported lockfile found. Pass --lockfile or run in a project with package-lock.json, pnpm-lock.yaml, or yarn.lock.\",\n );\n process.exit(EXIT.invalidInput);\n }\n const lines: string[] = [];\n lines.push(kleur.bold(`trawly why ${packageName}`));\n if (result.matches.length === 0) {\n lines.push(kleur.yellow(\"No matching package found in scanned lockfiles.\"));\n process.stdout.write(`${lines.join(\"\\n\")}\\n`);\n process.exit(EXIT.ok);\n }\n for (const match of result.matches) {\n const pkg = match.package;\n const kind = pkg.direct ? \"direct\" : \"transitive\";\n lines.push(\n `${pkg.name}@${pkg.version} (${kind}, ${pkg.manager ?? \"lockfile\"})`,\n );\n lines.push(` path: ${pkg.path}`);\n lines.push(` chain: ${match.chain.join(\" > \")}`);\n if (match.note) lines.push(kleur.gray(` note: ${match.note}`));\n if (pkg.sourceFile) {\n lines.push(\n kleur.gray(\n ` source: ${pkg.sourceFile}${pkg.line ? `:${pkg.line}` : \"\"}`,\n ),\n );\n }\n }\n process.stdout.write(`${lines.join(\"\\n\")}\\n`);\n process.exit(EXIT.ok);\n } catch (err) {\n printErr(`trawly: ${(err as Error).message}`);\n process.exit(EXIT.operational);\n }\n}\n\nasync function executeAdd(args: string[], opts: AddCliOptions): Promise<void> {\n try {\n const result = await runAdd(args, {\n failOn: opts.failOn,\n pm: opts.pm,\n allowVulnerable: opts.allowVulnerable,\n });\n process.stdout.write(reportAdd(result));\n\n if (result.errored.length > 0) process.exit(EXIT.operational);\n if (result.pmExitCode !== undefined && result.pmExitCode !== 0) {\n process.exit(result.pmExitCode);\n }\n if (result.blocked.length > 0) process.exit(EXIT.findings);\n process.exit(EXIT.ok);\n } catch (err) {\n printErr(`trawly: ${(err as Error).message}`);\n process.exit(EXIT.operational);\n }\n}\n\nfunction splitArgs(args: string[]): { specs: string[]; flags: string[] } {\n const specs: string[] = [];\n const flags: string[] = [];\n for (const a of args) {\n if (a.startsWith(\"-\")) flags.push(a);\n else specs.push(a);\n }\n return { specs, flags };\n}\n\nfunction printErr(msg: string): void {\n process.stderr.write(`${kleur.red(msg)}\\n`);\n}\n\nfunction renderReport(\n result: Awaited<ReturnType<typeof scanProject>>,\n opts: ScanCliOptions,\n): string {\n switch (opts.format) {\n case \"json\":\n return reportJson(result);\n case \"markdown\":\n return reportMarkdown(result);\n case \"sarif\":\n return reportSarif(result);\n case \"table\": {\n const view = opts.summary\n ? \"summary\"\n : opts.details\n ? \"details\"\n : \"grouped\";\n const brand = process.stdout.isTTY === true && !opts.output;\n return reportTable(result, { view, brand });\n }\n }\n}\n\nfunction writeOutput(cwd: string, path: string, content: string): void {\n const absolute = resolve(cwd, path);\n mkdirSync(dirname(absolute), { recursive: true });\n writeFileSync(absolute, `${content}\\n`);\n}\n\nawait program.parseAsync(process.argv);\n","import kleur from \"kleur\";\nimport { queryOsv } from \"../sources/osv.js\";\nimport { compareFindings, summarize } from \"../scanner.js\";\nimport { SEVERITY_RANK } from \"../types.js\";\nimport type { Finding, PackageInstance, Severity } from \"../types.js\";\nimport {\n buildAddCommand,\n detectPackageManager,\n type PackageManager,\n} from \"../installer/pm-detect.js\";\nimport { runPackageManager } from \"../installer/runner.js\";\nimport {\n parseSpec,\n partitionArgs,\n type ParsedSpec,\n type UnsupportedReason,\n} from \"../installer/spec-parser.js\";\nimport {\n resolveVersion,\n VersionResolveError,\n type ResolvedVersion,\n} from \"../installer/version-resolver.js\";\n\nexport interface AddOptions {\n cwd?: string;\n pm?: PackageManager;\n failOn: Severity | \"none\";\n allowVulnerable?: boolean;\n fetchImpl?: typeof fetch;\n /** Test seam: replace the real spawn with a stub. */\n runner?: typeof runPackageManager;\n}\n\nexport interface AddResult {\n /** Specs we sent to the package manager. */\n installed: ResolvedSpec[];\n /** Specs we refused to install. */\n blocked: BlockedSpec[];\n /** Specs we couldn't analyze (git, file, url, alias). */\n skipped: SkippedSpec[];\n /** Specs that failed registry resolution. */\n errored: ErroredSpec[];\n /** All findings collected, sorted. */\n findings: Finding[];\n /** Exit code from the PM, or undefined if we never ran it. */\n pmExitCode?: number;\n}\n\ninterface ResolvedSpec {\n spec: ParsedSpec;\n resolved: ResolvedVersion;\n findings: Finding[];\n}\n\ninterface BlockedSpec extends ResolvedSpec {\n reason: \"vulnerable\";\n}\n\ninterface SkippedSpec {\n spec: ParsedSpec;\n reason: UnsupportedReason;\n}\n\ninterface ErroredSpec {\n spec: ParsedSpec;\n message: string;\n}\n\nexport async function runAdd(\n args: string[],\n options: AddOptions,\n): Promise<AddResult> {\n const { specs, flags } = partitionArgs(args);\n\n const skipped: SkippedSpec[] = [];\n const resolvable: ParsedSpec[] = [];\n for (const spec of specs) {\n if (spec.unsupported) {\n skipped.push({ spec, reason: spec.unsupported });\n } else {\n resolvable.push(spec);\n }\n }\n\n const resolved: ResolvedSpec[] = [];\n const errored: ErroredSpec[] = [];\n await Promise.all(\n resolvable.map(async (spec) => {\n try {\n const r = await resolveVersion(spec.name, spec.requested, {\n fetchImpl: options.fetchImpl,\n });\n resolved.push({ spec, resolved: r, findings: [] });\n } catch (err) {\n const message =\n err instanceof VersionResolveError\n ? err.message\n : `Registry error: ${(err as Error).message}`;\n errored.push({ spec, message });\n }\n }),\n );\n\n let findings: Finding[] = [];\n if (resolved.length > 0) {\n const instances: PackageInstance[] = resolved.map((r) => ({\n name: r.spec.name,\n version: r.resolved.version,\n ecosystem: \"npm\",\n path: r.spec.raw,\n direct: true,\n dev: false,\n optional: false,\n }));\n try {\n findings = await queryOsv(instances, { fetchImpl: options.fetchImpl });\n } catch (err) {\n // If OSV is unreachable we cannot make a safe call; treat as a hard error\n // for every resolvable spec rather than silently letting installs through.\n const message = `OSV query failed: ${(err as Error).message}`;\n for (const r of resolved) errored.push({ spec: r.spec, message });\n resolved.length = 0;\n }\n }\n\n for (const f of findings) {\n const owner = resolved.find(\n (r) => r.spec.name === f.packageName && r.resolved.version === f.installedVersion,\n );\n if (owner) owner.findings.push(f);\n }\n\n const blocked: BlockedSpec[] = [];\n const installed: ResolvedSpec[] = [];\n for (const r of resolved) {\n if (shouldBlock(r.findings, options)) {\n blocked.push({ ...r, reason: \"vulnerable\" });\n } else {\n installed.push(r);\n }\n }\n\n findings.sort(compareFindings);\n\n let pmExitCode: number | undefined;\n if (installed.length > 0) {\n const pm = detectPackageManager({ override: options.pm, cwd: options.cwd });\n const cmd = buildAddCommand(\n pm,\n installed.map((r) => r.spec.raw),\n flags,\n );\n process.stdout.write(\n kleur.gray(`> ${cmd.bin} ${cmd.args.join(\" \")}\\n`),\n );\n const runner = options.runner ?? runPackageManager;\n pmExitCode = await runner(cmd, { cwd: options.cwd });\n }\n\n return { installed, blocked, skipped, errored, findings, pmExitCode };\n}\n\nexport function reportAdd(result: AddResult): string {\n const lines: string[] = [];\n\n if (result.skipped.length > 0) {\n for (const s of result.skipped) {\n lines.push(\n kleur.yellow(\n `~ Skipped ${s.spec.raw}: ${describeUnsupported(s.reason)} (cannot scan; not forwarded to install)`,\n ),\n );\n }\n }\n\n if (result.errored.length > 0) {\n for (const e of result.errored) {\n lines.push(kleur.red(`! ${e.spec.raw}: ${e.message}`));\n }\n }\n\n if (result.blocked.length > 0) {\n for (const b of result.blocked) {\n const sev = summarize(b.findings);\n const counts = describeSeverityCounts(sev);\n lines.push(\n kleur.red(\n `✗ Blocked ${b.spec.name}@${b.resolved.version}: ${counts}`,\n ),\n );\n if (b.resolved.source === \"fallback-latest\") {\n lines.push(\n kleur.gray(\n ` (scanned latest because we don't resolve semver ranges yet; you asked for \"${b.resolved.requested}\")`,\n ),\n );\n }\n for (const f of b.findings) {\n lines.push(\n ` - [${colorSeverity(f.severity)}] ${f.id} : ${f.summary}`,\n );\n if (f.fixedVersions.length > 0) {\n lines.push(kleur.gray(` fixed in: ${f.fixedVersions.join(\", \")}`));\n }\n if (f.url) lines.push(kleur.gray(` ${f.url}`));\n }\n }\n }\n\n if (result.installed.length > 0) {\n const names = result.installed\n .map((r) => `${r.spec.name}@${r.resolved.version}`)\n .join(\", \");\n lines.push(kleur.green(`✓ Installing: ${names}`));\n } else if (result.blocked.length > 0) {\n lines.push(\n kleur.red(\"Nothing installed : all requested packages were blocked.\"),\n );\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction shouldBlock(findings: Finding[], options: AddOptions): boolean {\n if (options.allowVulnerable) return false;\n if (options.failOn === \"none\") return false;\n const threshold = SEVERITY_RANK[options.failOn];\n return findings.some((f) => SEVERITY_RANK[f.severity] >= threshold);\n}\n\nfunction describeUnsupported(reason: UnsupportedReason): string {\n switch (reason) {\n case \"git\":\n return \"git specs cannot be scanned against OSV\";\n case \"url\":\n return \"URL specs cannot be scanned against OSV\";\n case \"file\":\n return \"local file specs cannot be scanned against OSV\";\n case \"alias\":\n return \"npm aliases are not supported in v1\";\n case \"workspace\":\n return \"workspace protocol specs are not scanned\";\n case \"invalid\":\n return \"could not parse spec\";\n }\n}\n\nfunction describeSeverityCounts(summary: Record<Severity, number>): string {\n const parts: string[] = [];\n for (const sev of [\"critical\", \"high\", \"moderate\", \"low\", \"unknown\"] as Severity[]) {\n if (summary[sev] > 0) parts.push(`${summary[sev]} ${sev}`);\n }\n return parts.length === 0 ? \"no advisories\" : `${parts.join(\", \")} advisor${total(summary) === 1 ? \"y\" : \"ies\"}`;\n}\n\nfunction total(summary: Record<Severity, number>): number {\n return Object.values(summary).reduce((a, b) => a + b, 0);\n}\n\nfunction colorSeverity(sev: Severity): string {\n switch (sev) {\n case \"critical\":\n return kleur.bold().red(sev);\n case \"high\":\n return kleur.red(sev);\n case \"moderate\":\n return kleur.yellow(sev);\n case \"low\":\n return kleur.cyan(sev);\n case \"unknown\":\n return kleur.gray(sev);\n }\n}\n\n// Re-exports so tests can poke at the parsed spec type.\nexport { parseSpec };\n","import { createHash } from \"node:crypto\";\nimport type { Finding, PackageInstance } from \"./types.js\";\n\nexport function fingerprintFinding(input: {\n source: Finding[\"source\"];\n id: string;\n ecosystem: string;\n packageName: string;\n installedVersion: string;\n type: Finding[\"type\"];\n}): string {\n return stableHash([\n input.source,\n input.type,\n input.id,\n input.ecosystem,\n input.packageName,\n input.installedVersion,\n ]);\n}\n\nexport function packageKey(pkg: PackageInstance): string {\n return pkg.purl ?? `${pkg.ecosystem}:${pkg.name}@${pkg.version}`;\n}\n\nfunction stableHash(parts: string[]): string {\n return createHash(\"sha256\").update(parts.join(\"\\0\")).digest(\"hex\");\n}\n","import { fingerprintFinding, packageKey } from \"../fingerprint.js\";\nimport type { Ecosystem, Finding, PackageInstance, Severity } from \"../types.js\";\n\nconst OSV_QUERYBATCH_URL = \"https://api.osv.dev/v1/querybatch\";\nconst OSV_VULN_URL = \"https://api.osv.dev/v1/vulns\";\nconst QUERY_CHUNK_SIZE = 500;\nconst REQUEST_TIMEOUT_MS = 15_000;\nconst MAX_RETRIES = 2;\nconst DETAIL_CONCURRENCY = 8;\n\ninterface OsvQueryBatchResponse {\n results: Array<{\n vulns?: Array<{ id: string; modified?: string }>;\n next_page_token?: string;\n }>;\n}\n\ninterface OsvSeverity {\n type: string;\n score: string;\n}\n\ninterface OsvAffectedRange {\n type: string;\n events: Array<{ introduced?: string; fixed?: string; last_affected?: string }>;\n}\n\ninterface OsvAffectedPackage {\n package?: { ecosystem?: string; name?: string; purl?: string };\n ranges?: OsvAffectedRange[];\n versions?: string[];\n ecosystem_specific?: { severity?: string };\n}\n\ninterface OsvVulnDetail {\n id: string;\n aliases?: string[];\n summary?: string;\n details?: string;\n references?: Array<{ type?: string; url?: string }>;\n severity?: OsvSeverity[];\n database_specific?: { severity?: string };\n affected?: OsvAffectedPackage[];\n}\n\nexport interface OsvQueryDeps {\n fetchImpl?: typeof fetch;\n}\n\ninterface UniquePackage {\n name: string;\n version: string;\n ecosystem?: Ecosystem;\n purl?: string;\n}\n\n/**\n * Build the deduplicated list of unique name@version pairs to query OSV with.\n */\nexport function dedupeForQuery(\n packages: PackageInstance[],\n): UniquePackage[] {\n const seen = new Set<string>();\n const out: UniquePackage[] = [];\n for (const pkg of packages) {\n const key = packageKey(pkg);\n if (seen.has(key)) continue;\n seen.add(key);\n if (pkg.purl) out.push({ name: pkg.name, version: pkg.version, purl: pkg.purl });\n else if (pkg.ecosystem === \"npm\") out.push({ name: pkg.name, version: pkg.version });\n else {\n out.push({\n name: pkg.name,\n version: pkg.version,\n ecosystem: pkg.ecosystem,\n });\n }\n }\n return out;\n}\n\n/**\n * Query OSV for the given installed packages and return one Finding per\n * (advisory, affected package instance) pair.\n */\nexport async function queryOsv(\n packages: PackageInstance[],\n deps: OsvQueryDeps = {},\n): Promise<Finding[]> {\n const fetchImpl = deps.fetchImpl ?? fetch;\n const unique = dedupeForQuery(packages);\n if (unique.length === 0) return [];\n\n const idsByPackage = new Map<string, Set<string>>();\n for (const chunk of chunked(unique, QUERY_CHUNK_SIZE)) {\n await queryBatchWithPagination(fetchImpl, chunk, idsByPackage);\n }\n\n const allIds = new Set<string>();\n for (const ids of idsByPackage.values()) {\n for (const id of ids) allIds.add(id);\n }\n\n const detailsById = new Map<string, OsvVulnDetail>();\n await mapWithConcurrency([...allIds], DETAIL_CONCURRENCY, async (id) => {\n try {\n const detail = await getJson<OsvVulnDetail>(\n fetchImpl,\n `${OSV_VULN_URL}/${encodeURIComponent(id)}`,\n );\n detailsById.set(id, detail);\n } catch {\n // Skip missing/broken records; we still have the id reported below.\n }\n });\n\n const findings: Finding[] = [];\n for (const pkg of packages) {\n const key = packageKey(pkg);\n const ids = idsByPackage.get(key);\n if (!ids) continue;\n for (const id of ids) {\n const detail = detailsById.get(id);\n findings.push(buildFinding(pkg, id, detail));\n }\n }\n return findings;\n}\n\nasync function queryBatchWithPagination(\n fetchImpl: typeof fetch,\n initial: UniquePackage[],\n idsByPackage: Map<string, Set<string>>,\n): Promise<void> {\n let pending = initial;\n const pageTokens = new Map<string, string>();\n\n while (pending.length > 0) {\n const res = await postJson<OsvQueryBatchResponse>(\n fetchImpl,\n OSV_QUERYBATCH_URL,\n { queries: pending.map((q) => toOsvQuery(q, pageTokens.get(queryKey(q)))) },\n );\n\n const next: UniquePackage[] = [];\n res.results.forEach((result, i) => {\n const q = pending[i];\n if (!q) return;\n const key = queryKey(q);\n if (result.vulns && result.vulns.length > 0) {\n const ids = idsByPackage.get(key) ?? new Set<string>();\n for (const v of result.vulns) ids.add(v.id);\n idsByPackage.set(key, ids);\n }\n if (result.next_page_token) {\n pageTokens.set(key, result.next_page_token);\n next.push(q);\n } else {\n pageTokens.delete(key);\n }\n });\n pending = next;\n }\n}\n\nfunction toOsvQuery(\n q: UniquePackage,\n pageToken: string | undefined,\n): Record<string, unknown> {\n const query = q.purl\n ? { package: { purl: q.purl } }\n : {\n package: { ecosystem: q.ecosystem ?? \"npm\", name: q.name },\n version: q.version,\n };\n return pageToken ? { ...query, page_token: pageToken } : query;\n}\n\nfunction queryKey(q: UniquePackage): string {\n return q.purl ?? `${q.ecosystem ?? \"npm\"}:${q.name}@${q.version}`;\n}\n\nfunction buildFinding(\n pkg: PackageInstance,\n id: string,\n detail: OsvVulnDetail | undefined,\n): Finding {\n const severity = detail ? parseSeverity(detail, pkg.name) : \"unknown\";\n const summary = detail?.summary ?? detail?.details ?? id;\n const aliases = detail?.aliases ?? [];\n const fingerprint = fingerprintFinding({\n source: \"osv\",\n type: \"vulnerability\",\n id,\n ecosystem: pkg.ecosystem,\n packageName: pkg.name,\n installedVersion: pkg.version,\n });\n return {\n id,\n source: \"osv\",\n type: \"vulnerability\",\n severity,\n ecosystem: pkg.ecosystem,\n packageName: pkg.name,\n installedVersion: pkg.version,\n summary: truncate(summary, 240),\n url: pickAdvisoryUrl(detail) ?? `https://osv.dev/vulnerability/${id}`,\n fixedVersions: detail ? collectFixedVersions(detail, pkg.name) : [],\n affectedPaths: [pkg.path],\n fingerprint,\n aliases,\n sourceFile: pkg.sourceFile,\n line: pkg.line,\n };\n}\n\nexport function parseSeverity(\n detail: OsvVulnDetail,\n packageName?: string,\n): Severity {\n // GHSA records expose a normalized severity in database_specific.severity.\n const dbSpecific = detail.database_specific?.severity?.toLowerCase();\n if (\n dbSpecific === \"critical\" ||\n dbSpecific === \"high\" ||\n dbSpecific === \"moderate\" ||\n dbSpecific === \"low\"\n ) {\n return dbSpecific;\n }\n if (dbSpecific === \"medium\") return \"moderate\";\n\n for (const aff of matchingAffected(detail, packageName)) {\n const ecosystemSeverity = aff.ecosystem_specific?.severity?.toLowerCase();\n if (\n ecosystemSeverity === \"critical\" ||\n ecosystemSeverity === \"high\" ||\n ecosystemSeverity === \"moderate\" ||\n ecosystemSeverity === \"low\"\n ) {\n return ecosystemSeverity;\n }\n if (ecosystemSeverity === \"medium\") return \"moderate\";\n }\n\n const cvss = detail.severity?.find((s) => s.type?.startsWith(\"CVSS_\"));\n if (cvss) {\n const score = parseCvssScore(cvss.score);\n if (score === undefined) return \"unknown\";\n if (score >= 9.0) return \"critical\";\n if (score >= 7.0) return \"high\";\n if (score >= 4.0) return \"moderate\";\n if (score > 0) return \"low\";\n }\n return \"unknown\";\n}\n\nfunction parseCvssScore(vector: string): number | undefined {\n const direct = Number.parseFloat(vector);\n if (!Number.isNaN(direct) && vector.trim() !== \"\") return direct;\n // Some entries store the full CVSS vector string; we don't compute it here.\n return undefined;\n}\n\nfunction pickAdvisoryUrl(detail: OsvVulnDetail | undefined): string | undefined {\n if (!detail?.references) return undefined;\n const advisory = detail.references.find((r) => r.type === \"ADVISORY\");\n return advisory?.url ?? detail.references[0]?.url;\n}\n\nexport function collectFixedVersions(\n detail: OsvVulnDetail,\n packageName: string,\n): string[] {\n const out = new Set<string>();\n for (const aff of matchingAffected(detail, packageName)) {\n for (const range of aff.ranges ?? []) {\n for (const event of range.events ?? []) {\n if (event.fixed) out.add(event.fixed);\n }\n }\n }\n return [...out];\n}\n\nfunction matchingAffected(\n detail: OsvVulnDetail,\n packageName: string | undefined,\n): OsvAffectedPackage[] {\n if (!packageName) return detail.affected ?? [];\n return (detail.affected ?? []).filter((aff) => {\n const affectedName = aff.package?.name;\n return !affectedName || affectedName === packageName;\n });\n}\n\nfunction* chunked<T>(items: T[], size: number): Generator<T[]> {\n for (let i = 0; i < items.length; i += size) {\n yield items.slice(i, i + size);\n }\n}\n\nasync function mapWithConcurrency<T>(\n items: T[],\n concurrency: number,\n worker: (item: T) => Promise<void>,\n): Promise<void> {\n let next = 0;\n const workers = Array.from(\n { length: Math.min(concurrency, items.length) },\n async () => {\n while (next < items.length) {\n const item = items[next++];\n if (item !== undefined) await worker(item);\n }\n },\n );\n await Promise.all(workers);\n}\n\nasync function postJson<T>(\n fetchImpl: typeof fetch,\n url: string,\n body: unknown,\n): Promise<T> {\n return withRetry(async () => {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n try {\n const res = await fetchImpl(url, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n if (!res.ok) {\n throw new HttpError(\n `OSV ${res.status}: ${res.statusText}`,\n res.status,\n retryAfterMs(res.headers),\n );\n }\n return (await res.json()) as T;\n } finally {\n clearTimeout(timer);\n }\n });\n}\n\nasync function getJson<T>(fetchImpl: typeof fetch, url: string): Promise<T> {\n return withRetry(async () => {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n try {\n const res = await fetchImpl(url, { signal: controller.signal });\n if (!res.ok) {\n throw new HttpError(\n `OSV ${res.status}: ${res.statusText}`,\n res.status,\n retryAfterMs(res.headers),\n );\n }\n return (await res.json()) as T;\n } finally {\n clearTimeout(timer);\n }\n });\n}\n\nclass HttpError extends Error {\n constructor(\n message: string,\n public readonly status: number,\n public readonly retryAfterMs?: number,\n ) {\n super(message);\n }\n}\n\nasync function withRetry<T>(fn: () => Promise<T>): Promise<T> {\n let lastErr: unknown;\n for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {\n try {\n return await fn();\n } catch (err) {\n lastErr = err;\n if (!isRetryable(err) || attempt === MAX_RETRIES) break;\n const delay = err instanceof HttpError && err.retryAfterMs !== undefined\n ? err.retryAfterMs\n : 250 * 2 ** attempt;\n await new Promise((r) => setTimeout(r, delay));\n }\n }\n throw lastErr;\n}\n\nfunction isRetryable(err: unknown): boolean {\n if (err instanceof HttpError) return err.status === 429 || err.status >= 500;\n // AbortError (timeout) and network errors are retryable.\n return true;\n}\n\nfunction retryAfterMs(headers: Headers): number | undefined {\n const value = headers.get(\"retry-after\");\n if (!value) return undefined;\n const seconds = Number(value);\n if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1000;\n const date = Date.parse(value);\n if (Number.isNaN(date)) return undefined;\n return Math.max(0, date - Date.now());\n}\n\nfunction truncate(s: string, max: number): string {\n if (s.length <= max) return s;\n return `${s.slice(0, max - 1)}…`;\n}\n","import { existsSync, statSync } from \"node:fs\";\nimport { dirname, resolve, join } from \"node:path\";\nimport { applyBaseline, writeBaseline } from \"./baseline.js\";\nimport { loadConfig } from \"./config.js\";\nimport { scanEnvFiles } from \"./env.js\";\nimport { parseLockfile } from \"./extractors/lockfile.js\";\nimport { parseSbom } from \"./extractors/sbom.js\";\nimport { applyIgnores } from \"./ignore.js\";\nimport { resolvePolicy } from \"./policy.js\";\nimport { collectRiskSignals } from \"./risk.js\";\nimport { queryOsv } from \"./sources/osv.js\";\nimport { SEVERITY_RANK } from \"./types.js\";\nimport type {\n Finding,\n PackageInstance,\n ScanError,\n ScanLockfileOptions,\n ScanProjectOptions,\n ScanResult,\n Severity,\n} from \"./types.js\";\n\nconst DEFAULT_ALLOWED_REGISTRIES = [\n \"https://registry.npmjs.org\",\n \"https://registry.yarnpkg.com\",\n];\n\nexport async function scanProject(\n options: ScanProjectOptions = {},\n): Promise<ScanResult> {\n const cwd = resolve(options.cwd ?? process.cwd());\n const loadedConfig = loadConfig(cwd, options.config);\n const policy = resolvePolicy(options.policy, loadedConfig.config.policy);\n const lockfilePaths = options.lockfile\n ? normalizePaths(cwd, options.lockfile)\n : detectLockfiles(cwd);\n const sbomPaths = normalizePaths(cwd, options.sbom);\n const envEnabled = options.env ?? loadedConfig.config.env ?? policy?.env ?? false;\n\n if (lockfilePaths.length === 0 && sbomPaths.length === 0 && !envEnabled) {\n throw new ScanInputError(\n `No supported lockfile or SBOM found in ${cwd}. Pass --lockfile/--sbom or run in a directory with package-lock.json, pnpm-lock.yaml, or yarn.lock.`,\n );\n }\n\n return scanLockfile({\n lockfilePath: lockfilePaths,\n sbom: sbomPaths,\n cwd,\n config: options.config,\n policy: options.policy,\n baseline: options.baseline,\n writeBaseline: options.writeBaseline,\n risk: options.risk ?? loadedConfig.config.risk ?? policy?.risk,\n env: envEnabled,\n allowedRegistries:\n options.allowedRegistries ?? loadedConfig.config.allowedRegistries,\n includeDev: options.includeDev ?? policy?.includeDev,\n prodOnly: options.prodOnly,\n fetchImpl: options.fetchImpl,\n now: options.now,\n });\n}\n\nexport async function scanLockfile(\n options: ScanLockfileOptions,\n): Promise<ScanResult> {\n const initialCwd = resolve(options.cwd ?? process.cwd());\n const lockfilePaths = normalizePaths(initialCwd, options.lockfilePath);\n const sbomPaths = normalizePaths(initialCwd, options.sbom);\n const cwd = options.cwd\n ? initialCwd\n : deriveCwdFromInputs(lockfilePaths, sbomPaths, initialCwd);\n const now = options.now ?? new Date();\n const loadedConfig = loadConfig(cwd, options.config);\n const policy = resolvePolicy(options.policy, loadedConfig.config.policy);\n const envEnabled = options.env ?? loadedConfig.config.env ?? policy?.env ?? false;\n\n for (const path of [...lockfilePaths, ...sbomPaths]) validateFile(path);\n\n const allInstances = [\n ...lockfilePaths.flatMap((path) => parseLockfile(path)),\n ...sbomPaths.flatMap((path) => parseSbom(path)),\n ];\n const instances = filterInstances(allInstances, {\n ...options,\n includeDev: options.includeDev ?? policy?.includeDev,\n });\n const errors: ScanError[] = [];\n const warnings: string[] = [];\n const envResult = envEnabled\n ? scanEnvFiles(cwd)\n : { findings: [], warnings: [], filesScanned: 0 };\n warnings.push(...envResult.warnings);\n\n let findings: Finding[] = [...envResult.findings];\n try {\n findings.push(...(await queryOsv(instances, { fetchImpl: options.fetchImpl })));\n } catch (err) {\n errors.push({\n message: \"Failed to query OSV advisory database\",\n cause: (err as Error).message,\n });\n }\n\n const riskEnabled =\n options.risk ?? loadedConfig.config.risk ?? policy?.risk ?? true;\n const risk = await collectRiskSignals(instances, {\n enabled: riskEnabled,\n allowedRegistries:\n options.allowedRegistries ??\n loadedConfig.config.allowedRegistries ??\n DEFAULT_ALLOWED_REGISTRIES,\n fetchImpl: options.fetchImpl,\n now,\n });\n findings.push(...risk.findings);\n warnings.push(...risk.warnings);\n\n const ignoreResult = applyIgnores(\n findings,\n loadedConfig.config.ignore,\n now,\n );\n warnings.push(...ignoreResult.warnings);\n findings = ignoreResult.active;\n\n findings.sort(compareFindings);\n ignoreResult.ignored.sort(compareFindings);\n\n const appliedBaseline = applyBaseline(findings, cwd, options.baseline);\n let baseline = appliedBaseline?.result;\n if (appliedBaseline) {\n findings = appliedBaseline.findings;\n }\n if (options.writeBaseline) {\n baseline = writeBaseline(findings, cwd, options.writeBaseline, baseline);\n }\n\n return {\n scannedAt: now.toISOString(),\n packagesScanned: instances.length,\n findings,\n ignoredFindings: ignoreResult.ignored,\n summary: summarize(findings),\n errors,\n warnings,\n baseline,\n };\n}\n\nfunction deriveCwdFromInputs(\n lockfilePaths: string[],\n sbomPaths: string[],\n fallback: string,\n): string {\n const firstInput = lockfilePaths[0] ?? sbomPaths[0];\n return firstInput ? dirname(firstInput) : fallback;\n}\n\nexport class ScanInputError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ScanInputError\";\n }\n}\n\nfunction detectLockfiles(cwd: string): string[] {\n const candidates = [\n \"package-lock.json\",\n \"npm-shrinkwrap.json\",\n \"pnpm-lock.yaml\",\n \"yarn.lock\",\n ].map((file) => join(cwd, file));\n return candidates.filter((candidate) => existsSync(candidate));\n}\n\nfunction filterInstances(\n instances: PackageInstance[],\n options: { includeDev?: boolean; prodOnly?: boolean },\n): PackageInstance[] {\n const includeDev = options.prodOnly ? false : options.includeDev !== false;\n if (includeDev) return instances;\n return instances.filter((p) => !p.dev);\n}\n\nexport function compareFindings(a: Finding, b: Finding): number {\n const sev = SEVERITY_RANK[b.severity] - SEVERITY_RANK[a.severity];\n if (sev !== 0) return sev;\n if (a.source !== b.source) return a.source.localeCompare(b.source);\n if (a.packageName !== b.packageName) {\n return a.packageName.localeCompare(b.packageName);\n }\n if (a.installedVersion !== b.installedVersion) {\n return a.installedVersion.localeCompare(b.installedVersion);\n }\n return a.id.localeCompare(b.id);\n}\n\nexport function summarize(findings: Finding[]): Record<Severity, number> {\n const summary: Record<Severity, number> = {\n critical: 0,\n high: 0,\n moderate: 0,\n low: 0,\n unknown: 0,\n };\n for (const f of findings) summary[f.severity]++;\n return summary;\n}\n\n/**\n * Returns true when any finding meets or exceeds the given severity threshold.\n * \"none\" means never fail.\n */\nexport function meetsThreshold(\n findings: Finding[],\n threshold: Severity | \"none\",\n): boolean {\n if (threshold === \"none\") return false;\n const min = SEVERITY_RANK[threshold];\n return findings.some(\n (f) => f.baseline !== \"existing\" && SEVERITY_RANK[f.severity] >= min,\n );\n}\n\nfunction normalizePaths(\n cwd: string,\n value: string | string[] | undefined,\n): string[] {\n if (!value) return [];\n const values = Array.isArray(value) ? value : [value];\n return [...new Set(values.map((path) => resolve(cwd, path)))];\n}\n\nfunction validateFile(path: string): void {\n if (!existsSync(path)) {\n throw new ScanInputError(`Input file does not exist: ${path}`);\n }\n const stat = statSync(path);\n if (!stat.isFile()) {\n throw new ScanInputError(`Input path is not a file: ${path}`);\n }\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport type { BaselineFile, BaselineResult, Finding } from \"./types.js\";\n\nexport interface AppliedBaseline {\n result: BaselineResult;\n findings: Finding[];\n}\n\nexport class BaselineError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"BaselineError\";\n }\n}\n\nexport function applyBaseline(\n findings: Finding[],\n cwd: string,\n baselinePath?: string,\n): AppliedBaseline | undefined {\n if (!baselinePath) return undefined;\n const absolute = resolve(cwd, baselinePath);\n const loaded = readBaseline(absolute);\n const fingerprints = new Set(loaded.findings);\n let existing = 0;\n let fresh = 0;\n const marked = findings.map((finding) => {\n if (fingerprints.has(finding.fingerprint)) {\n existing++;\n return { ...finding, baseline: \"existing\" as const };\n }\n fresh++;\n return { ...finding, baseline: \"new\" as const };\n });\n return {\n result: {\n path: absolute,\n loaded: true,\n total: findings.length,\n existing,\n new: fresh,\n },\n findings: marked,\n };\n}\n\nexport function writeBaseline(\n findings: Finding[],\n cwd: string,\n baselinePath: string,\n existing?: BaselineResult,\n): BaselineResult {\n const absolute = resolve(cwd, baselinePath);\n const unique = [...new Set(findings.map((f) => f.fingerprint))].sort();\n const payload: BaselineFile = {\n version: 1,\n generatedAt: new Date().toISOString(),\n findings: unique,\n };\n mkdirSync(dirname(absolute), { recursive: true });\n writeFileSync(absolute, `${JSON.stringify(payload, null, 2)}\\n`);\n return {\n path: existing?.path,\n loaded: existing?.loaded ?? false,\n written: absolute,\n total: findings.length,\n existing: existing?.existing ?? 0,\n new: existing?.new ?? findings.length,\n };\n}\n\nfunction readBaseline(path: string): BaselineFile {\n if (!existsSync(path)) {\n throw new BaselineError(`Baseline file does not exist: ${path}`);\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(readFileSync(path, \"utf8\")) as unknown;\n } catch (err) {\n throw new BaselineError(\n `Failed to parse baseline ${path}: ${(err as Error).message}`,\n );\n }\n if (!isRecord(parsed) || parsed.version !== 1) {\n throw new BaselineError(`${path}: unsupported baseline format.`);\n }\n if (!Array.isArray(parsed.findings)) {\n throw new BaselineError(`${path}: findings must be an array.`);\n }\n const findings = parsed.findings.filter((v): v is string => typeof v === \"string\");\n return {\n version: 1,\n generatedAt:\n typeof parsed.generatedAt === \"string\" ? parsed.generatedAt : \"\",\n findings,\n };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { resolve, join } from \"node:path\";\nimport { parse as parseToml } from \"smol-toml\";\nimport type {\n FailOnLevel,\n IgnoreEntry,\n PolicyPresetName,\n TrawlyConfig,\n} from \"./types.js\";\n\nconst CONFIG_NAME = \"trawly.toml\";\nconst FAIL_ON_VALUES = new Set<FailOnLevel>([\n \"critical\",\n \"high\",\n \"moderate\",\n \"low\",\n \"none\",\n]);\nconst POLICY_VALUES = new Set<PolicyPresetName>([\n \"ci\",\n \"strict\",\n \"library\",\n \"app\",\n]);\n\nexport interface LoadedConfig {\n path?: string;\n config: TrawlyConfig;\n}\n\nexport class ConfigError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ConfigError\";\n }\n}\n\nexport function loadConfig(cwd: string, explicitPath?: string): LoadedConfig {\n const configPath = explicitPath\n ? resolve(cwd, explicitPath)\n : findConfig(cwd);\n\n if (!configPath) return { config: { ignore: [] } };\n if (!existsSync(configPath)) {\n throw new ConfigError(`Config file does not exist: ${configPath}`);\n }\n\n let raw: unknown;\n try {\n raw = parseToml(readFileSync(configPath, \"utf8\"));\n } catch (err) {\n throw new ConfigError(\n `Failed to parse ${configPath}: ${(err as Error).message}`,\n );\n }\n\n return { path: configPath, config: normalizeConfig(raw, configPath) };\n}\n\nfunction findConfig(cwd: string): string | undefined {\n const candidate = join(cwd, CONFIG_NAME);\n return existsSync(candidate) ? candidate : undefined;\n}\n\nfunction normalizeConfig(raw: unknown, path: string): TrawlyConfig {\n if (!isRecord(raw)) throw new ConfigError(`${path} must be a TOML table.`);\n\n const failOn = optionalString(raw.failOn, \"failOn\", path);\n if (failOn !== undefined && !FAIL_ON_VALUES.has(failOn as FailOnLevel)) {\n throw new ConfigError(\n `${path}: failOn must be one of ${[...FAIL_ON_VALUES].join(\", \")}.`,\n );\n }\n\n const policy = optionalString(raw.policy, \"policy\", path);\n if (policy !== undefined && !POLICY_VALUES.has(policy as PolicyPresetName)) {\n throw new ConfigError(\n `${path}: policy must be one of ${[...POLICY_VALUES].join(\", \")}.`,\n );\n }\n\n const risk = optionalBoolean(raw.risk, \"risk\", path);\n const env = optionalBoolean(raw.env, \"env\", path);\n const allowedRegistries = normalizeStringArray(\n raw.allowedRegistries,\n \"allowedRegistries\",\n path,\n );\n if (raw.ignore !== undefined && raw.IgnoredVulns !== undefined) {\n console.warn(\n `${path}: both \"ignore\" and legacy \"IgnoredVulns\" are defined; using \"ignore\".`,\n );\n }\n const ignore = normalizeIgnore(raw.ignore ?? raw.IgnoredVulns ?? [], path);\n\n return {\n failOn: failOn as FailOnLevel | undefined,\n policy: policy as PolicyPresetName | undefined,\n risk,\n env,\n allowedRegistries,\n ignore,\n };\n}\n\nfunction normalizeIgnore(raw: unknown, path: string): IgnoreEntry[] {\n if (raw === undefined) return [];\n if (!Array.isArray(raw)) {\n throw new ConfigError(`${path}: ignore must be an array of tables.`);\n }\n return raw.map((item, idx) => {\n if (!isRecord(item)) {\n throw new ConfigError(`${path}: ignore[${idx}] must be a table.`);\n }\n const id = requiredString(item.id, `ignore[${idx}].id`, path);\n const expires = requiredDateString(\n item.expires,\n `ignore[${idx}].expires`,\n path,\n );\n const reason = requiredString(item.reason, `ignore[${idx}].reason`, path);\n return {\n id,\n expires,\n reason,\n package: optionalString(item.package, `ignore[${idx}].package`, path),\n ecosystem: optionalString(item.ecosystem, `ignore[${idx}].ecosystem`, path),\n version: optionalString(item.version, `ignore[${idx}].version`, path),\n };\n });\n}\n\nfunction normalizeStringArray(\n raw: unknown,\n field: string,\n path: string,\n): string[] | undefined {\n if (raw === undefined) return undefined;\n if (!Array.isArray(raw) || raw.some((v) => typeof v !== \"string\")) {\n throw new ConfigError(`${path}: ${field} must be an array of strings.`);\n }\n return raw;\n}\n\nfunction requiredDateString(raw: unknown, field: string, path: string): string {\n const value = requiredString(raw, field, path);\n if (!isIsoDate(value)) {\n throw new ConfigError(`${path}: ${field} must be YYYY-MM-DD.`);\n }\n return value;\n}\n\nfunction requiredString(raw: unknown, field: string, path: string): string {\n if (typeof raw !== \"string\" || raw.trim() === \"\") {\n throw new ConfigError(`${path}: ${field} is required.`);\n }\n return raw;\n}\n\nfunction optionalString(\n raw: unknown,\n field: string,\n path: string,\n): string | undefined {\n if (raw === undefined) return undefined;\n if (typeof raw !== \"string\") {\n throw new ConfigError(`${path}: ${field} must be a string.`);\n }\n return raw;\n}\n\nfunction optionalBoolean(\n raw: unknown,\n field: string,\n path: string,\n): boolean | undefined {\n if (raw === undefined) return undefined;\n if (typeof raw !== \"boolean\") {\n throw new ConfigError(`${path}: ${field} must be true or false.`);\n }\n return raw;\n}\n\nfunction isIsoDate(s: string): boolean {\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(s)) return false;\n const date = new Date(`${s}T00:00:00.000Z`);\n return !Number.isNaN(date.getTime()) && date.toISOString().startsWith(s);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import {\n lstatSync,\n readdirSync,\n readFileSync,\n statSync,\n} from \"node:fs\";\nimport { basename, join, relative } from \"node:path\";\nimport { fingerprintFinding } from \"./fingerprint.js\";\nimport type { Finding } from \"./types.js\";\n\nconst MAX_ENV_FILE_BYTES = 1024 * 1024;\nconst SKIP_DIRS = new Set([\n \".git\",\n \".hg\",\n \".svn\",\n \"coverage\",\n \"dist\",\n \"node_modules\",\n \"vendor\",\n]);\nconst SAFE_ENV_SUFFIXES = new Set([\n \"default\",\n \"defaults\",\n \"dist\",\n \"example\",\n \"sample\",\n \"template\",\n]);\nconst SECRET_KEY_RE =\n /(?:^|_)(?:SECRET|TOKEN|PASSWORD|PASS|PWD|PRIVATE_KEY|API_KEY|ACCESS_KEY|AUTH|CREDENTIAL|DATABASE_URL|DB_URL|REDIS_URL|MONGO_URI|CONNECTION_STRING|WEBHOOK|CLIENT_SECRET)(?:$|_)/i;\nconst PRIVATE_KEY_RE = /PRIVATE_KEY|BEGIN_[A-Z0-9_]+_PRIVATE_KEY/i;\nconst PLACEHOLDER_RE =\n /^(?:|changeme|change_me|change-me|example|example-value|placeholder|replace_me|replace-me|todo|test|dummy|your_.+|<.+>|\\$\\{.+\\}|x+)$/i;\n\nexport interface EnvScanResult {\n findings: Finding[];\n warnings: string[];\n filesScanned: number;\n}\n\ninterface EnvAssignment {\n key: string;\n value: string;\n line: number;\n}\n\nexport function scanEnvFiles(cwd: string): EnvScanResult {\n const warnings: string[] = [];\n const findings: Finding[] = [];\n let filesScanned = 0;\n\n for (const file of findEnvFiles(cwd)) {\n let raw: string;\n try {\n const stat = statSync(file);\n if (stat.size > MAX_ENV_FILE_BYTES) {\n warnings.push(\n `Skipped env file ${relative(cwd, file)} because it is larger than 1 MiB.`,\n );\n continue;\n }\n raw = readFileSync(file, \"utf8\");\n } catch (err) {\n warnings.push(\n `Could not read env file ${relative(cwd, file)}: ${(err as Error).message}`,\n );\n continue;\n }\n\n filesScanned++;\n const rel = normalizePath(relative(cwd, file));\n findings.push(envFileFinding(file, rel));\n\n for (const assignment of parseEnvAssignments(raw)) {\n if (!isSensitiveAssignment(assignment)) continue;\n findings.push(envSecretFinding(file, rel, assignment));\n }\n }\n\n return { findings, warnings, filesScanned };\n}\n\nfunction findEnvFiles(root: string): string[] {\n const out: string[] = [];\n const stack = [root];\n while (stack.length > 0) {\n const dir = stack.pop()!;\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n continue;\n }\n for (const entry of entries) {\n const path = join(dir, entry);\n let stat;\n try {\n stat = lstatSync(path);\n } catch {\n continue;\n }\n if (stat.isSymbolicLink()) continue;\n if (stat.isDirectory()) {\n if (!SKIP_DIRS.has(entry)) stack.push(path);\n continue;\n }\n if (stat.isFile() && isEnvFile(entry)) out.push(path);\n }\n }\n return out.sort();\n}\n\nfunction isEnvFile(name: string): boolean {\n if (name === \".env\") return true;\n if (!name.startsWith(\".env.\")) return false;\n const suffixes = name\n .slice(\".env.\".length)\n .toLowerCase()\n .split(\".\")\n .filter(Boolean);\n return !suffixes.some((suffix) => SAFE_ENV_SUFFIXES.has(suffix));\n}\n\nfunction parseEnvAssignments(raw: string): EnvAssignment[] {\n const out: EnvAssignment[] = [];\n raw.split(/\\r?\\n/).forEach((line, index) => {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(\"#\")) return;\n const match = /^(?:export\\s+)?([A-Za-z_][A-Za-z0-9_]*)\\s*=\\s*(.*)$/.exec(\n trimmed,\n );\n if (!match) return;\n const key = match[1]!;\n const value = unquote(match[2]!.trim());\n out.push({ key, value, line: index + 1 });\n });\n return out;\n}\n\nfunction isSensitiveAssignment(assignment: EnvAssignment): boolean {\n if (!SECRET_KEY_RE.test(assignment.key)) return false;\n return !PLACEHOLDER_RE.test(assignment.value.trim());\n}\n\nfunction envFileFinding(sourceFile: string, rel: string): Finding {\n const id = \"TRAWLY-ENV-FILE\";\n return {\n id,\n source: \"trawly\",\n type: \"secret\",\n severity: \"moderate\",\n ecosystem: \"env\",\n packageName: \".env file\",\n installedVersion: rel,\n summary:\n \"Committed env file detected. Verify it does not contain secrets and prefer committing an example/template file instead.\",\n fixedVersions: [],\n affectedPaths: [rel],\n fingerprint: fingerprintFinding({\n source: \"trawly\",\n type: \"secret\",\n id,\n ecosystem: \"env\",\n packageName: \".env file\",\n installedVersion: rel,\n }),\n aliases: [],\n sourceFile,\n line: 1,\n };\n}\n\nfunction envSecretFinding(\n sourceFile: string,\n rel: string,\n assignment: EnvAssignment,\n): Finding {\n const id = \"TRAWLY-ENV-SECRET\";\n return {\n id,\n source: \"trawly\",\n type: \"secret\",\n severity: PRIVATE_KEY_RE.test(assignment.key) ? \"critical\" : \"high\",\n ecosystem: \"env\",\n packageName: assignment.key,\n installedVersion: rel,\n summary:\n \"Committed env file contains a secret-like variable. The value is intentionally omitted from this report.\",\n fixedVersions: [],\n affectedPaths: [rel],\n fingerprint: fingerprintFinding({\n source: \"trawly\",\n type: \"secret\",\n id,\n ecosystem: \"env\",\n packageName: assignment.key,\n installedVersion: rel,\n }),\n aliases: [],\n sourceFile,\n line: assignment.line,\n };\n}\n\nfunction unquote(value: string): string {\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n return value.slice(1, -1);\n }\n return value;\n}\n\nfunction normalizePath(path: string): string {\n return path.split(/[\\\\/]/).join(\"/\");\n}\n","import { basename } from \"node:path\";\nimport type { PackageInstance } from \"../types.js\";\nimport { parseNpmPackageLock } from \"./npm-package-lock.js\";\nimport { parsePnpmLock } from \"./pnpm-lock.js\";\nimport { parseYarnLock } from \"./yarn-lock.js\";\n\nexport function parseLockfile(filePath: string): PackageInstance[] {\n const file = basename(filePath);\n if (file === \"package-lock.json\" || file === \"npm-shrinkwrap.json\") {\n return parseNpmPackageLock(filePath);\n }\n if (file === \"pnpm-lock.yaml\") return parsePnpmLock(filePath);\n if (file === \"yarn.lock\") return parseYarnLock(filePath);\n throw new Error(\n `Unsupported lockfile ${filePath}. Supported: package-lock.json, npm-shrinkwrap.json, pnpm-lock.yaml, yarn.lock.`,\n );\n}\n","import { readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { PackageInstance } from \"../types.js\";\n\ninterface NpmLockEntry {\n version?: string;\n resolved?: string;\n integrity?: string;\n hasInstallScript?: boolean;\n dev?: boolean;\n devOptional?: boolean;\n optional?: boolean;\n peer?: boolean;\n link?: boolean;\n // Present on the root (\"\") entry only.\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n optionalDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n}\n\ninterface NpmLockfile {\n name?: string;\n lockfileVersion?: number;\n packages?: Record<string, NpmLockEntry>;\n}\n\n/**\n * Parse an npm `package-lock.json` (v2 or v3) and return one\n * PackageInstance per node in the `packages` map.\n *\n * The empty-string key represents the root project and is skipped.\n */\nexport function parseNpmPackageLock(filePath: string): PackageInstance[] {\n const absolute = resolve(filePath);\n const raw = readFileSync(absolute, \"utf8\");\n let parsed: NpmLockfile;\n try {\n parsed = JSON.parse(raw) as NpmLockfile;\n } catch (err) {\n throw new Error(\n `Failed to parse ${absolute}: ${(err as Error).message}`,\n );\n }\n\n if (parsed.lockfileVersion !== 2 && parsed.lockfileVersion !== 3) {\n throw new Error(\n `Unsupported npm lockfileVersion ${String(\n parsed.lockfileVersion,\n )} in ${absolute}. Only v2 and v3 are supported.`,\n );\n }\n\n const packages = parsed.packages;\n if (!packages || typeof packages !== \"object\") {\n throw new Error(\n `Lockfile ${absolute} has no \"packages\" map; cannot extract installed versions.`,\n );\n }\n\n const directDeps = collectDirectDependencyNames(packages[\"\"] ?? {});\n const instances: PackageInstance[] = [];\n\n for (const [path, entry] of Object.entries(packages)) {\n if (path === \"\") continue;\n if (entry.link) continue; // workspace symlink, not a real install\n const name = packagePathToName(path);\n if (!name) continue;\n if (!entry.version) continue;\n\n instances.push({\n name,\n version: entry.version,\n ecosystem: \"npm\",\n path,\n direct: directDeps.has(name) && isTopLevelInstance(path),\n dev: Boolean(entry.dev || entry.devOptional),\n optional: Boolean(entry.optional || entry.devOptional),\n inputKind: \"lockfile\",\n sourceFile: absolute,\n line: lineOf(raw, JSON.stringify(path)),\n manager: \"npm\",\n resolved: entry.resolved,\n integrity: entry.integrity,\n registry: registryFromResolved(entry.resolved),\n hasInstallScript: Boolean(entry.hasInstallScript),\n });\n }\n\n return instances;\n}\n\nfunction collectDirectDependencyNames(rootEntry: NpmLockEntry): Set<string> {\n const names = new Set<string>();\n for (const key of [\n \"dependencies\",\n \"devDependencies\",\n \"optionalDependencies\",\n \"peerDependencies\",\n ] as const) {\n const block = rootEntry[key];\n if (!block) continue;\n for (const name of Object.keys(block)) names.add(name);\n }\n return names;\n}\n\n/**\n * \"node_modules/foo\" -> \"foo\"\n * \"node_modules/@scope/bar\" -> \"@scope/bar\"\n * \"node_modules/foo/node_modules/bar\" -> \"bar\"\n */\nexport function packagePathToName(path: string): string | null {\n const marker = \"node_modules/\";\n const idx = path.lastIndexOf(marker);\n if (idx === -1) return null;\n const tail = path.slice(idx + marker.length);\n if (!tail) return null;\n if (tail.startsWith(\"@\")) {\n const firstSlash = tail.indexOf(\"/\");\n if (firstSlash === -1) return null;\n const secondSlash = tail.indexOf(\"/\", firstSlash + 1);\n return secondSlash === -1 ? tail : tail.slice(0, secondSlash);\n }\n const next = tail.indexOf(\"/\");\n return next === -1 ? tail : tail.slice(0, next);\n}\n\n/** A direct-install path has exactly one `node_modules/` segment. */\nfunction isTopLevelInstance(path: string): boolean {\n const first = path.indexOf(\"node_modules/\");\n if (first === -1) return false;\n return path.indexOf(\"node_modules/\", first + 1) === -1;\n}\n\nfunction registryFromResolved(resolved: string | undefined): string | undefined {\n if (!resolved) return undefined;\n try {\n const url = new URL(resolved);\n return `${url.protocol}//${url.host}`;\n } catch {\n return undefined;\n }\n}\n\nfunction lineOf(raw: string, needle: string): number | undefined {\n const idx = raw.indexOf(needle);\n if (idx === -1) return undefined;\n return raw.slice(0, idx).split(/\\r?\\n/).length;\n}\n","import { readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { parse as parseYaml } from \"yaml\";\nimport type { PackageInstance } from \"../types.js\";\nimport { readPackageJsonInfoFrom } from \"./package-json.js\";\n\ninterface PnpmDepRef {\n version?: string;\n specifier?: string;\n}\n\ninterface PnpmPackageEntry {\n resolution?: { integrity?: string; tarball?: string };\n dev?: boolean;\n optional?: boolean;\n requiresBuild?: boolean;\n}\n\ninterface PnpmLockfile {\n lockfileVersion?: string | number;\n importers?: Record<\n string,\n {\n dependencies?: Record<string, string | PnpmDepRef>;\n devDependencies?: Record<string, string | PnpmDepRef>;\n optionalDependencies?: Record<string, string | PnpmDepRef>;\n }\n >;\n packages?: Record<string, PnpmPackageEntry>;\n dependencies?: Record<string, string | PnpmDepRef>;\n devDependencies?: Record<string, string | PnpmDepRef>;\n optionalDependencies?: Record<string, string | PnpmDepRef>;\n}\n\nconst SUPPORTED_MAJOR_VERSIONS = new Set([6, 9]);\n\nexport function parsePnpmLock(filePath: string): PackageInstance[] {\n const absolute = resolve(filePath);\n const raw = readFileSync(absolute, \"utf8\");\n let parsed: PnpmLockfile;\n try {\n parsed = parseYaml(raw) as PnpmLockfile;\n } catch (err) {\n throw new Error(\n `Failed to parse ${absolute}: ${(err as Error).message}`,\n );\n }\n\n const major = parseLockfileMajor(parsed.lockfileVersion);\n if (major === null || !SUPPORTED_MAJOR_VERSIONS.has(major)) {\n throw new Error(\n `Unsupported pnpm lockfileVersion ${String(parsed.lockfileVersion)} in ${absolute}. Supported: 6.x, 9.x.`,\n );\n }\n\n if (!parsed.packages || typeof parsed.packages !== \"object\") {\n throw new Error(`Lockfile ${absolute} has no \"packages\" map.`);\n }\n\n const rootInfo = readPackageJsonInfoFrom(absolute);\n const importerDirect = collectImporterDirect(parsed);\n const directDeps =\n importerDirect.all.size > 0 ? importerDirect.all : rootInfo.allDirect;\n const devDeps =\n importerDirect.dev.size > 0 ? importerDirect.dev : rootInfo.devDependencies;\n const optionalDeps =\n importerDirect.optional.size > 0\n ? importerDirect.optional\n : rootInfo.optionalDependencies;\n\n const instances: PackageInstance[] = [];\n for (const [key, entry] of Object.entries(parsed.packages)) {\n const parsedKey = parsePnpmPackageKey(key);\n if (!parsedKey) continue;\n const direct = directDeps.has(parsedKey.name);\n instances.push({\n name: parsedKey.name,\n version: parsedKey.version,\n ecosystem: \"npm\",\n path: key,\n direct,\n dev: direct ? devDeps.has(parsedKey.name) : Boolean(entry.dev),\n optional: direct\n ? optionalDeps.has(parsedKey.name)\n : Boolean(entry.optional),\n inputKind: \"lockfile\",\n sourceFile: absolute,\n line: lineOf(raw, key),\n manager: \"pnpm\",\n resolved: entry.resolution?.tarball,\n integrity: entry.resolution?.integrity,\n registry: registryFromResolved(entry.resolution?.tarball),\n hasInstallScript: Boolean(entry.requiresBuild),\n });\n }\n return instances;\n}\n\nexport function parsePnpmPackageKey(\n key: string,\n): { name: string; version: string } | null {\n let normalized = key.replace(/^\\/+/, \"\");\n const peerStart = normalized.indexOf(\"(\");\n if (peerStart !== -1) normalized = normalized.slice(0, peerStart);\n normalized = normalized.split(\"_\")[0] ?? normalized;\n const at = normalized.lastIndexOf(\"@\");\n if (at <= 0) return null;\n const name = normalized.slice(0, at);\n const version = normalized.slice(at + 1);\n if (!name || !version) return null;\n return { name, version };\n}\n\nfunction collectImporterDirect(lock: PnpmLockfile): {\n all: Set<string>;\n dev: Set<string>;\n optional: Set<string>;\n} {\n const all = new Set<string>();\n const dev = new Set<string>();\n const optional = new Set<string>();\n const importers = lock.importers ?? {\n \".\": {\n dependencies: lock.dependencies,\n devDependencies: lock.devDependencies,\n optionalDependencies: lock.optionalDependencies,\n },\n };\n for (const importer of Object.values(importers)) {\n addKeys(importer.dependencies, all);\n addKeys(importer.devDependencies, all, dev);\n addKeys(importer.optionalDependencies, all, optional);\n }\n return { all, dev, optional };\n}\n\nfunction parseLockfileMajor(value: unknown): number | null {\n if (typeof value === \"number\") return Math.trunc(value);\n if (typeof value === \"string\") {\n const major = Number.parseInt(value, 10);\n return Number.isNaN(major) ? null : major;\n }\n return null;\n}\n\nfunction addKeys(\n value: Record<string, string | PnpmDepRef> | undefined,\n all: Set<string>,\n bucket?: Set<string>,\n): void {\n if (!value) return;\n for (const name of Object.keys(value)) {\n all.add(name);\n bucket?.add(name);\n }\n}\n\nfunction registryFromResolved(resolved: string | undefined): string | undefined {\n if (!resolved) return undefined;\n try {\n const url = new URL(resolved);\n return `${url.protocol}//${url.host}`;\n } catch {\n return undefined;\n }\n}\n\nfunction lineOf(raw: string, needle: string): number | undefined {\n const idx = raw.indexOf(needle);\n if (idx === -1) return undefined;\n return raw.slice(0, idx).split(/\\r?\\n/).length;\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\n\nexport interface PackageJsonInfo {\n dependencies: Set<string>;\n devDependencies: Set<string>;\n optionalDependencies: Set<string>;\n allDirect: Set<string>;\n}\n\nexport function readPackageJsonInfoFrom(filePath: string): PackageJsonInfo {\n return readPackageJsonInfo(dirname(filePath));\n}\n\nexport function readPackageJsonInfo(cwd: string): PackageJsonInfo {\n const info: PackageJsonInfo = {\n dependencies: new Set(),\n devDependencies: new Set(),\n optionalDependencies: new Set(),\n allDirect: new Set(),\n };\n const path = join(cwd, \"package.json\");\n if (!existsSync(path)) return info;\n try {\n const raw = JSON.parse(readFileSync(path, \"utf8\")) as Record<string, unknown>;\n collect(raw.dependencies, info.dependencies, info.allDirect);\n collect(raw.devDependencies, info.devDependencies, info.allDirect);\n collect(raw.optionalDependencies, info.optionalDependencies, info.allDirect);\n collect(raw.peerDependencies, info.dependencies, info.allDirect);\n } catch {\n return info;\n }\n return info;\n}\n\nfunction collect(\n value: unknown,\n target: Set<string>,\n allDirect: Set<string>,\n): void {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return;\n for (const name of Object.keys(value)) {\n target.add(name);\n allDirect.add(name);\n }\n}\n","import { readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { parse as parseYaml } from \"yaml\";\nimport * as yarnClassicModule from \"@yarnpkg/lockfile\";\nimport type { PackageInstance } from \"../types.js\";\nimport { readPackageJsonInfoFrom } from \"./package-json.js\";\n\nconst yarnClassic = (\n \"parse\" in yarnClassicModule\n ? yarnClassicModule\n : (yarnClassicModule as { default: typeof yarnClassicModule }).default\n) as { parse(input: string): { type: string; object: Record<string, unknown> } };\n\ninterface YarnClassicEntry {\n version?: string;\n resolved?: string;\n integrity?: string;\n optionalDependencies?: Record<string, string>;\n}\n\ninterface YarnBerryEntry {\n version?: string;\n resolution?: string;\n checksum?: string;\n languageName?: string;\n linkType?: string;\n}\n\nconst LOCAL_YARN_PROTOCOLS = [\"workspace:\", \"patch:\", \"portal:\", \"file:\"];\n\nexport interface ParsedYarnClassicEntry {\n specs: string[];\n fields: Record<string, string>;\n}\n\nexport function parseYarnLock(filePath: string): PackageInstance[] {\n const absolute = resolve(filePath);\n const raw = readFileSync(absolute, \"utf8\");\n return isBerryLock(raw)\n ? parseYarnBerryLock(absolute, raw)\n : parseYarnClassicLock(absolute, raw);\n}\n\nexport function parseYarnClassicLock(\n absolute: string,\n raw: string,\n): PackageInstance[] {\n const parsed = yarnClassic.parse(raw);\n if (parsed.type === \"conflict\") {\n throw new Error(`Yarn lockfile ${absolute} contains merge conflicts.`);\n }\n const rootInfo = readPackageJsonInfoFrom(absolute);\n const instances: PackageInstance[] = [];\n for (const [descriptor, value] of Object.entries(parsed.object)) {\n if (!isRecord(value)) continue;\n const entry = value as YarnClassicEntry;\n if (!entry.version) continue;\n const name = parseYarnDescriptorName(descriptor);\n if (!name) continue;\n const direct = rootInfo.allDirect.has(name);\n instances.push({\n name,\n version: entry.version,\n ecosystem: \"npm\",\n path: descriptor,\n direct,\n dev: direct ? rootInfo.devDependencies.has(name) : false,\n optional: direct ? rootInfo.optionalDependencies.has(name) : false,\n inputKind: \"lockfile\",\n sourceFile: absolute,\n line: lineOf(raw, descriptor),\n manager: \"yarn\",\n resolved: entry.resolved,\n integrity: entry.integrity,\n registry: registryFromResolved(entry.resolved),\n hasInstallScript: false,\n });\n }\n return dedupeInstances(instances);\n}\n\nexport function parseYarnBerryLock(\n absolute: string,\n raw: string,\n): PackageInstance[] {\n let parsed: Record<string, unknown>;\n try {\n parsed = parseYaml(raw) as Record<string, unknown>;\n } catch (err) {\n throw new Error(\n `Failed to parse ${absolute}: ${(err as Error).message}`,\n );\n }\n const rootInfo = readPackageJsonInfoFrom(absolute);\n const instances: PackageInstance[] = [];\n for (const [descriptor, value] of Object.entries(parsed)) {\n if (descriptor === \"__metadata\" || !isRecord(value)) continue;\n const entry = value as YarnBerryEntry;\n if (!entry.version) continue;\n const resolution = entry.resolution ?? descriptor;\n if (hasLocalYarnProtocol(resolution) || hasLocalYarnProtocol(descriptor)) {\n continue;\n }\n const name =\n parseYarnDescriptorName(resolution) ?? parseYarnDescriptorName(descriptor);\n if (!name) continue;\n const direct = rootInfo.allDirect.has(name);\n instances.push({\n name,\n version: entry.version,\n ecosystem: \"npm\",\n path: descriptor,\n direct,\n dev: direct ? rootInfo.devDependencies.has(name) : false,\n optional: direct ? rootInfo.optionalDependencies.has(name) : false,\n inputKind: \"lockfile\",\n sourceFile: absolute,\n line: lineOf(raw, descriptor),\n manager: \"yarn\",\n integrity: entry.checksum,\n hasInstallScript: false,\n });\n }\n return dedupeInstances(instances);\n}\n\nfunction hasLocalYarnProtocol(value: string): boolean {\n const normalized = value.trim().replace(/^\"|\"$/g, \"\");\n return LOCAL_YARN_PROTOCOLS.some(\n (protocol) =>\n normalized.startsWith(protocol) || normalized.includes(`@${protocol}`),\n );\n}\n\nexport function parseClassicEntries(raw: string): ParsedYarnClassicEntry[] {\n const entries: ParsedYarnClassicEntry[] = [];\n let current: ParsedYarnClassicEntry | null = null;\n\n for (const line of raw.split(/\\r?\\n/)) {\n if (line === \"\" || line.trimStart().startsWith(\"#\")) continue;\n if (!/^\\s/.test(line)) {\n if (current) entries.push(current);\n current = {\n specs: splitClassicSpecs(line.replace(/:\\s*$/, \"\")),\n fields: {},\n };\n continue;\n }\n if (!current) continue;\n const indent = line.match(/^ +/)?.[0].length ?? 0;\n if (indent !== 2) continue;\n const trimmed = line.trim();\n const match =\n /^([^\\s\"]+)\\s+\"((?:[^\"\\\\]|\\\\.)*)\"$/.exec(trimmed) ??\n /^([^\\s\"]+)\\s+(\\S+)$/.exec(trimmed);\n if (!match) continue;\n current.fields[match[1]!] = match[2]!;\n }\n\n if (current) entries.push(current);\n return entries;\n}\n\nexport function parseYarnDescriptorName(descriptor: string): string | null {\n const first = descriptor.split(\",\")[0]?.trim().replace(/^\"|\"$/g, \"\");\n if (!first) return null;\n for (const marker of [\"@npm:\", \"@patch:\", \"@workspace:\", \"@portal:\", \"@file:\"]) {\n const idx = first.lastIndexOf(marker);\n if (idx > 0) return first.slice(0, idx);\n }\n if (first.startsWith(\"@\")) {\n const slash = first.indexOf(\"/\");\n if (slash === -1) return null;\n const at = first.indexOf(\"@\", slash + 1);\n return at === -1 ? first : first.slice(0, at);\n }\n const at = first.indexOf(\"@\");\n return at === -1 ? first : first.slice(0, at);\n}\n\nexport function parseYarnSpec(spec: string): { name: string; selector: string } {\n const normalized = spec.trim().replace(/^\"|\"$/g, \"\");\n const startSearch = normalized.startsWith(\"@\") ? 1 : 0;\n const at = normalized.indexOf(\"@\", startSearch);\n if (at <= 0) return { name: normalized, selector: \"\" };\n let selector = normalized.slice(at + 1);\n if (selector.startsWith(\"npm:\")) selector = selector.slice(4);\n return { name: normalized.slice(0, at), selector };\n}\n\nfunction splitClassicSpecs(header: string): string[] {\n const specs: string[] = [];\n let current = \"\";\n let quoted = false;\n for (const char of header) {\n if (char === '\"') {\n quoted = !quoted;\n continue;\n }\n if (char === \",\" && !quoted) {\n const spec = current.trim();\n if (spec) specs.push(spec);\n current = \"\";\n continue;\n }\n current += char;\n }\n const tail = current.trim();\n if (tail) specs.push(tail);\n return specs;\n}\n\nfunction isBerryLock(raw: string): boolean {\n return raw.includes(\"__metadata:\") || raw.includes(\"cacheKey:\");\n}\n\nfunction dedupeInstances(instances: PackageInstance[]): PackageInstance[] {\n const seen = new Set<string>();\n const out: PackageInstance[] = [];\n for (const instance of instances) {\n const key = `${instance.name}@${instance.version}`;\n if (seen.has(key)) continue;\n seen.add(key);\n out.push(instance);\n }\n return out;\n}\n\nfunction registryFromResolved(resolved: string | undefined): string | undefined {\n if (!resolved) return undefined;\n try {\n const url = new URL(resolved);\n return `${url.protocol}//${url.host}`;\n } catch {\n return undefined;\n }\n}\n\nfunction lineOf(raw: string, needle: string): number | undefined {\n const idx = raw.indexOf(needle);\n if (idx === -1) return undefined;\n return raw.slice(0, idx).split(/\\r?\\n/).length;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import { readFileSync } from \"node:fs\";\nimport { basename, resolve } from \"node:path\";\nimport { XMLParser } from \"fast-xml-parser\";\nimport { PackageURL } from \"packageurl-js\";\nimport type { Ecosystem, PackageInstance } from \"../types.js\";\n\ninterface PurlPackage {\n name: string;\n version: string;\n ecosystem: Ecosystem;\n purl: string;\n}\n\nexport function parseSbom(filePath: string): PackageInstance[] {\n const absolute = resolve(filePath);\n const raw = readFileSync(absolute, \"utf8\");\n const trimmed = raw.trimStart();\n if (trimmed.startsWith(\"{\")) return parseJsonSbom(absolute, raw);\n if (trimmed.startsWith(\"<\")) return parseCycloneDxXml(absolute, raw);\n return parseSpdxTagValue(absolute, raw);\n}\n\nfunction parseJsonSbom(absolute: string, raw: string): PackageInstance[] {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw) as unknown;\n } catch (err) {\n throw new Error(\n `Failed to parse ${absolute}: ${(err as Error).message}`,\n );\n }\n if (!isRecord(parsed)) {\n throw new Error(`SBOM ${absolute} must contain a JSON object.`);\n }\n if (Array.isArray(parsed.components)) {\n return parseCycloneDxJson(absolute, raw, parsed.components);\n }\n if (Array.isArray(parsed.packages)) {\n return parseSpdxJson(absolute, raw, parsed.packages);\n }\n throw new Error(\n `Could not detect SBOM format for ${absolute}; expected CycloneDX or SPDX.`,\n );\n}\n\nfunction parseCycloneDxJson(\n absolute: string,\n raw: string,\n components: unknown[],\n): PackageInstance[] {\n const instances: PackageInstance[] = [];\n for (const component of components) {\n if (!isRecord(component) || typeof component.purl !== \"string\") continue;\n const pkg = parsePurlPackage(component.purl);\n if (!pkg) continue;\n instances.push(sbomPackage(pkg, absolute, raw, component.purl));\n }\n return dedupe(instances);\n}\n\nfunction parseCycloneDxXml(absolute: string, raw: string): PackageInstance[] {\n const parser = new XMLParser({\n ignoreAttributes: false,\n attributeNamePrefix: \"\",\n textNodeName: \"#text\",\n });\n let parsed: unknown;\n try {\n parsed = parser.parse(raw);\n } catch (err) {\n throw new Error(\n `Failed to parse ${absolute}: ${(err as Error).message}`,\n );\n }\n const bom = isRecord(parsed) ? parsed.bom : undefined;\n const components = isRecord(bom) && isRecord(bom.components)\n ? arrayify(bom.components.component)\n : [];\n const instances: PackageInstance[] = [];\n for (const component of components) {\n if (!isRecord(component) || typeof component.purl !== \"string\") continue;\n const pkg = parsePurlPackage(component.purl);\n if (!pkg) continue;\n instances.push(sbomPackage(pkg, absolute, raw, component.purl));\n }\n return dedupe(instances);\n}\n\nfunction parseSpdxJson(\n absolute: string,\n raw: string,\n packages: unknown[],\n): PackageInstance[] {\n const instances: PackageInstance[] = [];\n for (const pkgRecord of packages) {\n if (!isRecord(pkgRecord)) continue;\n const externalRefs = Array.isArray(pkgRecord.externalRefs)\n ? pkgRecord.externalRefs\n : [];\n for (const ref of externalRefs) {\n if (!isRecord(ref)) continue;\n const locator = ref.referenceLocator;\n const type = String(ref.referenceType ?? \"\").toLowerCase();\n if (type !== \"purl\" || typeof locator !== \"string\") continue;\n const pkg = parsePurlPackage(locator);\n if (!pkg) continue;\n instances.push(sbomPackage(pkg, absolute, raw, locator));\n }\n }\n return dedupe(instances);\n}\n\nfunction parseSpdxTagValue(absolute: string, raw: string): PackageInstance[] {\n if (!raw.includes(\"SPDXVersion:\")) {\n throw new Error(\n `Could not detect SBOM format for ${absolute}; expected CycloneDX or SPDX.`,\n );\n }\n const instances: PackageInstance[] = [];\n for (const line of raw.split(/\\r?\\n/)) {\n const match = line.match(/^ExternalRef:\\s+PACKAGE-MANAGER\\s+purl\\s+(\\S+)/);\n if (!match?.[1]) continue;\n const pkg = parsePurlPackage(match[1]);\n if (!pkg) continue;\n instances.push(sbomPackage(pkg, absolute, raw, match[1]));\n }\n return dedupe(instances);\n}\n\nexport function parsePurlPackage(purl: string): PurlPackage | null {\n let parsed: PackageURL;\n try {\n parsed = PackageURL.fromString(purl);\n } catch {\n return null;\n }\n if (!parsed.version) return null;\n const ecosystem = purlTypeToOsvEcosystem(parsed.type);\n if (!ecosystem) return null;\n return {\n name: purlName(parsed),\n version: parsed.version,\n ecosystem,\n purl,\n };\n}\n\nfunction sbomPackage(\n pkg: PurlPackage,\n absolute: string,\n raw: string,\n needle: string,\n): PackageInstance {\n return {\n name: pkg.name,\n version: pkg.version,\n ecosystem: pkg.ecosystem,\n path: `${basename(absolute)}:${pkg.purl}`,\n direct: false,\n dev: false,\n optional: false,\n inputKind: \"sbom\",\n purl: pkg.purl,\n sourceFile: absolute,\n line: lineOf(raw, needle),\n manager: \"sbom\",\n };\n}\n\nfunction purlTypeToOsvEcosystem(type: string): string | null {\n switch (type.toLowerCase()) {\n case \"npm\":\n return \"npm\";\n case \"pypi\":\n return \"PyPI\";\n case \"maven\":\n return \"Maven\";\n case \"gem\":\n return \"RubyGems\";\n case \"nuget\":\n return \"NuGet\";\n case \"golang\":\n case \"go\":\n return \"Go\";\n case \"cargo\":\n return \"crates.io\";\n case \"composer\":\n return \"Packagist\";\n case \"deb\":\n return \"Debian\";\n case \"apk\":\n return \"Alpine\";\n default:\n return null;\n }\n}\n\nfunction purlName(purl: PackageURL): string {\n if (purl.type.toLowerCase() === \"npm\" && purl.namespace) {\n const scope = purl.namespace.startsWith(\"@\")\n ? purl.namespace\n : `@${purl.namespace}`;\n return `${scope}/${purl.name}`;\n }\n if (purl.type.toLowerCase() === \"maven\" && purl.namespace) {\n return `${purl.namespace}:${purl.name}`;\n }\n return purl.namespace ? `${purl.namespace}/${purl.name}` : purl.name;\n}\n\nfunction dedupe(instances: PackageInstance[]): PackageInstance[] {\n const seen = new Set<string>();\n const out: PackageInstance[] = [];\n for (const instance of instances) {\n const key = instance.purl ?? `${instance.ecosystem}:${instance.name}@${instance.version}`;\n if (seen.has(key)) continue;\n seen.add(key);\n out.push(instance);\n }\n return out;\n}\n\nfunction arrayify(value: unknown): unknown[] {\n if (value === undefined) return [];\n return Array.isArray(value) ? value : [value];\n}\n\nfunction lineOf(raw: string, needle: string): number | undefined {\n const idx = raw.indexOf(needle);\n if (idx === -1) return undefined;\n return raw.slice(0, idx).split(/\\r?\\n/).length;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import type { Finding, IgnoreEntry } from \"./types.js\";\n\nexport interface IgnoreResult {\n active: Finding[];\n ignored: Finding[];\n warnings: string[];\n}\n\nexport function applyIgnores(\n findings: Finding[],\n ignores: IgnoreEntry[],\n now: Date,\n): IgnoreResult {\n if (ignores.length === 0) return { active: findings, ignored: [], warnings: [] };\n\n const warnings: string[] = [];\n const activeIgnores = ignores.filter((entry) => {\n const expires = new Date(`${entry.expires}T23:59:59.999Z`);\n if (Number.isNaN(expires.getTime()) || expires < now) {\n warnings.push(\n `Ignore for ${entry.id} expired on ${entry.expires} and was not applied.`,\n );\n return false;\n }\n return true;\n });\n\n const active: Finding[] = [];\n const ignored: Finding[] = [];\n for (const finding of findings) {\n const matched = activeIgnores.some((entry) => matchesIgnore(finding, entry));\n if (matched) {\n ignored.push({ ...finding, ignored: true });\n } else {\n active.push(finding);\n }\n }\n return { active, ignored, warnings };\n}\n\nfunction matchesIgnore(finding: Finding, entry: IgnoreEntry): boolean {\n const ids = new Set([finding.id, ...finding.aliases]);\n if (!ids.has(entry.id)) return false;\n if (entry.package && entry.package !== finding.packageName) return false;\n if (entry.ecosystem && entry.ecosystem !== finding.ecosystem) return false;\n if (entry.version && entry.version !== finding.installedVersion) return false;\n return true;\n}\n","import type { FailOnLevel, PolicyPresetName } from \"./types.js\";\n\nexport interface PolicyPreset {\n failOn: FailOnLevel;\n risk: boolean;\n env: boolean;\n includeDev: boolean;\n}\n\nexport const POLICY_PRESETS: Record<PolicyPresetName, PolicyPreset> = {\n ci: {\n failOn: \"high\",\n risk: true,\n env: false,\n includeDev: true,\n },\n strict: {\n failOn: \"moderate\",\n risk: true,\n env: true,\n includeDev: true,\n },\n library: {\n failOn: \"moderate\",\n risk: true,\n env: false,\n includeDev: false,\n },\n app: {\n failOn: \"high\",\n risk: true,\n env: true,\n includeDev: true,\n },\n};\n\nexport function resolvePolicy(\n requested: PolicyPresetName | undefined,\n configured: PolicyPresetName | undefined,\n): PolicyPreset | undefined {\n const name = requested ?? configured;\n return name ? POLICY_PRESETS[name] : undefined;\n}\n\n","import { fingerprintFinding } from \"./fingerprint.js\";\nimport type { Finding, PackageInstance } from \"./types.js\";\n\nconst REGISTRY_URL = \"https://registry.npmjs.org\";\nconst REGISTRY_ENV = \"TRAWLY_NPM_REGISTRY_URL\";\nconst REQUEST_TIMEOUT_MS = 15_000;\nconst NEW_VERSION_DAYS = 30;\nconst NEW_PACKAGE_DAYS = 90;\nconst PACKUMENT_CONCURRENCY = 8;\nconst PACKUMENT_MAX_RETRIES = 3;\nconst PACKUMENT_BACKOFF_MS = 250;\n\nexport interface RiskOptions {\n enabled: boolean;\n allowedRegistries: string[];\n fetchImpl?: typeof fetch;\n now: Date;\n}\n\ninterface Packument {\n time?: Record<string, string>;\n versions?: Record<string, { deprecated?: string }>;\n}\n\nexport interface RiskResult {\n findings: Finding[];\n warnings: string[];\n}\n\nexport async function collectRiskSignals(\n packages: PackageInstance[],\n options: RiskOptions,\n): Promise<RiskResult> {\n if (!options.enabled) return { findings: [], warnings: [] };\n\n const findings: Finding[] = [];\n const warnings: string[] = [];\n for (const pkg of packages) {\n if (pkg.hasInstallScript) {\n findings.push(riskFinding(pkg, {\n id: \"TRAWLY-INSTALL-SCRIPT\",\n severity: \"moderate\",\n summary: `${pkg.name}@${pkg.version} declares install-time scripts or requires a build step.`,\n }));\n }\n\n const registry = normalizeRegistry(pkg.registry);\n if (registry && !isAllowedRegistry(registry, options.allowedRegistries)) {\n findings.push(riskFinding(pkg, {\n id: \"TRAWLY-UNEXPECTED-REGISTRY\",\n severity: \"moderate\",\n summary: `${pkg.name}@${pkg.version} was resolved from unexpected registry ${registry}.`,\n }));\n }\n }\n\n const npmPackageGroups = groupNpmPackages(packages);\n const fetchImpl = options.fetchImpl ?? fetch;\n // One packument per package name covers every installed version, so fetch\n // by name and reuse across version groups.\n const groupsByName = new Map<string, PackageInstance[][]>();\n for (const group of npmPackageGroups) {\n const name = group[0]?.name;\n if (!name) continue;\n const list = groupsByName.get(name) ?? [];\n list.push(group);\n groupsByName.set(name, list);\n }\n\n await mapWithConcurrency(\n [...groupsByName.entries()],\n PACKUMENT_CONCURRENCY,\n async ([name, groups]) => {\n let packument: Packument;\n try {\n packument = await fetchPackument(fetchImpl, name);\n } catch (err) {\n warnings.push(\n `Could not fetch npm publish metadata for ${name}: ${(err as Error).message}`,\n );\n return;\n }\n const createdAt = parseDate(packument.time?.created);\n const isNewPackage =\n !!createdAt && daysBetween(createdAt, options.now) < NEW_PACKAGE_DAYS;\n\n for (const group of groups) {\n const representative = group[0];\n if (!representative) continue;\n const versionAt = parseDate(packument.time?.[representative.version]);\n const deprecated = packument.versions?.[representative.version]?.deprecated;\n if (isNewPackage) {\n for (const pkg of group) {\n findings.push(\n riskFinding(pkg, {\n id: \"TRAWLY-NEW-PACKAGE\",\n severity: \"moderate\",\n summary: `${pkg.name} was first published less than ${NEW_PACKAGE_DAYS} days ago.`,\n }),\n );\n }\n }\n if (deprecated) {\n for (const pkg of group) {\n findings.push(\n riskFinding(pkg, {\n id: \"TRAWLY-DEPRECATED-PACKAGE\",\n severity: \"moderate\",\n summary: `${pkg.name}@${pkg.version} is deprecated: ${deprecated}`,\n }),\n );\n }\n }\n if (versionAt && daysBetween(versionAt, options.now) < NEW_VERSION_DAYS) {\n for (const pkg of group) {\n findings.push(\n riskFinding(pkg, {\n id: \"TRAWLY-NEW-VERSION\",\n severity: \"low\",\n summary: `${pkg.name}@${pkg.version} was published less than ${NEW_VERSION_DAYS} days ago.`,\n }),\n );\n }\n }\n }\n },\n );\n\n return { findings, warnings };\n}\n\nfunction riskFinding(\n pkg: PackageInstance,\n input: { id: string; severity: Finding[\"severity\"]; summary: string },\n): Finding {\n return {\n id: input.id,\n source: \"trawly\",\n type: \"risk-signal\",\n severity: input.severity,\n ecosystem: pkg.ecosystem,\n packageName: pkg.name,\n installedVersion: pkg.version,\n summary: input.summary,\n fixedVersions: [],\n affectedPaths: [pkg.path],\n fingerprint: fingerprintFinding({\n source: \"trawly\",\n type: \"risk-signal\",\n id: input.id,\n ecosystem: pkg.ecosystem,\n packageName: pkg.name,\n installedVersion: pkg.version,\n }),\n aliases: [],\n sourceFile: pkg.sourceFile,\n line: pkg.line,\n };\n}\n\nfunction groupNpmPackages(packages: PackageInstance[]): PackageInstance[][] {\n const groups = new Map<string, PackageInstance[]>();\n for (const pkg of packages) {\n if (pkg.ecosystem !== \"npm\") continue;\n const key = `${pkg.name}@${pkg.version}`;\n const group = groups.get(key) ?? [];\n group.push(pkg);\n groups.set(key, group);\n }\n return [...groups.values()];\n}\n\nasync function fetchPackument(\n fetchImpl: typeof fetch,\n name: string,\n): Promise<Packument> {\n const registry = (process.env[REGISTRY_ENV] ?? REGISTRY_URL).replace(/\\/+$/, \"\");\n const url = `${registry}/${encodePackageName(name)}`;\n let lastErr: unknown;\n\n for (let attempt = 0; attempt <= PACKUMENT_MAX_RETRIES; attempt++) {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n try {\n const res = await fetchImpl(url, {\n signal: controller.signal,\n headers: { accept: \"application/json\" },\n });\n if (res.ok) return (await res.json()) as Packument;\n\n const err = new RegistryHttpError(\n `registry ${res.status}: ${res.statusText}`,\n res.status,\n retryAfterMs(res.headers),\n );\n if (!isRetryableRegistryError(err) || attempt === PACKUMENT_MAX_RETRIES) {\n throw err;\n }\n lastErr = err;\n await sleep(retryDelayMs(err, attempt));\n } catch (err) {\n if (err instanceof RegistryHttpError) throw err;\n lastErr = err;\n if (attempt === PACKUMENT_MAX_RETRIES) break;\n await sleep(retryDelayMs(undefined, attempt));\n } finally {\n clearTimeout(timer);\n }\n }\n throw lastErr;\n}\n\nasync function mapWithConcurrency<T>(\n items: T[],\n concurrency: number,\n worker: (item: T) => Promise<void>,\n): Promise<void> {\n let next = 0;\n const workers = Array.from(\n { length: Math.min(concurrency, items.length) },\n async () => {\n while (next < items.length) {\n const item = items[next++];\n if (item !== undefined) await worker(item);\n }\n },\n );\n await Promise.all(workers);\n}\n\nclass RegistryHttpError extends Error {\n constructor(\n message: string,\n public readonly status: number,\n public readonly retryAfterMs?: number,\n ) {\n super(message);\n }\n}\n\nfunction isRetryableRegistryError(err: RegistryHttpError): boolean {\n return err.status === 429 || err.status >= 500;\n}\n\nfunction retryDelayMs(\n err: RegistryHttpError | undefined,\n attempt: number,\n): number {\n if (err?.retryAfterMs !== undefined) return err.retryAfterMs;\n const base = PACKUMENT_BACKOFF_MS * 2 ** attempt;\n return base + Math.floor(Math.random() * Math.min(base, 100));\n}\n\nfunction retryAfterMs(headers: Headers): number | undefined {\n const value = headers.get(\"retry-after\");\n if (!value) return undefined;\n const seconds = Number(value);\n if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1000;\n const date = Date.parse(value);\n if (Number.isNaN(date)) return undefined;\n return Math.max(0, date - Date.now());\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction isAllowedRegistry(registry: string, allowed: string[]): boolean {\n const normalizedAllowed = allowed.map(normalizeRegistry).filter(isString);\n return normalizedAllowed.includes(registry);\n}\n\nfunction normalizeRegistry(value: string | undefined): string | undefined {\n if (!value) return undefined;\n try {\n const url = new URL(value);\n return `${url.protocol}//${url.host}`;\n } catch {\n return value.replace(/\\/+$/, \"\");\n }\n}\n\nfunction encodePackageName(name: string): string {\n if (name.startsWith(\"@\")) {\n const slash = name.indexOf(\"/\");\n if (slash !== -1) {\n return `${encodeURIComponent(name.slice(0, slash))}%2F${encodeURIComponent(name.slice(slash + 1))}`;\n }\n }\n return encodeURIComponent(name);\n}\n\nfunction parseDate(value: string | undefined): Date | undefined {\n if (!value) return undefined;\n const date = new Date(value);\n return Number.isNaN(date.getTime()) ? undefined : date;\n}\n\nfunction daysBetween(a: Date, b: Date): number {\n return (b.getTime() - a.getTime()) / 86_400_000;\n}\n\nfunction isString(value: string | undefined): value is string {\n return typeof value === \"string\";\n}\n","export type Severity = \"critical\" | \"high\" | \"moderate\" | \"low\" | \"unknown\";\n\nexport type Ecosystem = string;\n\nexport type FindingType =\n | \"vulnerability\"\n | \"malware\"\n | \"secret\"\n | \"risk-signal\"\n | \"integrity\";\n\nexport type FindingSource = \"osv\" | \"trawly\";\n\nexport type InputKind = \"lockfile\" | \"sbom\" | \"adhoc\";\n\nexport const SEVERITY_RANK: Record<Severity, number> = {\n critical: 4,\n high: 3,\n moderate: 2,\n low: 1,\n unknown: 0,\n};\n\nexport interface PackageInstance {\n name: string;\n version: string;\n ecosystem: Ecosystem;\n /** Path within the source manifest, e.g. \"node_modules/foo\" or an SBOM ref. */\n path: string;\n direct: boolean;\n dev: boolean;\n optional: boolean;\n inputKind?: InputKind;\n purl?: string;\n sourceFile?: string;\n line?: number;\n manager?: \"npm\" | \"pnpm\" | \"yarn\" | \"sbom\" | string;\n resolved?: string;\n integrity?: string;\n registry?: string;\n hasInstallScript?: boolean;\n publishedAt?: string;\n packagePublishedAt?: string;\n}\n\nexport interface Finding {\n id: string;\n source: FindingSource;\n type: FindingType;\n severity: Severity;\n ecosystem: Ecosystem;\n packageName: string;\n installedVersion: string;\n summary: string;\n url?: string;\n fixedVersions: string[];\n affectedPaths: string[];\n fingerprint: string;\n aliases: string[];\n sourceFile?: string;\n line?: number;\n ignored?: boolean;\n baseline?: \"new\" | \"existing\";\n}\n\nexport interface ScanError {\n message: string;\n cause?: string;\n}\n\nexport interface ScanResult {\n scannedAt: string;\n packagesScanned: number;\n findings: Finding[];\n ignoredFindings: Finding[];\n summary: Record<Severity, number>;\n errors: ScanError[];\n warnings: string[];\n baseline?: BaselineResult;\n}\n\nexport interface IgnoreEntry {\n id: string;\n package?: string;\n ecosystem?: string;\n version?: string;\n expires: string;\n reason: string;\n}\n\nexport interface TrawlyConfig {\n failOn?: FailOnLevel;\n policy?: PolicyPresetName;\n risk?: boolean;\n env?: boolean;\n allowedRegistries?: string[];\n ignore: IgnoreEntry[];\n}\n\nexport interface BaselineFile {\n version: 1;\n generatedAt: string;\n findings: string[];\n}\n\nexport interface BaselineResult {\n path?: string;\n loaded: boolean;\n written?: string;\n total: number;\n existing: number;\n new: number;\n}\n\nexport interface ScanProjectOptions {\n cwd?: string;\n lockfile?: string | string[];\n sbom?: string | string[];\n config?: string;\n policy?: PolicyPresetName;\n baseline?: string;\n writeBaseline?: string;\n risk?: boolean;\n env?: boolean;\n allowedRegistries?: string[];\n includeDev?: boolean;\n prodOnly?: boolean;\n fetchImpl?: typeof fetch;\n now?: Date;\n}\n\nexport interface ScanLockfileOptions {\n lockfilePath: string | string[];\n sbom?: string | string[];\n cwd?: string;\n config?: string;\n policy?: PolicyPresetName;\n baseline?: string;\n writeBaseline?: string;\n risk?: boolean;\n env?: boolean;\n allowedRegistries?: string[];\n includeDev?: boolean;\n prodOnly?: boolean;\n fetchImpl?: typeof fetch;\n now?: Date;\n}\n\nexport type FailOnLevel = Severity | \"none\";\n\nexport type PolicyPresetName = \"ci\" | \"strict\" | \"library\" | \"app\";\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport type PackageManager = \"npm\" | \"pnpm\" | \"yarn\" | \"bun\";\n\nexport interface PmCommand {\n /** Binary to spawn, e.g. \"pnpm\". */\n bin: string;\n /** Argv to spawn it with. */\n args: string[];\n}\n\nexport interface DetectOptions {\n /** Override detection. */\n override?: PackageManager;\n /** Project directory. Defaults to cwd. */\n cwd?: string;\n}\n\nconst LOCKFILES: Array<{ file: string; pm: PackageManager }> = [\n { file: \"pnpm-lock.yaml\", pm: \"pnpm\" },\n { file: \"yarn.lock\", pm: \"yarn\" },\n { file: \"bun.lockb\", pm: \"bun\" },\n { file: \"bun.lock\", pm: \"bun\" },\n { file: \"package-lock.json\", pm: \"npm\" },\n { file: \"npm-shrinkwrap.json\", pm: \"npm\" },\n];\n\nexport function detectPackageManager(opts: DetectOptions = {}): PackageManager {\n if (opts.override) return opts.override;\n const cwd = opts.cwd ?? process.cwd();\n\n const fromField = readPackageManagerField(cwd);\n if (fromField) return fromField;\n\n for (const { file, pm } of LOCKFILES) {\n if (existsSync(join(cwd, file))) return pm;\n }\n return \"npm\";\n}\n\nfunction readPackageManagerField(cwd: string): PackageManager | undefined {\n const pkgPath = join(cwd, \"package.json\");\n if (!existsSync(pkgPath)) return undefined;\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf8\")) as {\n packageManager?: string;\n };\n if (typeof pkg.packageManager !== \"string\") return undefined;\n const name = pkg.packageManager.split(\"@\")[0];\n if (name === \"npm\" || name === \"pnpm\" || name === \"yarn\" || name === \"bun\") {\n return name;\n }\n } catch {\n // Malformed package.json : fall back to lockfile detection.\n }\n return undefined;\n}\n\n/**\n * Build the argv to add packages with the chosen package manager.\n * `flags` are user-supplied PM flags (e.g. -D, --save-exact) preserved as-is.\n */\nexport function buildAddCommand(\n pm: PackageManager,\n packages: string[],\n flags: string[],\n): PmCommand {\n switch (pm) {\n case \"npm\":\n return { bin: \"npm\", args: [\"install\", ...flags, ...packages] };\n case \"pnpm\":\n return { bin: \"pnpm\", args: [\"add\", ...flags, ...packages] };\n case \"yarn\":\n return { bin: \"yarn\", args: [\"add\", ...flags, ...packages] };\n case \"bun\":\n return { bin: \"bun\", args: [\"add\", ...flags, ...packages] };\n }\n}\n\nexport function buildInstallCommand(\n pm: PackageManager,\n flags: string[],\n): PmCommand {\n return { bin: pm, args: [\"install\", ...flags] };\n}\n\nexport function buildRemoveCommand(\n pm: PackageManager,\n packages: string[],\n flags: string[],\n): PmCommand {\n switch (pm) {\n case \"npm\":\n return { bin: \"npm\", args: [\"uninstall\", ...flags, ...packages] };\n case \"pnpm\":\n return { bin: \"pnpm\", args: [\"remove\", ...flags, ...packages] };\n case \"yarn\":\n return { bin: \"yarn\", args: [\"remove\", ...flags, ...packages] };\n case \"bun\":\n return { bin: \"bun\", args: [\"remove\", ...flags, ...packages] };\n }\n}\n","import { spawn } from \"node:child_process\";\nimport type { PmCommand } from \"./pm-detect.js\";\n\nexport interface RunOptions {\n cwd?: string;\n}\n\n/**\n * Spawn the package manager with stdio inherited so the user sees the live\n * install output. Resolves with the PM's exit code.\n */\nexport function runPackageManager(\n cmd: PmCommand,\n opts: RunOptions = {},\n): Promise<number> {\n return new Promise((resolve, reject) => {\n const child = spawn(cmd.bin, cmd.args, {\n cwd: opts.cwd,\n stdio: \"inherit\",\n shell: process.platform === \"win32\",\n });\n child.on(\"error\", reject);\n child.on(\"close\", (code) => resolve(code ?? 0));\n });\n}\n","export interface ParsedSpec {\n /** Original argv token, preserved so we can hand it back to the package manager. */\n raw: string;\n /** Bare package name, e.g. \"next\" or \"@types/node\". */\n name: string;\n /**\n * Whatever followed the \"@\" separator: an exact version, a semver range,\n * or a dist-tag like \"latest\" / \"next\". Undefined when the user passed only\n * the package name.\n */\n requested?: string;\n /** Specs we cannot meaningfully scan (git, tarball, file, url, alias). */\n unsupported?: UnsupportedReason;\n}\n\nexport type UnsupportedReason =\n | \"git\"\n | \"url\"\n | \"file\"\n | \"alias\"\n | \"workspace\"\n | \"invalid\";\n\nconst URL_PROTOCOLS = [\"http:\", \"https:\", \"git:\", \"git+ssh:\", \"git+https:\", \"git+http:\"];\n\nexport function parseSpec(raw: string): ParsedSpec {\n const trimmed = raw.trim();\n if (trimmed === \"\") {\n return { raw, name: \"\", unsupported: \"invalid\" };\n }\n\n if (trimmed.startsWith(\"file:\")) return { raw, name: trimmed, unsupported: \"file\" };\n if (trimmed.startsWith(\"workspace:\")) {\n return { raw, name: trimmed, unsupported: \"workspace\" };\n }\n if (URL_PROTOCOLS.some((p) => trimmed.startsWith(p))) {\n const reason = trimmed.includes(\"git\") ? \"git\" : \"url\";\n return { raw, name: trimmed, unsupported: reason };\n }\n // npm aliases: \"alias@npm:real-pkg@1.0\". We can't reliably gate these in v1.\n if (/^[^@/].*@npm:/.test(trimmed) || /^@[^/]+\\/[^@]+@npm:/.test(trimmed)) {\n return { raw, name: trimmed, unsupported: \"alias\" };\n }\n\n // Scoped: \"@scope/name\" or \"@scope/name@version\".\n if (trimmed.startsWith(\"@\")) {\n const slash = trimmed.indexOf(\"/\");\n if (slash === -1) return { raw, name: trimmed, unsupported: \"invalid\" };\n const rest = trimmed.slice(slash + 1);\n const at = rest.indexOf(\"@\");\n if (at === -1) {\n return { raw, name: trimmed };\n }\n const subname = rest.slice(0, at);\n const requested = rest.slice(at + 1);\n if (subname === \"\" || requested === \"\") {\n return { raw, name: trimmed, unsupported: \"invalid\" };\n }\n return { raw, name: `${trimmed.slice(0, slash)}/${subname}`, requested };\n }\n\n const at = trimmed.indexOf(\"@\");\n if (at === -1) return { raw, name: trimmed };\n const name = trimmed.slice(0, at);\n const requested = trimmed.slice(at + 1);\n if (name === \"\" || requested === \"\") {\n return { raw, name: trimmed, unsupported: \"invalid\" };\n }\n return { raw, name, requested };\n}\n\n/**\n * Splits an argv list into recognized package specs and forwarded flags.\n * Anything starting with \"-\" is treated as a flag and preserved untouched.\n */\nexport function partitionArgs(args: string[]): {\n specs: ParsedSpec[];\n flags: string[];\n} {\n const specs: ParsedSpec[] = [];\n const flags: string[] = [];\n for (const arg of args) {\n if (arg.startsWith(\"-\")) {\n flags.push(arg);\n continue;\n }\n specs.push(parseSpec(arg));\n }\n return { specs, flags };\n}\n","const REGISTRY_URL = \"https://registry.npmjs.org\";\nconst REQUEST_TIMEOUT_MS = 15_000;\n\nexport interface ResolveDeps {\n fetchImpl?: typeof fetch;\n registryUrl?: string;\n}\n\nexport interface ResolvedVersion {\n /** Concrete version we'll hand to OSV. */\n version: string;\n /**\n * How we picked it: \"exact\" (user pinned), \"dist-tag\" (latest/next/etc),\n * or \"fallback-latest\" (we couldn't resolve a range so we scanned latest).\n */\n source: \"exact\" | \"dist-tag\" | \"fallback-latest\";\n /** Set when source !== \"exact\" : what the user asked for. */\n requested?: string;\n}\n\ninterface PackumentDistTags {\n latest?: string;\n [tag: string]: string | undefined;\n}\n\ninterface Packument {\n name?: string;\n \"dist-tags\"?: PackumentDistTags;\n versions?: Record<string, unknown>;\n}\n\nconst EXACT_VERSION_RE = /^\\d+\\.\\d+\\.\\d+(?:[-+][\\w.+-]+)?$/;\nconst RANGE_CHARS_RE = /[\\^~><=|\\s*x]/i;\n\n/**\n * Resolve a user-supplied spec to a concrete version we can query OSV with.\n *\n * Strategy (v1):\n * - no version requested → dist-tags.latest\n * - exact version (1.2.3) → use as-is, verified to exist\n * - dist-tag (latest/next/beta) → dist-tags[tag], or fall back to latest\n * - semver range (^1, >=2) → dist-tags.latest with source=\"fallback-latest\"\n *\n * The fallback case is a known limitation: the installed version may differ\n * from what we scanned. The orchestrator surfaces this in its report.\n */\nexport async function resolveVersion(\n name: string,\n requested: string | undefined,\n deps: ResolveDeps = {},\n): Promise<ResolvedVersion> {\n const fetchImpl = deps.fetchImpl ?? fetch;\n const registry = deps.registryUrl ?? REGISTRY_URL;\n const packument = await fetchPackument(fetchImpl, registry, name);\n\n const distTags = packument[\"dist-tags\"] ?? {};\n const latest = distTags.latest;\n\n if (!requested) {\n if (!latest) {\n throw new VersionResolveError(\n `Package ${name} has no \"latest\" dist-tag in the registry.`,\n );\n }\n return { version: latest, source: \"dist-tag\", requested: \"latest\" };\n }\n\n if (EXACT_VERSION_RE.test(requested)) {\n if (packument.versions && !packument.versions[requested]) {\n throw new VersionResolveError(\n `Version ${requested} of ${name} is not published.`,\n );\n }\n return { version: requested, source: \"exact\" };\n }\n\n if (!RANGE_CHARS_RE.test(requested) && distTags[requested]) {\n return {\n version: distTags[requested] as string,\n source: \"dist-tag\",\n requested,\n };\n }\n\n if (!latest) {\n throw new VersionResolveError(\n `Cannot resolve ${name}@${requested}: no \"latest\" dist-tag available to fall back on.`,\n );\n }\n return { version: latest, source: \"fallback-latest\", requested };\n}\n\nexport class VersionResolveError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"VersionResolveError\";\n }\n}\n\nasync function fetchPackument(\n fetchImpl: typeof fetch,\n registry: string,\n name: string,\n): Promise<Packument> {\n const url = `${registry.replace(/\\/$/, \"\")}/${encodePackageName(name)}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n try {\n const res = await fetchImpl(url, {\n signal: controller.signal,\n headers: { accept: \"application/json\" },\n });\n if (res.status === 404) {\n throw new VersionResolveError(`Package ${name} not found in registry.`);\n }\n if (!res.ok) {\n throw new VersionResolveError(\n `Registry ${res.status} for ${name}: ${res.statusText}`,\n );\n }\n return (await res.json()) as Packument;\n } finally {\n clearTimeout(timer);\n }\n}\n\nfunction encodePackageName(name: string): string {\n // Scoped names: \"@scope/name\" → \"@scope%2Fname\"\n if (name.startsWith(\"@\")) {\n const slash = name.indexOf(\"/\");\n if (slash !== -1) {\n return `${encodeURIComponent(name.slice(0, slash))}%2F${encodeURIComponent(name.slice(slash + 1))}`;\n }\n }\n return encodeURIComponent(name);\n}\n","import { spawn } from \"node:child_process\";\nimport { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { join, relative, resolve, sep } from \"node:path\";\nimport type { Severity } from \"./types.js\";\n\nexport type EnvIssueKind =\n | \"tracked-by-git\"\n | \"not-gitignored\"\n | \"would-be-published\"\n | \"secret-in-example\"\n | \"no-gitignore\";\n\nexport interface EnvIssue {\n kind: EnvIssueKind;\n severity: Severity;\n file: string;\n message: string;\n detail?: string;\n}\n\nexport interface EnvScanResult {\n scannedAt: string;\n cwd: string;\n envFiles: string[];\n issues: EnvIssue[];\n summary: Record<Severity, number>;\n errors: { message: string; cause?: string }[];\n}\n\nexport interface EnvScanOptions {\n cwd?: string;\n /** Cap on directory recursion depth from cwd. Default 6. */\n maxDepth?: number;\n /** Override directory skip list (replaces the default). */\n skipDirs?: string[];\n}\n\nconst DEFAULT_SKIP_DIRS = new Set([\n \"node_modules\",\n \".git\",\n \"dist\",\n \"build\",\n \".next\",\n \".nuxt\",\n \".svelte-kit\",\n \".turbo\",\n \".cache\",\n \"coverage\",\n \"out\",\n \".vercel\",\n \".output\",\n]);\n\nconst EXAMPLE_NAME = /^\\.env(\\.[^.]+)*\\.(example|sample|template|dist)$/i;\nconst EXAMPLE_SUFFIX_NAME = /(\\.|^)(example|sample|template)$/i;\n\nexport async function scanEnv(\n options: EnvScanOptions = {},\n): Promise<EnvScanResult> {\n const cwd = resolve(options.cwd ?? process.cwd());\n const skipDirs = options.skipDirs\n ? new Set(options.skipDirs)\n : DEFAULT_SKIP_DIRS;\n const maxDepth = options.maxDepth ?? 6;\n\n const errors: { message: string; cause?: string }[] = [];\n const envFiles = discoverEnvFiles(cwd, skipDirs, maxDepth);\n\n const inGit = isGitRepo(cwd);\n const gitignorePath = join(cwd, \".gitignore\");\n const hasGitignore = existsSync(gitignorePath);\n const exampleFiles = envFiles.filter(isExampleFile);\n const realEnvFiles = envFiles.filter((f) => !isExampleFile(f));\n\n const [trackedSet, ignoredMap, publishCheck, exampleSecrets] =\n await Promise.all([\n inGit ? gitTracked(cwd, envFiles) : Promise.resolve(new Set<string>()),\n inGit\n ? gitCheckIgnore(cwd, envFiles)\n : Promise.resolve(fallbackIgnoreMap(cwd, envFiles)),\n checkPublishExposure(cwd, realEnvFiles),\n scanExampleFilesForSecrets(cwd, exampleFiles),\n ]).catch((err) => {\n errors.push({\n message: \"env scan: parallel checks failed\",\n cause: (err as Error).message,\n });\n return [\n new Set<string>(),\n new Map<string, boolean>(),\n [] as PublishFinding[],\n [] as SecretFinding[],\n ] as const;\n });\n\n const issues: EnvIssue[] = [];\n\n if (envFiles.length > 0 && !hasGitignore) {\n issues.push({\n kind: \"no-gitignore\",\n severity: \"moderate\",\n file: \".gitignore\",\n message: \"Project has env files but no .gitignore.\",\n detail:\n \"Add a .gitignore that includes .env and .env.* before committing.\",\n });\n }\n\n for (const file of realEnvFiles) {\n if (trackedSet.has(file)) {\n issues.push({\n kind: \"tracked-by-git\",\n severity: \"critical\",\n file,\n message: `${file} is tracked by git.`,\n detail:\n \"This file is committed to the repo. Run `git rm --cached` and rotate any secrets that were exposed.\",\n });\n continue;\n }\n const ignored = ignoredMap.get(file);\n if (hasGitignore && ignored === false) {\n issues.push({\n kind: \"not-gitignored\",\n severity: \"high\",\n file,\n message: `${file} exists but is not covered by .gitignore.`,\n detail: \"Add a matching pattern (e.g. `.env*`) to .gitignore.\",\n });\n }\n }\n\n for (const f of publishCheck) {\n issues.push({\n kind: \"would-be-published\",\n severity: \"critical\",\n file: f.file,\n message: `${f.file} would be included in the published npm tarball.`,\n detail: f.reason,\n });\n }\n\n for (const f of exampleSecrets) {\n issues.push({\n kind: \"secret-in-example\",\n severity: \"high\",\n file: f.file,\n message: `${f.file} appears to contain a real secret.`,\n detail: `Matched pattern: ${f.pattern} on key \\`${f.key}\\`. Example files should hold placeholder values only.`,\n });\n }\n\n issues.sort(compareIssues);\n\n return {\n scannedAt: new Date().toISOString(),\n cwd,\n envFiles,\n issues,\n summary: summarizeIssues(issues),\n errors,\n };\n}\n\nfunction compareIssues(a: EnvIssue, b: EnvIssue): number {\n const rank: Record<Severity, number> = {\n critical: 4,\n high: 3,\n moderate: 2,\n low: 1,\n unknown: 0,\n };\n const sev = rank[b.severity] - rank[a.severity];\n if (sev !== 0) return sev;\n if (a.file !== b.file) return a.file.localeCompare(b.file);\n return a.kind.localeCompare(b.kind);\n}\n\nfunction summarizeIssues(issues: EnvIssue[]): Record<Severity, number> {\n const out: Record<Severity, number> = {\n critical: 0,\n high: 0,\n moderate: 0,\n low: 0,\n unknown: 0,\n };\n for (const i of issues) out[i.severity]++;\n return out;\n}\n\nfunction discoverEnvFiles(\n cwd: string,\n skipDirs: Set<string>,\n maxDepth: number,\n): string[] {\n const found: string[] = [];\n walk(cwd, cwd, 0);\n found.sort();\n return found;\n\n function walk(dir: string, root: string, depth: number): void {\n if (depth > maxDepth) return;\n let entries: import(\"node:fs\").Dirent[];\n try {\n entries = readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n for (const entry of entries) {\n if (entry.isDirectory()) {\n if (skipDirs.has(entry.name) || entry.name.startsWith(\".git\")) continue;\n walk(join(dir, entry.name), root, depth + 1);\n continue;\n }\n if (!entry.isFile() && !entry.isSymbolicLink()) continue;\n if (isEnvFilename(entry.name)) {\n found.push(toPosix(relative(root, join(dir, entry.name))));\n }\n }\n }\n}\n\nfunction isEnvFilename(name: string): boolean {\n if (name === \".env\") return true;\n if (name.startsWith(\".env.\")) return true;\n return false;\n}\n\nfunction isExampleFile(file: string): boolean {\n const base = file.split(\"/\").pop() ?? file;\n if (EXAMPLE_NAME.test(base)) return true;\n // Catch `.env.example` and similar where the suffix is the last segment.\n const segments = base.split(\".\");\n const last = segments[segments.length - 1] ?? \"\";\n return EXAMPLE_SUFFIX_NAME.test(last);\n}\n\nfunction toPosix(p: string): string {\n return sep === \"/\" ? p : p.split(sep).join(\"/\");\n}\n\nfunction isGitRepo(cwd: string): boolean {\n let dir = cwd;\n for (let i = 0; i < 32; i++) {\n if (existsSync(join(dir, \".git\"))) return true;\n const parent = resolve(dir, \"..\");\n if (parent === dir) return false;\n dir = parent;\n }\n return false;\n}\n\nasync function gitTracked(\n cwd: string,\n files: string[],\n): Promise<Set<string>> {\n if (files.length === 0) return new Set();\n const { stdout, code } = await runGit(cwd, [\"ls-files\", \"-z\", \"--\", ...files]);\n if (code !== 0) return new Set();\n const tracked = stdout.split(\"\\0\").filter(Boolean).map(toPosix);\n return new Set(tracked);\n}\n\nasync function gitCheckIgnore(\n cwd: string,\n files: string[],\n): Promise<Map<string, boolean>> {\n const result = new Map<string, boolean>();\n if (files.length === 0) return result;\n // -z is only valid with --stdin. We pipe NUL-separated paths to a single\n // process — one spawn for any number of files.\n const stdin = `${files.join(\"\\0\")}\\0`;\n const { stdout, code } = await runGit(\n cwd,\n [\"check-ignore\", \"--no-index\", \"-v\", \"-n\", \"-z\", \"--stdin\"],\n stdin,\n );\n if (code !== 0 && code !== 1) {\n // Operational failure; treat all as unknown (false).\n for (const f of files) result.set(f, false);\n return result;\n }\n // -z -v -n format: for each input path, three NUL-separated fields:\n // <source>\\0<linenum>\\0<pattern>\\0<pathname>\\0\n // For non-matching paths: source/linenum/pattern are empty strings.\n const parts = stdout.split(\"\\0\");\n for (let i = 0; i + 3 < parts.length; i += 4) {\n const source = parts[i];\n const pathname = toPosix(parts[i + 3] ?? \"\");\n if (!pathname) continue;\n result.set(pathname, source !== \"\");\n }\n for (const f of files) {\n if (!result.has(f)) result.set(f, false);\n }\n return result;\n}\n\nfunction fallbackIgnoreMap(\n cwd: string,\n files: string[],\n): Map<string, boolean> {\n // Not a git repo: do best-effort matching on a literal .gitignore.\n const result = new Map<string, boolean>();\n const patterns = readIgnoreFile(join(cwd, \".gitignore\"));\n for (const f of files) result.set(f, matchesAny(f, patterns));\n return result;\n}\n\nfunction runGit(\n cwd: string,\n args: string[],\n stdin?: string,\n): Promise<{ stdout: string; stderr: string; code: number }> {\n return new Promise((resolveP) => {\n const child = spawn(\"git\", args, {\n cwd,\n stdio: [stdin === undefined ? \"ignore\" : \"pipe\", \"pipe\", \"pipe\"],\n });\n let stdout = \"\";\n let stderr = \"\";\n child.stdout?.on(\"data\", (d) => {\n stdout += d.toString(\"utf8\");\n });\n child.stderr?.on(\"data\", (d) => {\n stderr += d.toString(\"utf8\");\n });\n child.on(\"error\", () => resolveP({ stdout, stderr, code: -1 }));\n child.on(\"close\", (code) =>\n resolveP({ stdout, stderr, code: code ?? -1 }),\n );\n if (stdin !== undefined && child.stdin) {\n child.stdin.end(stdin);\n }\n });\n}\n\ninterface PublishFinding {\n file: string;\n reason: string;\n}\n\nasync function checkPublishExposure(\n cwd: string,\n envFiles: string[],\n): Promise<PublishFinding[]> {\n if (envFiles.length === 0) return [];\n const pkgPath = join(cwd, \"package.json\");\n if (!existsSync(pkgPath)) return [];\n let pkg: { files?: unknown; private?: unknown };\n try {\n pkg = JSON.parse(readFileSync(pkgPath, \"utf8\"));\n } catch {\n return [];\n }\n // Private packages are never published; skip the check.\n if (pkg.private === true) return [];\n\n const findings: PublishFinding[] = [];\n\n if (Array.isArray(pkg.files)) {\n const allowList = pkg.files.filter((x): x is string => typeof x === \"string\");\n for (const file of envFiles) {\n if (matchesAny(file, allowList)) {\n findings.push({\n file,\n reason: `package.json \"files\" allowlist matches this path. Remove the entry or move the file.`,\n });\n }\n }\n return findings;\n }\n\n // No `files` allowlist: npm uses .npmignore, falling back to .gitignore.\n const npmignorePath = join(cwd, \".npmignore\");\n const ignorePath = existsSync(npmignorePath)\n ? npmignorePath\n : join(cwd, \".gitignore\");\n const ignoreSource = existsSync(ignorePath)\n ? ignorePath === npmignorePath\n ? \".npmignore\"\n : \".gitignore\"\n : null;\n const patterns = ignoreSource ? readIgnoreFile(ignorePath) : [];\n\n for (const file of envFiles) {\n if (!matchesAny(file, patterns)) {\n findings.push({\n file,\n reason: ignoreSource\n ? `Not matched by any pattern in ${ignoreSource}. Add an entry like \\`.env*\\`.`\n : `No .npmignore or .gitignore present, so npm will include this file in the published tarball. Add an .npmignore.`,\n });\n }\n }\n return findings;\n}\n\nfunction readIgnoreFile(path: string): string[] {\n if (!existsSync(path)) return [];\n try {\n return readFileSync(path, \"utf8\")\n .split(/\\r?\\n/)\n .map((l) => l.trim())\n .filter((l) => l.length > 0 && !l.startsWith(\"#\"));\n } catch {\n return [];\n }\n}\n\n/**\n * Simplified gitignore-style matcher. Supports:\n * - exact filename / path match\n * - leading `/` anchors to repo root\n * - `*` wildcard within a single path segment\n * - `**` matches any number of segments\n * - leading `!` negation\n * Patterns without a slash match against the basename at any depth.\n */\nexport function matchesAny(file: string, patterns: string[]): boolean {\n let matched = false;\n for (const raw of patterns) {\n let pattern = raw;\n let negate = false;\n if (pattern.startsWith(\"!\")) {\n negate = true;\n pattern = pattern.slice(1);\n }\n if (pattern.endsWith(\"/\")) pattern = pattern.slice(0, -1);\n if (matchesPattern(file, pattern)) matched = !negate;\n }\n return matched;\n}\n\nfunction matchesPattern(file: string, pattern: string): boolean {\n if (!pattern) return false;\n const anchored = pattern.startsWith(\"/\");\n const pat = anchored ? pattern.slice(1) : pattern;\n const hasSlash = pat.includes(\"/\");\n const candidates = anchored\n ? [file]\n : hasSlash\n ? [file]\n : [file, file.split(\"/\").pop() ?? file];\n const re = globToRegex(pat);\n return candidates.some((c) => re.test(c));\n}\n\nfunction globToRegex(pattern: string): RegExp {\n let re = \"^\";\n for (let i = 0; i < pattern.length; i++) {\n const ch = pattern[i];\n if (ch === \"*\") {\n if (pattern[i + 1] === \"*\") {\n re += \".*\";\n i++;\n if (pattern[i + 1] === \"/\") i++;\n } else {\n re += \"[^/]*\";\n }\n } else if (ch === \"?\") {\n re += \"[^/]\";\n } else if (ch === \".\") {\n re += \"\\\\.\";\n } else if (/[\\\\^$+()=!|{}[\\]]/.test(ch ?? \"\")) {\n re += `\\\\${ch}`;\n } else {\n re += ch;\n }\n }\n re += \"$\";\n return new RegExp(re);\n}\n\ninterface SecretFinding {\n file: string;\n key: string;\n pattern: string;\n}\n\nconst SECRET_PATTERNS: { name: string; re: RegExp }[] = [\n { name: \"AWS access key id\", re: /\\bAKIA[0-9A-Z]{16}\\b/ },\n { name: \"GitHub token\", re: /\\bgh[pousr]_[A-Za-z0-9]{36,}\\b/ },\n { name: \"Slack token\", re: /\\bxox[abprs]-[A-Za-z0-9-]{10,}\\b/ },\n { name: \"Stripe live key\", re: /\\bsk_live_[A-Za-z0-9]{16,}\\b/ },\n { name: \"Google API key\", re: /\\bAIza[0-9A-Za-z_-]{35}\\b/ },\n { name: \"Generic JWT\", re: /\\beyJ[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]{10,}\\b/ },\n { name: \"Private key block\", re: /-----BEGIN (RSA |EC |OPENSSH |DSA |PGP )?PRIVATE KEY-----/ },\n];\n\nconst PLACEHOLDER_RE = /^(?:|x+|y+|<.*>|\\{.*\\}|change[-_ ]?me|todo|placeholder|your[-_ ].+|example|dummy|fake|test)$/i;\n\nasync function scanExampleFilesForSecrets(\n cwd: string,\n files: string[],\n): Promise<SecretFinding[]> {\n const findings: SecretFinding[] = [];\n await Promise.all(\n files.map(async (file) => {\n let content: string;\n try {\n content = readFileSync(join(cwd, file), \"utf8\");\n } catch {\n return;\n }\n const lines = content.split(/\\r?\\n/);\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(\"#\")) continue;\n const eq = trimmed.indexOf(\"=\");\n if (eq <= 0) continue;\n const key = trimmed.slice(0, eq).trim();\n let value = trimmed.slice(eq + 1).trim();\n // Strip wrapping quotes and inline comment.\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n } else {\n const hashIdx = value.indexOf(\" #\");\n if (hashIdx >= 0) value = value.slice(0, hashIdx).trim();\n }\n if (!value || PLACEHOLDER_RE.test(value)) continue;\n for (const pat of SECRET_PATTERNS) {\n if (pat.re.test(value)) {\n findings.push({ file, key, pattern: pat.name });\n break;\n }\n }\n }\n }),\n );\n return findings;\n}\n\nexport function envIssuesMeetThreshold(\n issues: EnvIssue[],\n threshold: Severity | \"none\",\n): boolean {\n if (threshold === \"none\") return false;\n const rank: Record<Severity, number> = {\n critical: 4,\n high: 3,\n moderate: 2,\n low: 1,\n unknown: 0,\n };\n const min = rank[threshold];\n return issues.some((i) => rank[i.severity] >= min);\n}\n\n","import { existsSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { POLICY_PRESETS } from \"./policy.js\";\nimport { scanProject, ScanInputError } from \"./scanner.js\";\nimport type { PolicyPresetName, ScanResult } from \"./types.js\";\n\nexport interface InitOptions {\n cwd?: string;\n config?: string;\n baseline?: string;\n policy?: PolicyPresetName;\n risk?: boolean;\n env?: boolean;\n writeBaseline?: boolean;\n overwrite?: boolean;\n fetchImpl?: typeof fetch;\n}\n\nexport interface InitResult {\n configPath: string;\n configWritten: boolean;\n baselinePath?: string;\n baselineWritten: boolean;\n scan?: ScanResult;\n warnings: string[];\n}\n\nexport async function initProject(\n options: InitOptions = {},\n): Promise<InitResult> {\n const cwd = resolve(options.cwd ?? process.cwd());\n const policy = options.policy ?? \"ci\";\n const configPath = resolve(cwd, options.config ?? \"trawly.toml\");\n const baselinePath = options.baseline ?? \"trawly-baseline.json\";\n const warnings: string[] = [];\n\n let configWritten = false;\n if (options.overwrite || !existsSync(configPath)) {\n writeFileSync(configPath, renderConfig(policy, baselinePath));\n configWritten = true;\n } else {\n warnings.push(`${configPath} already exists; leaving it unchanged.`);\n }\n\n let scan: ScanResult | undefined;\n let baselineWritten = false;\n if (options.writeBaseline !== false) {\n try {\n scan = await scanProject({\n cwd,\n config: configPath,\n policy,\n risk: options.risk,\n env: options.env,\n writeBaseline: baselinePath,\n fetchImpl: options.fetchImpl,\n });\n baselineWritten = scan.baseline?.written !== undefined;\n } catch (err) {\n if (err instanceof ScanInputError) {\n warnings.push(\n \"No supported lockfile or SBOM was found, so no baseline was written.\",\n );\n } else {\n throw err;\n }\n }\n }\n\n return {\n configPath,\n configWritten,\n baselinePath: resolve(cwd, baselinePath),\n baselineWritten,\n scan,\n warnings,\n };\n}\n\nfunction renderConfig(\n policy: PolicyPresetName,\n baselinePath: string,\n): string {\n const preset = POLICY_PRESETS[policy];\n return [\n `policy = \"${policy}\"`,\n `failOn = \"${preset.failOn}\"`,\n `risk = ${String(preset.risk)}`,\n `env = ${String(preset.env)}`,\n 'allowedRegistries = [\"https://registry.npmjs.org\", \"https://registry.yarnpkg.com\"]',\n \"\",\n `# Existing findings are tracked in ${baselinePath}.`,\n \"# Ignore entries must expire.\",\n \"# [[ignore]]\",\n '# id = \"GHSA-example\"',\n '# package = \"example-package\"',\n '# expires = \"2026-06-30\"',\n '# reason = \"Not reachable in this application\"',\n \"\",\n ].join(\"\\n\");\n}\n","import kleur from \"kleur\";\nimport type { EnvIssue, EnvScanResult } from \"../env-scan.js\";\nimport type { Severity } from \"../types.js\";\nimport { renderBanner } from \"./banner.js\";\n\nexport interface ReportEnvTableOptions {\n /**\n * When true, renders a boxed `trawly` nameplate at the top in place of the\n * plain `trawly env: …` header. CLI sets this only when stdout is a TTY so\n * that piped/CI output stays log-parser friendly.\n */\n brand?: boolean;\n}\n\nconst SEVERITY_COLOR: Record<Severity, (s: string) => string> = {\n critical: (s) => kleur.bold().red(s),\n high: (s) => kleur.red(s),\n moderate: (s) => kleur.yellow(s),\n low: (s) => kleur.cyan(s),\n unknown: (s) => kleur.gray(s),\n};\n\nconst SEVERITY_ORDER: Severity[] = [\n \"critical\",\n \"high\",\n \"moderate\",\n \"low\",\n \"unknown\",\n];\n\nconst KIND_LABEL: Record<EnvIssue[\"kind\"], string> = {\n \"tracked-by-git\": \"tracked-by-git\",\n \"not-gitignored\": \"not-gitignored\",\n \"would-be-published\": \"would-be-published\",\n \"secret-in-example\": \"secret-in-example\",\n \"no-gitignore\": \"no-gitignore\",\n};\n\nexport function reportEnvTable(\n result: EnvScanResult,\n options: ReportEnvTableOptions = {},\n): string {\n const lines: string[] = [];\n\n if (options.brand) {\n const { metricsLine, timestamp } = headerParts(result);\n lines.push(renderBanner({ metrics: metricsLine, timestamp }));\n } else {\n lines.push(kleur.bold(formatHeader(result)));\n }\n\n for (const err of result.errors) {\n lines.push(\n kleur.red(`! ${err.message}${err.cause ? ` (${err.cause})` : \"\"}`),\n );\n }\n\n if (result.envFiles.length === 0) {\n lines.push(\"\");\n lines.push(kleur.gray(\"No .env files found in project.\"));\n return lines.join(\"\\n\");\n }\n\n if (result.issues.length === 0) {\n lines.push(\"\");\n lines.push(kleur.green(\"✓ No env-leak issues found.\"));\n lines.push(kleur.gray(\" Files checked:\"));\n for (const f of result.envFiles) lines.push(kleur.gray(` ${f}`));\n return lines.join(\"\\n\");\n }\n\n lines.push(\"\");\n lines.push(formatSummary(result.summary));\n lines.push(\"\");\n\n lines.push(formatIssueRows(result.issues));\n\n lines.push(\"\");\n lines.push(\n kleur.gray(\n \"Reminder: trawly env checks ignore coverage and publish exposure. It cannot prove a secret hasn't already leaked elsewhere — rotate any value you suspect was committed.\",\n ),\n );\n return lines.join(\"\\n\");\n}\n\nfunction formatIssueRows(issues: EnvIssue[]): string {\n const rows: string[][] = [[\"SEV\", \"KIND\", \"FILE\", \"MESSAGE\", \"HINT\"]];\n for (const issue of issues) {\n rows.push([\n issue.severity,\n KIND_LABEL[issue.kind],\n issue.file,\n truncate(issue.message, 60),\n issue.detail ? truncate(issue.detail, 60) : \":\",\n ]);\n }\n\n return renderTable(rows, (rowIdx, row, cells) => {\n if (rowIdx === 0) return kleur.bold().underline(cells.join(\" \"));\n const sev = row[0] as Severity;\n const colorize = SEVERITY_COLOR[sev] ?? ((s: string) => s);\n cells[0] = colorize(cells[0]!);\n cells[2] = kleur.cyan(cells[2]!);\n cells[1] = kleur.bold(cells[1]!);\n return cells.join(\" \");\n });\n}\n\nfunction formatHeader(result: EnvScanResult): string {\n const { metricsLine, timestamp } = headerParts(result);\n return `trawly env: ${metricsLine} (${timestamp})`;\n}\n\nfunction headerParts(result: EnvScanResult): {\n metricsLine: string;\n timestamp: string;\n} {\n const fileCount = result.envFiles.length;\n const issueCount = result.issues.length;\n const metricsLine = [\n `${fileCount} env file${fileCount === 1 ? \"\" : \"s\"} scanned`,\n `${issueCount} issue${issueCount === 1 ? \"\" : \"s\"}`,\n ].join(\" · \");\n return { metricsLine, timestamp: result.scannedAt };\n}\n\nfunction formatSummary(summary: Record<Severity, number>): string {\n const parts: string[] = [];\n for (const sev of SEVERITY_ORDER) {\n const count = summary[sev];\n if (count === 0) continue;\n parts.push(SEVERITY_COLOR[sev](`${sev}: ${count}`));\n }\n if (parts.length === 0) return kleur.green(\"No findings.\");\n return `Issues : ${parts.join(\" \")}`;\n}\n\nexport function reportEnvJson(result: EnvScanResult): string {\n return JSON.stringify(result, null, 2);\n}\n\nfunction truncate(s: string, max: number): string {\n if (s.length <= max) return s;\n return `${s.slice(0, max - 1)}…`;\n}\n\nfunction renderTable(\n rows: string[][],\n format: (rowIdx: number, row: string[], cells: string[]) => string,\n): string {\n const widths = rows[0]!.map((_, col) =>\n Math.max(...rows.map((r) => visibleLength(r[col]!))),\n );\n return rows\n .map((row, i) => {\n const cells = row.map((cell, col) => padEndVisible(cell, widths[col]!));\n return format(i, row, cells);\n })\n .join(\"\\n\");\n}\n\n// kleur wraps strings in ANSI escape codes; padEnd needs the visible width.\nconst ANSI_RE = /\\u001B\\[[0-9;]*m/g;\nfunction visibleLength(s: string): number {\n return s.replace(ANSI_RE, \"\").length;\n}\nfunction padEndVisible(s: string, width: number): string {\n const pad = Math.max(0, width - visibleLength(s));\n return s + \" \".repeat(pad);\n}\n","import kleur from \"kleur\";\n\nexport interface BannerProps {\n /** First content row, e.g. \"164 packages · 2 affected · 2 findings\". */\n metrics: string;\n /** Second content row, typically a scannedAt ISO timestamp. */\n timestamp: string;\n}\n\nconst BORDER = {\n tl: \"┌\",\n tr: \"┐\",\n bl: \"└\",\n br: \"┘\",\n h: \"─\",\n v: \"│\",\n} as const;\n\nconst TITLE = \"trawly\";\nconst SIDE_PAD = 1; // single space between │ and content\nconst MIN_TITLE_FILLER = 4; // ensure at least \"────\" after `─ trawly `\n\nexport function renderBanner(props: BannerProps): string {\n const contentRows = [props.metrics, props.timestamp];\n const titleSegment = ` ${TITLE} `; // \" trawly \"\n const minTitleWidth = 1 + titleSegment.length + MIN_TITLE_FILLER; // ─ + \" trawly \" + ────\n\n const innerWidth = Math.max(\n ...contentRows.map((r) => r.length + SIDE_PAD * 2),\n minTitleWidth,\n );\n\n const top = renderTop(innerWidth);\n const bottom = renderBottom(innerWidth);\n const metricsLine = renderRow(innerWidth, props.metrics, kleur.bold);\n const timestampLine = renderRow(innerWidth, props.timestamp, kleur.gray);\n\n return [top, metricsLine, timestampLine, bottom].join(\"\\n\");\n}\n\nfunction renderTop(innerWidth: number): string {\n const titleSegment = ` ${kleur.bold().cyan(TITLE)} `;\n const titleVisibleLen = TITLE.length + 2; // bold/cyan don't add visible chars\n const fillerCount = innerWidth - 1 - titleVisibleLen; // -1 for the leading \"─\"\n return (\n kleur.gray(BORDER.tl) +\n kleur.gray(BORDER.h) +\n titleSegment +\n kleur.gray(BORDER.h.repeat(Math.max(MIN_TITLE_FILLER, fillerCount))) +\n kleur.gray(BORDER.tr)\n );\n}\n\nfunction renderBottom(innerWidth: number): string {\n return kleur.gray(`${BORDER.bl}${BORDER.h.repeat(innerWidth)}${BORDER.br}`);\n}\n\nfunction renderRow(\n innerWidth: number,\n content: string,\n colorize: (s: string) => string,\n): string {\n const fill = Math.max(0, innerWidth - SIDE_PAD * 2 - content.length);\n return (\n kleur.gray(BORDER.v) +\n \" \".repeat(SIDE_PAD) +\n colorize(content) +\n \" \".repeat(fill + SIDE_PAD) +\n kleur.gray(BORDER.v)\n );\n}\n","import type { ScanResult } from \"../types.js\";\n\nexport function reportJson(result: ScanResult): string {\n return JSON.stringify(result, null, 2);\n}\n","import type { Finding, ScanResult, Severity } from \"../types.js\";\n\nconst ORDER: Severity[] = [\"critical\", \"high\", \"moderate\", \"low\", \"unknown\"];\n\nexport function reportMarkdown(result: ScanResult): string {\n const lines: string[] = [];\n lines.push(\"# trawly report\");\n lines.push(\"\");\n lines.push(`Scanned at: \\`${result.scannedAt}\\``);\n lines.push(`Packages scanned: **${result.packagesScanned}**`);\n lines.push(`Findings: **${result.findings.length}**`);\n if (result.ignoredFindings.length > 0) {\n lines.push(`Ignored findings: **${result.ignoredFindings.length}**`);\n }\n if (result.baseline) {\n lines.push(\n `Baseline: **${result.baseline.new} new**, **${result.baseline.existing} existing**`,\n );\n }\n lines.push(\"\");\n lines.push(`Severity summary: ${formatSummary(result.summary)}`);\n\n if (result.warnings.length > 0) {\n lines.push(\"\");\n lines.push(\"## Warnings\");\n for (const warning of result.warnings) lines.push(`- ${warning}`);\n }\n\n lines.push(\"\");\n lines.push(\"## Findings\");\n if (result.findings.length === 0) {\n lines.push(\"\");\n lines.push(\"No active findings.\");\n } else {\n lines.push(\"\");\n lines.push(\"| Severity | Source | Package | Version | ID | Summary |\");\n lines.push(\"| --- | --- | --- | --- | --- | --- |\");\n for (const finding of result.findings) {\n lines.push(findingRow(finding));\n }\n }\n\n if (result.ignoredFindings.length > 0) {\n lines.push(\"\");\n lines.push(\"## Ignored Findings\");\n lines.push(\"\");\n lines.push(\"| Severity | Source | Package | Version | ID | Summary |\");\n lines.push(\"| --- | --- | --- | --- | --- | --- |\");\n for (const finding of result.ignoredFindings) {\n lines.push(findingRow(finding));\n }\n }\n\n return lines.join(\"\\n\");\n}\n\nfunction formatSummary(summary: Record<Severity, number>): string {\n const parts = ORDER.filter((sev) => summary[sev] > 0).map(\n (sev) => `${sev}: ${summary[sev]}`,\n );\n return parts.length === 0 ? \"none\" : parts.join(\", \");\n}\n\nfunction findingRow(finding: Finding): string {\n const id = finding.url\n ? `[${escapeCell(finding.id)}](${finding.url})`\n : escapeCell(finding.id);\n return [\n finding.severity,\n finding.source,\n escapeCell(finding.packageName),\n escapeCell(finding.installedVersion),\n id,\n escapeCell(finding.summary),\n ].join(\" | \").replace(/^/, \"| \").replace(/$/, \" |\");\n}\n\nfunction escapeCell(value: string): string {\n return value.replace(/\\|/g, \"\\\\|\").replace(/\\n/g, \" \");\n}\n","import { readFileSync } from \"node:fs\";\n\nconst FALLBACK_VERSION = \"0.1.0\";\n\nexport const TRAWLY_VERSION = readPackageVersion();\n\nfunction readPackageVersion(): string {\n try {\n const packageJson = JSON.parse(\n readFileSync(new URL(\"../package.json\", import.meta.url), \"utf8\"),\n ) as { version?: unknown };\n return typeof packageJson.version === \"string\"\n ? packageJson.version\n : FALLBACK_VERSION;\n } catch {\n return FALLBACK_VERSION;\n }\n}\n","import type { Finding, ScanResult } from \"../types.js\";\nimport { TRAWLY_VERSION } from \"../version.js\";\n\ninterface SarifRule {\n id: string;\n name: string;\n shortDescription: { text: string };\n fullDescription: { text: string };\n helpUri?: string;\n properties: { tags: string[]; precision: string; securitySeverity?: string };\n}\n\nexport function reportSarif(result: ScanResult): string {\n const allFindings = [...result.findings, ...result.ignoredFindings];\n const rules = buildRules(allFindings);\n const sarif = {\n version: \"2.1.0\",\n $schema:\n \"https://json.schemastore.org/sarif-2.1.0.json\",\n runs: [\n {\n tool: {\n driver: {\n name: \"trawly\",\n informationUri: \"https://github.com/Arindam200/trawly\",\n semanticVersion: TRAWLY_VERSION,\n rules,\n },\n },\n results: allFindings.map((finding) => findingToResult(finding)),\n },\n ],\n };\n return JSON.stringify(sarif, null, 2);\n}\n\nfunction buildRules(findings: Finding[]): SarifRule[] {\n const map = new Map<string, SarifRule>();\n for (const finding of findings) {\n if (map.has(finding.id)) continue;\n map.set(finding.id, {\n id: finding.id,\n name: finding.id,\n shortDescription: { text: finding.summary },\n fullDescription: { text: finding.summary },\n helpUri: finding.url,\n properties: {\n tags: [finding.source, finding.type, finding.ecosystem],\n precision: finding.source === \"osv\" ? \"high\" : \"medium\",\n securitySeverity: securitySeverity(finding),\n },\n });\n }\n return [...map.values()];\n}\n\nfunction findingToResult(finding: Finding): Record<string, unknown> {\n const result: Record<string, unknown> = {\n ruleId: finding.id,\n level: sarifLevel(finding),\n message: {\n text: `${finding.packageName}@${finding.installedVersion}: ${finding.summary}`,\n },\n locations: [\n {\n physicalLocation: {\n artifactLocation: {\n uri: artifactUri(finding),\n },\n region: finding.line ? { startLine: finding.line } : undefined,\n },\n },\n ],\n partialFingerprints: {\n trawlyFingerprint: finding.fingerprint,\n },\n properties: {\n package: finding.packageName,\n version: finding.installedVersion,\n ecosystem: finding.ecosystem,\n source: finding.source,\n aliases: finding.aliases,\n baseline: finding.baseline,\n },\n };\n if (finding.ignored) {\n result.suppressions = [\n { kind: \"external\", justification: \"Ignored by trawly configuration\" },\n ];\n }\n return result;\n}\n\nfunction artifactUri(finding: Finding): string {\n const path = finding.sourceFile ?? finding.affectedPaths[0];\n if (path) return path;\n const ecosystem = encodeURIComponent(finding.ecosystem || \"unknown\");\n const name = encodeURIComponent(finding.packageName || \"unknown\");\n const version = encodeURIComponent(finding.installedVersion || \"unknown\");\n return `pkg:${ecosystem}/${name}@${version}`;\n}\n\nfunction sarifLevel(finding: Finding): \"error\" | \"warning\" | \"note\" {\n if (finding.severity === \"critical\" || finding.severity === \"high\") {\n return \"error\";\n }\n if (finding.severity === \"moderate\" || finding.severity === \"low\") {\n return \"warning\";\n }\n return \"note\";\n}\n\nfunction securitySeverity(finding: Finding): string {\n switch (finding.severity) {\n case \"critical\":\n return \"9.5\";\n case \"high\":\n return \"8.0\";\n case \"moderate\":\n return \"5.0\";\n case \"low\":\n return \"2.0\";\n case \"unknown\":\n return \"0.0\";\n }\n}\n","import kleur from \"kleur\";\nimport {\n type Finding,\n type ScanResult,\n type Severity,\n SEVERITY_RANK,\n} from \"../types.js\";\nimport { renderBanner } from \"./banner.js\";\n\nexport type TableView = \"grouped\" | \"details\" | \"summary\";\n\nexport interface ReportTableOptions {\n /** @deprecated use `view` instead */\n details?: boolean;\n view?: TableView;\n /**\n * When true, renders a boxed `trawly` nameplate at the top in place of the\n * plain `trawly: …` header. CLI sets this only when stdout is a TTY so that\n * piped/CI output stays log-parser friendly.\n */\n brand?: boolean;\n}\n\nconst SEVERITY_COLOR: Record<Severity, (s: string) => string> = {\n critical: (s) => kleur.bold().red(s),\n high: (s) => kleur.red(s),\n moderate: (s) => kleur.yellow(s),\n low: (s) => kleur.cyan(s),\n unknown: (s) => kleur.gray(s),\n};\n\nconst SEVERITY_ORDER: Severity[] = [\n \"critical\",\n \"high\",\n \"moderate\",\n \"low\",\n \"unknown\",\n];\n\ninterface PackageGroup {\n packageName: string;\n installedVersion: string;\n topSeverity: Severity;\n counts: Record<Severity, number>;\n findings: Finding[];\n recommendedFix: string | null;\n}\n\nexport function reportTable(\n result: ScanResult,\n options: ReportTableOptions = {},\n): string {\n const view: TableView = options.view ?? (options.details ? \"details\" : \"grouped\");\n const lines: string[] = [];\n const warnings = result.warnings ?? [];\n const ignoredFindings = result.ignoredFindings ?? [];\n\n if (options.brand) {\n const { metricsLine, timestamp } = headerParts(result);\n lines.push(renderBanner({ metrics: metricsLine, timestamp }));\n } else {\n lines.push(kleur.bold(formatHeader(result)));\n }\n\n if (result.errors.length > 0) {\n for (const err of result.errors) {\n lines.push(\n kleur.red(`! ${err.message}${err.cause ? ` (${err.cause})` : \"\"}`),\n );\n }\n }\n if (warnings.length > 0) {\n for (const warning of warnings) {\n lines.push(kleur.yellow(`~ ${warning}`));\n }\n }\n if (ignoredFindings.length > 0) {\n lines.push(\n kleur.gray(`${ignoredFindings.length} finding(s) ignored by config.`),\n );\n }\n if (result.baseline) {\n lines.push(\n kleur.gray(\n `Baseline: ${result.baseline.new} new, ${result.baseline.existing} existing.`,\n ),\n );\n }\n\n if (result.findings.length === 0) {\n lines.push(kleur.green(\"✓ No active findings.\"));\n lines.push(\n kleur.gray(\n \" Note: absence of findings is not proof of safety.\",\n ),\n );\n return lines.join(\"\\n\");\n }\n\n if (view === \"summary\") {\n lines.push(formatSummary(result.summary));\n lines.push(reminder());\n return lines.join(\"\\n\");\n }\n\n lines.push(\"\");\n lines.push(formatSummary(result.summary));\n lines.push(\"\");\n\n if (view === \"details\") {\n lines.push(formatDetailRows(sortFindings(result.findings)));\n } else {\n const groups = groupByPackage(result.findings);\n lines.push(formatGroupedRows(groups));\n lines.push(\"\");\n lines.push(\n kleur.gray(\"Run `trawly scan --details` to see individual findings.\"),\n );\n }\n\n lines.push(\"\");\n lines.push(reminder());\n return lines.join(\"\\n\");\n}\n\nfunction formatHeader(result: ScanResult): string {\n const { metricsLine, timestamp } = headerParts(result);\n return `trawly: ${metricsLine} (${timestamp})`;\n}\n\nfunction headerParts(result: ScanResult): {\n metricsLine: string;\n timestamp: string;\n} {\n const affected = new Set(\n result.findings.map((f) => `${f.packageName}@${f.installedVersion}`),\n ).size;\n const findingCount = result.findings.length;\n const metricsLine = [\n `${result.packagesScanned} packages`,\n `${affected} affected`,\n `${findingCount} ${findingCount === 1 ? \"finding\" : \"findings\"}`,\n ].join(\" · \");\n return { metricsLine, timestamp: result.scannedAt };\n}\n\nfunction formatSummary(summary: ScanResult[\"summary\"]): string {\n const parts: string[] = [];\n for (const sev of SEVERITY_ORDER) {\n const count = summary[sev];\n if (count === 0) continue;\n parts.push(SEVERITY_COLOR[sev](`${sev}: ${count}`));\n }\n if (parts.length === 0) return kleur.green(\"No findings.\");\n return `Findings : ${parts.join(\" \")}`;\n}\n\nfunction reminder(): string {\n return kleur.gray(\n \"Reminder: absence of findings is not proof of safety.\",\n );\n}\n\nfunction sortFindings(findings: Finding[]): Finding[] {\n return [...findings].sort((a, b) => {\n const sev = SEVERITY_RANK[b.severity] - SEVERITY_RANK[a.severity];\n if (sev !== 0) return sev;\n const name = a.packageName.localeCompare(b.packageName);\n if (name !== 0) return name;\n return a.id.localeCompare(b.id);\n });\n}\n\nfunction groupByPackage(findings: Finding[]): PackageGroup[] {\n const map = new Map<string, PackageGroup>();\n for (const f of findings) {\n const key = `${f.packageName}@${f.installedVersion}`;\n let group = map.get(key);\n if (!group) {\n group = {\n packageName: f.packageName,\n installedVersion: f.installedVersion,\n topSeverity: f.severity,\n counts: { critical: 0, high: 0, moderate: 0, low: 0, unknown: 0 },\n findings: [],\n recommendedFix: null,\n };\n map.set(key, group);\n }\n group.findings.push(f);\n group.counts[f.severity] += 1;\n if (SEVERITY_RANK[f.severity] > SEVERITY_RANK[group.topSeverity]) {\n group.topSeverity = f.severity;\n }\n }\n\n for (const group of map.values()) {\n group.recommendedFix = pickRecommendedFix(group.findings);\n }\n\n return [...map.values()].sort((a, b) => {\n const sev = SEVERITY_RANK[b.topSeverity] - SEVERITY_RANK[a.topSeverity];\n if (sev !== 0) return sev;\n const totalA = a.findings.length;\n const totalB = b.findings.length;\n if (totalA !== totalB) return totalB - totalA;\n return a.packageName.localeCompare(b.packageName);\n });\n}\n\nfunction formatGroupedRows(groups: PackageGroup[]): string {\n const rows: string[][] = [\n [\"PACKAGE\", \"VERSION\", \"SEVERITY\", \"FIX\"],\n ];\n for (const g of groups) {\n rows.push([\n g.packageName,\n g.installedVersion,\n formatSeverityCounts(g.counts),\n g.recommendedFix ? `>=${g.recommendedFix}` : \":\",\n ]);\n }\n return renderTable(rows, (rowIdx, _row, cells) => {\n if (rowIdx === 0) return kleur.bold().underline(cells.join(\" \"));\n return cells.join(\" \");\n });\n}\n\nfunction formatDetailRows(findings: Finding[]): string {\n const rows: string[][] = [\n [\"SEV\", \"PACKAGE\", \"VERSION\", \"ID\", \"FIXED IN\", \"SUMMARY\"],\n ];\n for (const f of findings) {\n rows.push([\n f.severity,\n f.packageName,\n f.installedVersion,\n f.id,\n f.fixedVersions.length ? f.fixedVersions.join(\", \") : \":\",\n truncate(f.summary, 70),\n ]);\n }\n return renderTable(rows, (rowIdx, row, cells) => {\n if (rowIdx === 0) return kleur.bold().underline(cells.join(\" \"));\n const sev = row[0] as Severity;\n const colorize = SEVERITY_COLOR[sev] ?? ((s: string) => s);\n cells[0] = colorize(cells[0]!);\n return cells.join(\" \");\n });\n}\n\nfunction formatSeverityCounts(counts: Record<Severity, number>): string {\n const parts: string[] = [];\n for (const sev of SEVERITY_ORDER) {\n const n = counts[sev];\n if (n === 0) continue;\n parts.push(SEVERITY_COLOR[sev](`${n} ${sev}`));\n }\n return parts.join(\", \");\n}\n\nfunction renderTable(\n rows: string[][],\n format: (rowIdx: number, row: string[], cells: string[]) => string,\n): string {\n const widths = rows[0]!.map((_, col) =>\n Math.max(...rows.map((r) => visibleLength(r[col]!))),\n );\n return rows\n .map((row, i) => {\n const cells = row.map((cell, col) => padEndVisible(cell, widths[col]!));\n return format(i, row, cells);\n })\n .join(\"\\n\");\n}\n\n/**\n * Pick the highest semver-ish value across all fixedVersions in the group.\n * Picking the max guarantees the upgrade clears every known advisory; users\n * can drop into `--details` if they want to evaluate alternative fix lines\n * (e.g. staying on a previous major).\n */\nfunction pickRecommendedFix(findings: Finding[]): string | null {\n const candidates: string[] = [];\n for (const f of findings) {\n for (const v of f.fixedVersions) candidates.push(v);\n }\n if (candidates.length === 0) return null;\n const unique = [...new Set(candidates)];\n unique.sort(compareSemver);\n return unique[unique.length - 1] ?? null;\n}\n\nfunction compareSemver(a: string, b: string): number {\n const pa = parseSemverParts(a);\n const pb = parseSemverParts(b);\n for (let i = 0; i < 3; i++) {\n const diff = (pa[i] ?? 0) - (pb[i] ?? 0);\n if (diff !== 0) return diff;\n }\n return a.localeCompare(b);\n}\n\nfunction parseSemverParts(v: string): number[] {\n const m = v.match(/(\\d+)\\.(\\d+)\\.(\\d+)/);\n if (!m) return [0, 0, 0];\n return [Number(m[1]), Number(m[2]), Number(m[3])];\n}\n\nfunction truncate(s: string, max: number): string {\n if (s.length <= max) return s;\n return `${s.slice(0, max - 1)}…`;\n}\n\n// kleur wraps strings in ANSI escape codes; padEnd needs the visible width.\nconst ANSI_RE = /\\u001B\\[[0-9;]*m/g;\nfunction visibleLength(s: string): number {\n return s.replace(ANSI_RE, \"\").length;\n}\nfunction padEndVisible(s: string, width: number): string {\n const pad = Math.max(0, width - visibleLength(s));\n return s + \" \".repeat(pad);\n}\n","import { existsSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport { parseLockfile } from \"./extractors/lockfile.js\";\nimport type { PackageInstance } from \"./types.js\";\n\nexport interface WhyOptions {\n cwd?: string;\n lockfile?: string | string[];\n}\n\nexport interface WhyMatch {\n package: PackageInstance;\n chain: string[];\n note?: string;\n}\n\nexport interface WhyResult {\n packageName: string;\n lockfiles: string[];\n matches: WhyMatch[];\n}\n\nexport function explainWhy(\n packageName: string,\n options: WhyOptions = {},\n): WhyResult {\n const cwd = resolve(options.cwd ?? process.cwd());\n const lockfiles = options.lockfile\n ? normalizePaths(cwd, options.lockfile)\n : detectLockfiles(cwd);\n const packages = lockfiles.flatMap((path) => parseLockfile(path));\n const matches = packages\n .filter((pkg) => pkg.name === packageName)\n .map((pkg) => ({\n package: pkg,\n chain: inferChain(pkg),\n note: graphNote(pkg),\n }))\n .sort((a, b) => {\n const source = (a.package.sourceFile ?? \"\").localeCompare(\n b.package.sourceFile ?? \"\",\n );\n if (source !== 0) return source;\n return a.package.path.localeCompare(b.package.path);\n });\n\n return { packageName, lockfiles, matches };\n}\n\nfunction inferChain(pkg: PackageInstance): string[] {\n if (pkg.manager === \"npm\") {\n const chain = packageNamesFromNodeModulesPath(pkg.path);\n if (chain.length > 0) return chain;\n }\n return [pkg.name];\n}\n\nfunction graphNote(pkg: PackageInstance): string | undefined {\n if (pkg.manager === \"npm\") return undefined;\n if (pkg.direct) return \"direct dependency\";\n return `${pkg.manager ?? \"lockfile\"} lock entry; full parent chain is not available yet`;\n}\n\nfunction packageNamesFromNodeModulesPath(path: string): string[] {\n const parts = path.split(\"/\");\n const names: string[] = [];\n for (let i = 0; i < parts.length; i++) {\n if (parts[i] !== \"node_modules\") continue;\n const first = parts[i + 1];\n if (!first) continue;\n if (first.startsWith(\"@\")) {\n const second = parts[i + 2];\n if (!second) continue;\n names.push(`${first}/${second}`);\n i += 2;\n } else {\n names.push(first);\n i += 1;\n }\n }\n return names;\n}\n\nfunction detectLockfiles(cwd: string): string[] {\n const candidates = [\n \"package-lock.json\",\n \"npm-shrinkwrap.json\",\n \"pnpm-lock.yaml\",\n \"yarn.lock\",\n ].map((file) => join(cwd, file));\n return candidates.filter((candidate) => existsSync(candidate));\n}\n\nfunction normalizePaths(\n cwd: string,\n value: string | string[] | undefined,\n): string[] {\n if (!value) return [];\n const values = Array.isArray(value) ? value : [value];\n return [...new Set(values.map((path) => resolve(cwd, path)))];\n}\n\n"],"mappings":"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","names":["mkdirSync","writeFileSync","dirname","resolve","kleur","retryAfterMs","existsSync","statSync","dirname","resolve","join","existsSync","readFileSync","resolve","isRecord","readFileSync","join","readFileSync","join","basename","readFileSync","resolve","readFileSync","resolve","existsSync","readFileSync","dirname","join","resolve","readFileSync","lineOf","registryFromResolved","readFileSync","resolve","parseYaml","resolve","readFileSync","isRecord","lineOf","registryFromResolved","parseYaml","at","registryFromResolved","lineOf","isRecord","basename","readFileSync","basename","resolve","isRecord","lineOf","REQUEST_TIMEOUT_MS","mapWithConcurrency","retryAfterMs","resolve","resolve","dirname","join","existsSync","statSync","existsSync","readFileSync","join","resolve","at","requested","REGISTRY_URL","REQUEST_TIMEOUT_MS","fetchPackument","encodePackageName","spawn","existsSync","readdirSync","readFileSync","join","relative","resolve","PLACEHOLDER_RE","existsSync","writeFileSync","resolve","resolve","existsSync","writeFileSync","kleur","kleur","kleur","truncate","formatSummary","readFileSync","kleur","SEVERITY_COLOR","kleur","SEVERITY_ORDER","headerParts","formatHeader","formatSummary","renderTable","truncate","visibleLength","padEndVisible","ANSI_RE","existsSync","join","resolve","resolve","normalizePaths","detectLockfiles","join","existsSync","FAIL_ON_VALUES","POLICY_VALUES","kleur","resolve","mkdirSync","dirname","writeFileSync"]}