Secure Package Management

Secure Package Management

Hardening NPM and Python dependencies against supply chain attacks. Protect your builds from malicious packages and compromised maintainers.

Most of this is free and straightforward: lockfiles, package-manager policy, and stricter install settings can materially reduce risk without buying an expensive vendor platform.

Recent Notice: Axios npm compromise

Axios maintainers confirmed that [email protected] and [email protected] were malicious npm releases published through a compromised maintainer account on March 31, 2026. Those versions pulled in plain-crypto-js and were live for roughly three hours before removal.

If your lockfile or install logs show either affected Axios version or plain-crypto-js, treat that workstation or CI runner as potentially compromised, not merely out of date.

Quick Check

grep -E "axios@(1\\.14\\.1|0\\.30\\.4)|plain-crypto-js" package-lock.json yarn.lock 2>/dev/null
  • Downgrade or repin to [email protected] or [email protected].
  • Remove node_modules/plain-crypto-js/ and reinstall from a known-good lockfile.
  • Rotate credentials, tokens, and secrets exposed to that machine or CI job.
  • Review network and EDR telemetry for connections to sfrclak[.]com or 142.11.206.73:8000.
  • Prefer delaying newly published packages in CI and on developer workstations so short-lived malicious releases are less likely to land.

This repository's current package-lock.json has an empty packages object and does not show an Axios install, but the broader guidance still matters for any Node environment you operate elsewhere.

Notable Supply Chain Attacks

Real-world incidents that demonstrate why supply chain security is critical:

March 31, 2026
Axios npm compromise
Compromised maintainer account led to malicious publication of [email protected] and [email protected], which pulled in plain-crypto-js and dropped a cross-platform trojan. Post-mortem
Late February to March 2026
TeamPCP Supply Chain
Multi-stage campaign targeting Trivy, KICS, LiteLLM, and Telnyx via compromised maintainers.
August to October 2025
PhantomRaven npm
126 typosquatted packages, 86,000+ downloads targeting developer credentials.
Late November 2025
Shai-Hulud 2.0
796 packages compromised, 25,000+ repositories affected.
September 2025
Shai-Hulud npm Worm
Self-replicating worm compromised hundreds of npm packages starting around September 14.
September 8, 2025
Chalk/Debug
18 high-download packages compromised, live for approximately two hours.
August 26 to 27, 2025
Nx Attack
Malicious versions published, secrets exfiltrated rapidly within 24 hours.
March 29, 2024 (Discovered)
xz Utils Backdoor
Multi-year maintainer infiltration, backdoor inserted in releases 5.6.0 and 5.6.1 (February to March 2024). Disclosure
January 31 to April 1, 2021
Codecov
Bash uploader backdoored, undetected for just over two months.
2018
EventStream
Malicious dependency chain led to cryptocurrency theft attempts via compromised maintainer.

Hardening NPM and Python Dependencies: Mitigating Supply Chain Attacks

Open-source supply chain attacks are a significant and evolving threat to modern software development. Attackers frequently target build tools and local developer environments rather than waiting to exploit application code in production. By compromising maintainer accounts, using typosquatting, or exploiting dependency confusion, malicious code is injected directly into public registries.

In both NPM and PyPI, the risky path is any install flow that executes dependency-controlled code: Node lifecycle scripts such as preinstall and postinstall, and Python source builds that invoke PEP 517 backends or legacy setup.py. That code often runs with access to developer secrets, CI tokens, and internal package infrastructure.

Effective hardening combines strict lockfiles, delayed adoption of newly published releases, explicit approval of dependency build steps, and extra isolation for higher-risk installs.

1. JavaScript/TypeScript: Using pnpm

pnpm v10 is a strong default for Node projects because dependency lifecycle scripts are blocked unless you explicitly approve them. It also includes built-in controls for release-age delays, trusted build approvals, and blocking exotic transitive dependency sources. See the pnpm supply chain security guide and the settings reference.

Action: Commit a pnpm Policy to the Repository

Keep the security policy in pnpm-workspace.yaml so developers and CI runners enforce the same rules.

Enable pnpm and Migrate Project

# Enable pnpm via Corepack (Node.js 16.17+)
corepack enable pnpm

# Migrate an existing project
rm -rf node_modules package-lock.json
pnpm import  # Generates pnpm-lock.yaml

Project Security Policy (pnpm-workspace.yaml)

# Delay adoption of brand-new releases
minimumReleaseAge: 1440

# Block git/tarball transitive dependencies
blockExoticSubdeps: true

# Fail installs when unreviewed dependency build scripts appear
strictDepBuilds: true

# Approve only the dependency builds you trust
allowBuilds:
  esbuild: true

# Optional when your workflow supports pnpm trust signals
# trustPolicy: no-downgrade
Approving dependency builds: Use pnpm approve-builds to review pending scripts, then commit the resulting allowBuilds policy. Avoid relying on global ignore-scripts=true as the main pnpm workflow in v10; it is broader than necessary and also disables your project's own scripts.

2. Python: Using uv

Standard pip workflows can execute arbitrary code when an installation falls back to a source distribution. That execution path now commonly runs through PEP 517 build backends, not just legacy setup.py files.

uv is a fast Python package installer and resolver that acts as a drop-in replacement for pip. It simplifies dependency locking and strongly prefers wheels, but a high-trust workflow should still refuse source builds unless you explicitly allow them. See the uv compile guide and the uv CLI reference.

Action: Enforce Hashed, Wheel-Only Installs

For the strictest workflow, combine hash enforcement with --no-build so the install fails rather than building from an sdist.

Install uv

# Install uv (Mac/Linux)
curl -LsSf https://astral.sh/uv/install.sh | sh

Workflow for Secure Python Management

Virtual Environment and Lockfile

# Create an isolated virtual environment
uv venv
source .venv/bin/activate

# Generate a strictly hashed lockfile
# Input: requirements.in (e.g., requests==2.31.0)
uv pip compile requirements.in --generate-hashes -o requirements.txt

# Install exactly what is locked
# --require-hashes rejects unhashed entries
# --no-build fails if a wheel is unavailable and a source build would be required
uv pip sync requirements.txt --require-hashes --no-build

Instead of relying on a loose requirements.txt, use uv pip compile to lock exact versions and their cryptographic hashes. If a package is altered in PyPI without a version bump, the hash check will fail and the installation will be blocked. If a dependency is only available as an sdist, treat it as an exception and isolate that install path deliberately.

3. Dedicated Linux Isolation with bubblewrap

For Linux users, bubblewrap (bwrap) adds an extra boundary between install-time code and your workstation. The goal is to expose only the project directory and the cache or store paths you need, while hiding the rest of your real home directory from package scripts.

This is an advanced defense, not a transparent replacement for every install command. It is most useful for higher-risk dependency reviews, or for strict installs that already run from a warm cache or controlled internal registry.

Example Wrapper (~/bin/safe-install)

#!/bin/bash
set -eu

bwrap \
  --ro-bind /usr /usr \
  --ro-bind /bin /bin \
  --ro-bind /lib /lib \
  --ro-bind /lib64 /lib64 \
  --ro-bind /etc /etc \
  --proc /proc \
  --dev /dev \
  --tmpfs /tmp \
  --dir /work \
  --bind "$PWD" /work \
  --chdir /work \
  --dir /sandbox-home \
  --dir /sandbox-home/.cache \
  --dir /sandbox-home/.local \
  --dir /sandbox-home/.local/share \
  --dir /sandbox-home/.local/share/pnpm \
  --setenv HOME /sandbox-home \
  --setenv XDG_CACHE_HOME /sandbox-home/.cache \
  --ro-bind-try "$HOME/.cache/uv" /sandbox-home/.cache/uv \
  --ro-bind-try "$HOME/.cache/pnpm" /sandbox-home/.cache/pnpm \
  --ro-bind-try "$HOME/.local/share/pnpm/store" /sandbox-home/.local/share/pnpm/store \
  --unshare-ipc \
  --unshare-pid \
  --new-session \
  "$@"

Usage

safe-install uv pip sync requirements.txt --require-hashes --no-build
# or
safe-install pnpm install --frozen-lockfile
Network caveat: Add --unshare-net only when you already have a warm cache or an internal mirror reachable inside the sandbox. Otherwise dependency resolution and downloads will fail. For normal online installs, bubblewrap reduces host exposure but does not replace your package manager policy.

4. Scaling to Enterprise Environments (CI/CD)

Securing local developer machines is only part of the process; build pipelines require the same level of strictness.

Proxy Registries

Avoid pulling directly from public registries like npmjs.org or pypi.org in CI pipelines.

  • Route traffic through a private artifact proxy (e.g., JFrog Artifactory, Sonatype Nexus).
  • Enable quarantine policies on the proxy to automatically block packages with low reputation scores or newly published versions, effectively enforcing a network-wide release delay.

Enforce Configurations in CI Pipelines

GitHub Action: Enforcing uv Hashes and Wheel-Only Installs

steps:
  - uses: actions/checkout@v4
  - name: Install uv
    uses: astral-sh/setup-uv@v2
  - name: Install dependencies strictly
    run: uv pip sync requirements.txt --require-hashes --no-build

GitHub Action: Enforcing pnpm Policy

steps:
  - uses: actions/checkout@v4
  - uses: pnpm/action-setup@v3
    with:
      version: 10
  - name: Install with committed policy
    run: pnpm install --frozen-lockfile

Summary

Supply chain attacks exploit default configurations and implicit trust in package registries. Moving to pnpm with a committed build policy, using uv with hashed wheel-only installs, delaying newly published package versions, and adding optional Linux isolation with bwrap will significantly reduce exposure while preserving practical developer workflows.