Supply Chain · Security Audit

MCP server supply chain audit security

Before you install a community MCP server — or before you publish one — run a supply chain audit. This page covers the six-step process for Node.js/npm servers and the equivalent for Python/pip servers, including what to look for in postinstall scripts, how to verify lockfile integrity, and how to check provenance attestations.

Why MCP servers need supply chain audits

MCP servers run inside LLM agent processes with access to credentials, filesystem, and network. A compromised transitive dependency in an MCP server has direct access to every API key loaded into process.env and can intercept tool call arguments before validation. The supply chain attack surface is larger than for a standard web API because MCP servers are often installed by individuals (not security teams) and run locally without network egress controls.

Six-step npm supply chain audit

  1. Check lockfile presence and currency. A missing or stale package-lock.json means the installed dependency tree is non-deterministic — every npm install may resolve different versions. Verify: git log --oneline package-lock.json | head -1 — if the last lockfile update was more than 30 days ago and package.json has changed since, the lockfile is stale.
  2. Run npm audit. npm audit --json queries the npm vulnerability database against every package in your tree. Focus on HIGH and CRITICAL findings. A finding in a transitive dependency that cannot be updated (because the direct dependency hasn't released a fix) should be documented in SECURITY.md with a mitigation note.
    npm audit --json | jq '.vulnerabilities | to_entries[] |
      select(.value.severity == "high" or .value.severity == "critical") |
      { name: .key, severity: .value.severity, via: .value.via }'
  3. Enumerate packages with postinstall scripts. Postinstall scripts run arbitrary code at install time with the same permissions as the installing user. Any package with a postinstall script that is not a known legitimate use case (native binary compilation, certificate generation) deserves manual review.
    cat package-lock.json | node -e "
      let d = '';
      process.stdin.on('data', c => d += c);
      process.stdin.on('end', () => {
        const lock = JSON.parse(d);
        const pkgs = lock.packages || {};
        for (const [path, pkg] of Object.entries(pkgs)) {
          if (pkg.scripts?.postinstall || pkg.scripts?.install) {
            console.log(path, '→', pkg.scripts.postinstall || pkg.scripts.install);
          }
        }
      });
    "
  4. Check provenance attestations for direct dependencies. npm 9.5+ supports Sigstore-backed provenance attestations that link a published version to the CI run that built it. Packages without attestations were built and published outside of a verifiable CI pipeline — higher risk.
    node -e "
      const pkg = require('./package.json');
      const { execSync } = require('child_process');
      for (const name of Object.keys(pkg.dependencies || {})) {
        try {
          const info = JSON.parse(execSync('npm info ' + name + ' --json').toString());
          const hasProvenance = !!info?.dist?.attestations?.length;
          console.log(hasProvenance ? '✓' : '✗', name);
        } catch {}
      }
    "
  5. Verify the install method in CI. Check your CI pipeline config for npm install (vulnerable — resolves semver ranges) vs npm ci (safe — uses lockfile exactly). Replace every occurrence of npm install in CI scripts, Dockerfiles, and deployment pipelines with npm ci.
  6. Generate and commit an SBOM. A CycloneDX SBOM creates a reviewable record of every package in the tree at a point in time. Diff SBOMs between releases to see exactly what changed in the dependency tree — not just in your own code.
    npx @cyclonedx/cyclonedx-npm --output-format JSON --output-file sbom.json
    git add sbom.json && git commit -m "chore: regenerate SBOM"

Python/pip supply chain audit (for Python MCP servers)

Python MCP servers face equivalent risks. The pip hash-checking mode is the strongest control:

# requirements.txt with hash verification
requests==2.31.0 \
  --hash=sha256:58cd2187423839... \
  --hash=sha256:942c5a758f98d7...

# Install with hash verification enforced
pip install --require-hashes -r requirements.txt

Generate a hash-pinned requirements file from your current environment: pip-compile --generate-hashes requirements.in. Run pip-audit for vulnerability scanning equivalent to npm audit: pip-audit -r requirements.txt.

SkillAudit findings

CRITICAL No lockfile committed to repository — dependency tree non-deterministic, cannot audit what version will be installed
HIGH CI pipeline uses npm install — new compromised versions can be pulled automatically on each build
HIGH Unresolved HIGH or CRITICAL vulnerabilities in npm audit
MEDIUM Postinstall scripts present in >5 transitive packages without documented justification
MEDIUM No SBOM file in repository — dependency transparency unavailable for security review

Run a SkillAudit scan for automated supply chain analysis. SkillAudit checks lockfile presence and currency, npm audit status, postinstall script count, and SBOM availability in one scan. See also: MCP server supply chain risk deep-dive and MCP server SBOM security.