Skip to content

feat(audit): add registry signature verification#11405

Merged
zkochan merged 19 commits into
pnpm:mainfrom
colinfristoe:feat/audit-signatures
May 1, 2026
Merged

feat(audit): add registry signature verification#11405
zkochan merged 19 commits into
pnpm:mainfrom
colinfristoe:feat/audit-signatures

Conversation

@colinfristoe

@colinfristoe colinfristoe commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

Summary

As reported in #7909, I tried running pnpm audit signatures, assuming a similar behavior as npm audit signatures. The positional signatures argument was accepted but ignored, so pnpm ran a normal vulnerability audit instead of doing any registry signature verification.

This PR routes signatures as an pnpm audit subcommand and adds ECDSA registry signature verification for installed packages. The implementation reuses the lockfile audit indexing logic to collect the installed package/version pairs, fetches the registry signing keys from /-/npm/v1/keys, fetches full packuments for packages from registries that provide keys, and verifies each dist.signatures entry against the signed ${name}@${version}:${integrity} payload. Unknown audit subcommands now fail explicitly instead of being silently ignored.

NPM's implementation of npm audit signatures checks sigstore provenance attestations in addition to registry ECDSA signatures. While these would provide an additional trust signal about how a package was built and published, I chose to leave them out of this PR. They have a larger implementation and policy surface: TUF state, certificate transparency verification, attestation bundle fetching, identity checks, and evolving attestation formats.

Test Plan

  • Run pnpm init in a new project. Add a .npmrc file with registry=https://registry.npmjs.org/.
  • Run pnpm add lodash && pd audit signatures. Confirm the command succeeds with:
audited 1 package

1 package has a verified registry signature
  • Run pnpm remove lodash. Run node fake-registry.mjs (see below) and update .npmrc with registry=http://127.0.0.1:4873.
  • Run pnpm add valid@1.0.0 && pd audit signatures. Confirm the command succeeds with:
audited 1 package

1 package has a verified registry signature
  • Run pnpm add missing@1.0.0 && pd audit signatures. Confirm the command fails with:
audited 2 packages

1 package has a verified registry signature

1 package is missing registry signature but the registry is providing signing keys:

┌───────────────┬────────────────────────┐
│ missing@1.0.0 │ http://127.0.0.1:4873/ │
└───────────────┴────────────────────────┘
  • Run pnpm add tampered@1.0.0 && pd audit signatures. Confirm the command fails with:
audited 3 packages

1 package has a verified registry signature

1 package is missing registry signature but the registry is providing signing keys:

┌───────────────┬────────────────────────┐
│ missing@1.0.0 │ http://127.0.0.1:4873/ │
└───────────────┴────────────────────────┘


1 package has an invalid registry signature:

┌────────────────┬────────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ tampered@1.0.0 │ http://127.0.0.1:4873/ │ tampered@1.0.0 has an invalid registry signature with keyid SHA256:3O1jPM9qsCevotALUCf5xcwcDYW6IOm7bzozhEngVJ4 │
└────────────────┴────────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘


Someone might have tampered with this package since it was published on the registry!
  • In the same project, run pd audit signatures --json. The JSON output should look like:
{
  "audited": 3,
  "invalid": [
    {
      "integrity": "sha512-ajg3qLh9/4tt+64vlvZezWkdgRQ90u8yPr6y6WIS1vTOooZZSXWBbGH2K0ttGtVgN5QuJ/lcZmrsnluXe9MKvw==",
      "name": "tampered",
      "reason": "tampered@1.0.0 has an invalid registry signature with keyid SHA256:3O1jPM9qsCevotALUCf5xcwcDYW6IOm7bzozhEngVJ4",
      "registry": "http://127.0.0.1:4873/",
      "resolved": "http://127.0.0.1:4873/tampered-1.0.0.tgz",
      "version": "1.0.0"
    }
  ],
  "missing": [
    {
      "name": "missing",
      "registry": "http://127.0.0.1:4873/",
      "version": "1.0.0",
      "integrity": "sha512-YcKW2tvRGzAGBdd00Outu+u3LKx3eouD7LmyLMc/mLWiO+/3Irw8WfXjlQEwPno6I+Ne9FxF956nKtb3qQZiAg==",
      "resolved": "http://127.0.0.1:4873/missing-1.0.0.tgz"
    }
  ],
  "verified": 1
}
  • Run pd audit unknown -> this should now fail with:
 ERR_PNPM_AUDIT_UNKNOWN_SUBCOMMAND  Unknown audit subcommand: unknown

Simulating an NPM registry

// fake-registry.mjs
// sig-registry.mjs
import http from 'node:http'
import fs from 'node:fs'
import os from 'node:os'
import path from 'node:path'
import crypto from 'node:crypto'
import { execFileSync } from 'node:child_process'

const port = Number(process.env.PORT || 4873)
const version = '1.0.0'

const { publicKey, privateKey } = crypto.generateKeyPairSync('ec', {
  namedCurve: 'P-256',
})

const pub = publicKey.export({ type: 'spki', format: 'der' })
const keyid =
  'SHA256:' +
  crypto.createHash('sha256').update(pub).digest('base64').replace(/=+$/, '')

function integrityFor(data) {
  return 'sha512-' + crypto.createHash('sha512').update(data).digest('base64')
}

function makePackage(name, kind) {
  // Create a tiny real npm package and let `npm pack` produce the tarball.
  // This keeps the fixture close to actual registry metadata without needing
  // to hand-roll .tgz files.
  const dir = fs.mkdtempSync(path.join(os.tmpdir(), `${name}-`))
  fs.writeFileSync(path.join(dir, 'package.json'), JSON.stringify({ name, version }))
  fs.writeFileSync(path.join(dir, 'index.js'), `module.exports = ${JSON.stringify(name)}\n`)

  const [{ filename }] = JSON.parse(
    execFileSync('npm', ['pack', '--json'], { cwd: dir, encoding: 'utf8' })
  )

  const tarball = fs.readFileSync(path.join(dir, filename))
  const integrity = integrityFor(tarball)
  const shasum = crypto.createHash('sha1').update(tarball).digest('hex')

  const dist = {
    shasum,
    integrity,
    tarball: `http://127.0.0.1:${port}/${filename}`,
  }

  // The npm registry signature payload is:
  //
  //   `${name}@${version}:${dist.integrity}`
  //
  // For `valid`, sign the actual integrity.
  // For `tampered`, sign a different but valid-looking sha512 integrity.
  // That simulates a signature that may have been valid for a previous
  // package artifact, but no longer matches the current tarball metadata.
  // For `missing`, omit `dist.signatures` entirely.
  if (kind !== 'missing') {
    const oldTarball = Buffer.from(`previous contents for ${name}@${version}\n`)
    const signedIntegrity =
      kind === 'tampered'
        ? integrityFor(oldTarball)
        : integrity

    const payload = `${name}@${version}:${signedIntegrity}`

    dist.signatures = [{
      keyid,
      sig: crypto.sign('sha256', Buffer.from(payload), privateKey).toString('base64'),
    }]
  }

  return {
    filename,
    tarball,
    packument: {
      name,
      'dist-tags': { latest: version },
      versions: { [version]: { name, version, dist } },
    },
  }
}

const packages = {
  valid: makePackage('valid', 'valid'),
  tampered: makePackage('tampered', 'tampered'),
  missing: makePackage('missing', 'missing'),
}

const json = value => JSON.stringify(value)

http.createServer((req, res) => {
  const url = decodeURIComponent(req.url)

  // npm/pnpm signature verifiers fetch trusted registry keys here.
  // Keeping this endpoint present is what makes `missing` meaningful:
  // the registry claims to support signatures, but the package lacks one.
  if (req.method === 'GET' && url === '/-/npm/v1/keys') {
    res.setHeader('content-type', 'application/json')
    return res.end(json({
      keys: [{
        expires: null,
        keyid,
        keytype: 'ecdsa-sha2-nistp256',
        scheme: 'ecdsa-sha2-nistp256',
        key: pub.toString('base64'),
      }],
    }))
  }

  // Package metadata endpoint, e.g. GET /valid.
  const name = url.slice(1)
  if (req.method === 'GET' && packages[name]) {
    res.setHeader('content-type', 'application/json')
    return res.end(json(packages[name].packument))
  }

  // Tarball endpoint, e.g. GET /valid-1.0.0.tgz.
  const pkg = Object.values(packages).find(p => url === `/${p.filename}`)
  if (req.method === 'GET' && pkg) {
    res.setHeader('content-type', 'application/octet-stream')
    return res.end(pkg.tarball)
  }

  res.statusCode = 404
  res.end('not found')
}).listen(port, '127.0.0.1', () => {
  console.log(`registry=http://127.0.0.1:${port}`)
  console.log('packages: valid@1.0.0, tampered@1.0.0, missing@1.0.0')
})

Summary by CodeRabbit

  • New Features

    • Added pnpm audit signatures command to verify installed package ECDSA registry signatures; respects scoped registries, skips registries without signing keys, supports JSON or colored CLI reports, and returns non-zero when signatures are missing/invalid. CLI help updated.
  • Documentation

    • README updated with signature verification behavior, skipping rules, and limitations (no provenance attestations).
  • Tests

    • Added tests covering verification, missing/invalid signatures, registry key discovery, expiry, and reporting.
  • Chores

    • Updated spellcheck allowlist and package/config metadata.

@colinfristoe colinfristoe marked this pull request as ready for review April 30, 2026 15:37
@colinfristoe colinfristoe requested a review from zkochan as a code owner April 30, 2026 15:37
@zkochan

zkochan commented May 1, 2026

Copy link
Copy Markdown
Member

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented May 1, 2026

Copy link
Copy Markdown
✅ Actions performed

Full review triggered.

@coderabbitai

coderabbitai Bot commented May 1, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a new pnpm audit signatures subcommand and a signature-verification subsystem that fetches per-registry ECDSA P‑256 public keys from /-/npm/v1/keys, obtains package packuments, verifies signatures over ${name}@${version}:${integrity}, respects scoped registries, skips registries without keys, and reports verified, invalid, or missing.

Changes

Cohort / File(s) Summary
Release metadata & config
\.changeset/audit-signatures.md, cspell.json, deps/compliance/commands/tsconfig.json, deps/compliance/commands/package.json, deps/compliance/audit/package.json
Adds changeset announcing the feature; extends cspell allowlist (keyid, keytype, nistp); adds TS project reference for registry picker; adds p-limit dependency.
Documentation
deps/compliance/audit/README.md
Documents verifySignatures() flow: discover per-registry signing keys, fetch full packuments, verify signatures against ${name}@${version}:${integrity}, and describe skip behavior for registries without keys.
Signature verification implementation
deps/compliance/audit/src/verifySignatures.ts, deps/compliance/audit/src/index.ts
New verifySignatures implementation with exported interfaces and types; groups packages by registry, fetches /-/npm/v1/keys, caches packuments, runs concurrent ECDSA P‑256 verification, and returns { audited, verified, invalid, missing }. Index re-exports the verify API.
Signature verification tests
deps/compliance/audit/test/verifySignatures.ts
Adds comprehensive Jest tests that generate ECDSA keys and mock registry key and packument endpoints to exercise success, malformed/missing/unknown-keyid/expired-key, 404-skip, and other scenarios.
Audit command wiring & context
deps/compliance/commands/src/audit/audit.ts, deps/compliance/commands/src/audit/auditContext.ts
Adds signatures subcommand routing; extracts lockfile/context loading into loadAuditContext(); adds createAuditNetworkOptions() and maps networkConcurrency option.
Audit signatures command & reporting
deps/compliance/commands/src/audit/signatures.ts
New auditSignatures() command: builds targets (uses pickRegistryForPackage), prepares auth/network options, calls verifySignatures, renders JSON or CLI report, and sets nonzero exit when any invalid/missing.
Audit command tests & fixtures
deps/compliance/commands/test/audit/index.ts, deps/compliance/commands/test/audit/fixtures/has-signatures/package.json
Adds tests and fixture verifying CLI audit signatures behavior with mocked registries/keys and unknown-subcommand rejection tests.

Sequence Diagram(s)

sequenceDiagram
    actor CLI as pnpm CLI
    participant Cmd as Audit Command
    participant Verifier as verifySignatures
    participant Registry as Registry
    participant Crypto as Crypto

    CLI->>Cmd: run `pnpm audit signatures`
    Cmd->>Cmd: loadAuditContext(), build package list, pick registries
    Cmd->>Registry: GET /-/npm/v1/keys (per registry)
    Registry-->>Cmd: signing keys or 400/404 (no keys)
    Cmd->>Verifier: verifySignatures(packages, getAuthHeader, opts)
    Verifier->>Registry: GET /<package> (packument, fullMetadata)
    Registry-->>Verifier: packument with dist.integrity, tarball, signatures, time
    loop per package (concurrent, limited)
      Verifier->>Crypto: verify `${name}@${version}:${integrity}` with public key
      Crypto-->>Verifier: valid / invalid
    end
    Verifier-->>Cmd: { audited, verified[], invalid[], missing[] }
    Cmd->>CLI: render report and exitCode
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I hopped through keys and packument trails,
I checked each sig with tiny tails,
I nudged the bytes and counted rounds,
Each package stamped on checkered grounds,
— signed and safe beneath the moon.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(audit): add registry signature verification' directly and clearly describes the main change: adding registry signature verification functionality to the audit command.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@deps/compliance/audit/src/verifySignatures.ts`:
- Around line 102-118: The code currently assumes version.dist.signatures is a
well-formed array and calls verifyPackageSignatures which can throw on malformed
input; before calling verifyPackageSignatures (in verifySignatures.ts where
version, signatures and verifyPackageSignatures are used) add defensive
validation that version?.dist?.signatures is an Array and that each entry has
the expected shape (e.g., required properties used by verifyPackageSignatures);
if the shape is wrong, push the package into result.invalid or result.missing
with an appropriate reason (e.g., "Malformed signatures metadata") and return
instead of invoking verifyPackageSignatures.

In `@deps/compliance/commands/src/audit/signatures.ts`:
- Around line 74-77: The message "No dependencies were installed from a registry
with signing keys" is emitted when result.audited === 0 even if there are
recorded issues (e.g., result.invalid), which is misleading; update the
condition that pushes that message to only run when the result is truly empty by
checking audited === 0 AND that there are no entries in result.invalid (and any
other issue arrays used in this module, e.g., result.failed or result.errors)
before pushing to lines; locate the block that currently tests result.audited
and change it to a combined check (e.g., result.audited === 0 &&
(!result.invalid || result.invalid.length === 0) && (!result.failed ||
result.failed.length === 0)) so the "No dependencies..." message only appears
for an actually empty result state.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: fc77cfef-889d-43d1-90da-f8a97b401d34

📥 Commits

Reviewing files that changed from the base of the PR and between 3b12eb2 and db84e35.

⛔ Files ignored due to path filters (2)
  • deps/compliance/commands/test/audit/fixtures/has-signatures/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (14)
  • .changeset/audit-signatures.md
  • cspell.json
  • deps/compliance/audit/README.md
  • deps/compliance/audit/package.json
  • deps/compliance/audit/src/index.ts
  • deps/compliance/audit/src/verifySignatures.ts
  • deps/compliance/audit/test/verifySignatures.ts
  • deps/compliance/commands/package.json
  • deps/compliance/commands/src/audit/audit.ts
  • deps/compliance/commands/src/audit/auditContext.ts
  • deps/compliance/commands/src/audit/signatures.ts
  • deps/compliance/commands/test/audit/fixtures/has-signatures/package.json
  • deps/compliance/commands/test/audit/index.ts
  • deps/compliance/commands/tsconfig.json

Comment thread deps/security/signatures/src/verifySignatures.ts
Comment thread deps/compliance/commands/src/audit/signatures.ts Outdated
@zkochan zkochan force-pushed the feat/audit-signatures branch from a378a0a to ac30f3d Compare May 1, 2026 20:45

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
deps/compliance/commands/test/audit/index.ts (1)

396-427: 💤 Low value

Consider extracting shared test utilities.

The createSigningKey and mockRegistryKey helper functions are duplicated between this file and deps/compliance/audit/test/verifySignatures.ts. While test file duplication is sometimes acceptable for self-containment, if these helpers are expected to be reused across more test files, consider extracting them to a shared test utilities module.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@deps/compliance/commands/test/audit/index.ts` around lines 396 - 427, Extract
the duplicated helpers createSigningKey and mockRegistryKey into a new shared
test utilities module and replace the local definitions in both
deps/compliance/commands/test/audit/index.ts and
deps/compliance/audit/test/verifySignatures.ts with imports; specifically, move
the crypto-based createSigningKey function (including its return shape: keyid,
publicKey, sign) and the mockRegistryKey implementation that uses
getMockAgent().get(...).intercept(...).reply(...) into the shared module, export
them, update both files to import createSigningKey and mockRegistryKey
(preserving types such as ReturnType<typeof createSigningKey> where used), and
ensure any references to getMockAgent remain valid by importing it where needed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@deps/compliance/commands/test/audit/index.ts`:
- Around line 396-427: Extract the duplicated helpers createSigningKey and
mockRegistryKey into a new shared test utilities module and replace the local
definitions in both deps/compliance/commands/test/audit/index.ts and
deps/compliance/audit/test/verifySignatures.ts with imports; specifically, move
the crypto-based createSigningKey function (including its return shape: keyid,
publicKey, sign) and the mockRegistryKey implementation that uses
getMockAgent().get(...).intercept(...).reply(...) into the shared module, export
them, update both files to import createSigningKey and mockRegistryKey
(preserving types such as ReturnType<typeof createSigningKey> where used), and
ensure any references to getMockAgent remain valid by importing it where needed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: cb972617-8531-4e08-bc3a-dbeb51e504ee

📥 Commits

Reviewing files that changed from the base of the PR and between a378a0a and ac30f3d.

⛔ Files ignored due to path filters (1)
  • deps/compliance/commands/test/audit/fixtures/has-signatures/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (14)
  • .changeset/audit-signatures.md
  • cspell.json
  • deps/compliance/audit/README.md
  • deps/compliance/audit/package.json
  • deps/compliance/audit/src/index.ts
  • deps/compliance/audit/src/verifySignatures.ts
  • deps/compliance/audit/test/verifySignatures.ts
  • deps/compliance/commands/package.json
  • deps/compliance/commands/src/audit/audit.ts
  • deps/compliance/commands/src/audit/auditContext.ts
  • deps/compliance/commands/src/audit/signatures.ts
  • deps/compliance/commands/test/audit/fixtures/has-signatures/package.json
  • deps/compliance/commands/test/audit/index.ts
  • deps/compliance/commands/tsconfig.json
✅ Files skipped from review due to trivial changes (8)
  • deps/compliance/audit/package.json
  • deps/compliance/commands/package.json
  • deps/compliance/commands/tsconfig.json
  • cspell.json
  • deps/compliance/commands/test/audit/fixtures/has-signatures/package.json
  • .changeset/audit-signatures.md
  • deps/compliance/audit/README.md
  • deps/compliance/audit/src/verifySignatures.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • deps/compliance/audit/src/index.ts

A registry returning malformed PEM key material made verifier.verify throw
synchronously, rejecting the Promise.all and crashing the whole audit run.
Treat any verify failure as an invalid signature for that single package.
@zkochan zkochan added this to the v11.1 milestone May 1, 2026
Both fetchRegistryKeys and fetchPackument repeated the same JSON.parse +
PnpmError wrapping pattern. Collapse into a single helper.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
deps/compliance/audit/src/verifySignatures.ts (1)

193-198: ⚡ Quick win

Reduce getPackument parameter count to meet repo guideline.

getPackument currently takes 4 arguments; wrap context dependencies into a single object.

♻️ Proposed refactor
-      const packument = await getPackument(pkg, getAuthHeader, opts, packumentCache)
+      const packument = await getPackument(pkg, { getAuthHeader, opts, packumentCache })

+interface GetPackumentContext {
+  getAuthHeader: GetAuthHeader
+  opts: VerifySignaturesOptions
+  packumentCache: Map<string, Promise<Packument | undefined>>
+}
+
 async function getPackument (
   pkg: SignaturePackage,
-  getAuthHeader: GetAuthHeader,
-  opts: VerifySignaturesOptions,
-  packumentCache: Map<string, Promise<Packument | undefined>>
+  ctx: GetPackumentContext
 ): Promise<Packument | undefined> {
+  const { getAuthHeader, opts, packumentCache } = ctx
   const cacheKey = `${pkg.registry}:${pkg.name}`
   let packument = packumentCache.get(cacheKey)
   if (!packument) {
As per coding guidelines, "limit functions to two or three arguments or use a single options object instead".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@deps/compliance/audit/src/verifySignatures.ts` around lines 193 - 198, The
function getPackument currently takes four separate parameters (pkg:
SignaturePackage, getAuthHeader: GetAuthHeader, opts: VerifySignaturesOptions,
packumentCache: Map<string, Promise<Packument | undefined>>) — refactor it to
accept a single options object (e.g., { pkg, getAuthHeader, opts, packumentCache
}) and update the function signature and body to destructure those fields; then
update all call sites to pass the new options object instead of four positional
args and adjust any TypeScript types/interfaces to reference the new options
type so callers and inference remain correct.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@deps/compliance/audit/src/verifySignatures.ts`:
- Around line 193-198: The function getPackument currently takes four separate
parameters (pkg: SignaturePackage, getAuthHeader: GetAuthHeader, opts:
VerifySignaturesOptions, packumentCache: Map<string, Promise<Packument |
undefined>>) — refactor it to accept a single options object (e.g., { pkg,
getAuthHeader, opts, packumentCache }) and update the function signature and
body to destructure those fields; then update all call sites to pass the new
options object instead of four positional args and adjust any TypeScript
types/interfaces to reference the new options type so callers and inference
remain correct.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 1eca668b-cf39-4120-b14b-1b6a83725fca

📥 Commits

Reviewing files that changed from the base of the PR and between c9f9943 and c6c6240.

📒 Files selected for processing (1)
  • deps/compliance/audit/src/verifySignatures.ts

zkochan added 3 commits May 1, 2026 23:44
Move verifySignatures from @pnpm/deps.compliance.audit into a new
@pnpm/deps.compliance.signatures package. Vulnerability auditing and
signature verification are conceptually distinct trust subsystems, and
sigstore provenance verification is in scope for a future change — keeping
all signature work in its own package avoids growing the audit module into
two unrelated concerns.
The signature verification implementation moved to
@pnpm/deps.compliance.signatures; that package's README documents the
behavior. The audit package no longer needs to mention it.
Place the new signature verification package under deps/security/ rather
than deps/compliance/. Compliance is a fuzzy fit for tamper detection;
security is the right home, and sigstore provenance verification (future
scope) will live alongside it. Existing audit/license/sbom packages stay
where they are — this only changes where the new package lands.
@zkochan zkochan enabled auto-merge (squash) May 1, 2026 22:03
@zkochan zkochan merged commit 6ac06cb into pnpm:main May 1, 2026
9 checks passed
@welcome

welcome Bot commented May 1, 2026

Copy link
Copy Markdown

Congrats on merging your first pull request! 🎉🎉🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants