Package Registries¶
Enforce a Minimum Package Age — Critical¶
Most malicious package versions are removed within hours, or a few days, of publication. A minimum-age policy can significantly reduce the impact of upstream compromises. pip, npm, uv, Dependabot, and Renovate all support this functionality. Target 7 days as a reasonable starting point.
Tip
Regardless of which registry is being used, make sure to apply the same package age policy to automation tools such as Dependabot and Renovate, otherwise they will continue opening PRs the package manager refuses to install.
npm (CLI 11.x+):¶
minimumReleaseAge config, value in minutes.
Ref: npm Docs — Config
pnpm (10.16+):¶
Set in pnpm-workspace.yaml. Defaults to 1440 in v11.
Ref: pnpm Docs — Mitigating supply chain attacks
uv:¶
--exclude-newer accepts RFC 3339 timestamps or relative durations (7d, 1w, P7D).
pyproject.toml.
Ref: uv Docs — Resolution
pip (26.0+):¶
--uploaded-prior-to is per-invocation only. Set it in CI and via pip.conf. There is no persistent project-level equivalent yet.
bun (1.3+):¶
# Only install package versions published at least 7 days ago
bun add @types/bun --minimum-release-age 604800 # seconds
minimumReleaseAge can also be set in bunfig.toml.
[install]
# Only install package versions published at least 7 days ago
minimumReleaseAge = 604800
Ref: bun Docs
yarn (4.10.0+):¶
npmMinimalAgeGate set in relative durations in .yarnrc.yml.
Ref: yarn Docs
Pin Dependencies by Hash — Critical¶
Version strings (e.g.: @v1 or @latest) alone don't verify content. Hash pinning avoids substitution attacks and ensures the integrity of dependencies.
Python:
pip install --require-hashes -r requirements.txt
# generate with: pip-compile --generate-hashes
# or: conda-lock for conda environments
npm:
# package-lock.json records content hashes automatically
# use npm ci in CI — never npm install (which allows lockfile mutation)
Hash pinning does add some management overhead. Use Dependabot or Renovate to automate this process.
Audit Installed Environments Regularly — High¶
pip-audit # checks installed packages against OSV/PyPI advisory DB
pip-audit -r requirements.txt --fix # auto-remediate where possible
npm audit # npm equivalent
Run pip-audit in CI on every dependency change. For environments with AWS tooling (boto3, botocore, awscli), treat any advisory as significant. These are primary credential-exfiltration targets in active campaigns (TeamPCP, March–May 2026).
Avoid Execution of Lifecycle Scripts — Medium¶
The TanStack malware and the PyTorch Lightning compromises both executed during npm install / pip install via lifecycle hooks (prepare, postinstall) and optionalDependencies. These run automatically with no additional prompt.
For npm, consider --ignore-scripts in CI for packages that don't require build steps, or use a lockfile auditor that flags new lifecycle scripts introduced between versions. Configure .npmrc with ignore-scripts=true as a project default.
Important
Traditionally, vulnerabilities in the build environment were ignored as they were not accessible or exploitable in the production deployment. This is no longer the case. The build environment itself is being exploited with significant impact.
Mirror Approved Packages Internally — Medium¶
An internal mirror with an explicit allowlist prevents typosquatting, dependency confusion attacks, and pulls from attacker-controlled PyPI mirrors.
Options: Artifactory, Nexus, devpi (Python), Verdaccio (npm). Configure pip via pip.conf index-url pointing to the internal mirror only; block direct egress to pypi.org/npmjs.com from CI runners.