Skip to content

Back to the catalog

AikidoSec/safe-chain
github.comrepo

AikidoSec/safe-chain

Aikido Safe Chain is an open-source local proxy and shell-alias wrapper for npm, yarn, pnpm, bun, pip, uv, poetry, pipx and pdm. It checks every package download, including deep dependencies, against the Aikido Intel malware feed and blocks malicious packages before install. It also enforces a configurable 48-hour minimum package age by suppressing too-new versions in registry metadata. It supports custom registries and a self-hosted malware-list mirror, and has CI/CD install recipes for GitHub Actions, Azure Pipelines, CircleCI, Jenkins, Bitbucket and GitLab.

TL;DR Free Aikido tool that proxies npm/PyPI installs on dev machines and CI, blocking known malware and packages newer than 48 hours.
Document

What it is

Aikido Safe Chain (release 1.5.25 in the page's install commands) is a free, tokenless tool that wraps package-manager commands so that every download is checked against the Aikido Intel malware feed and against a minimum-age rule. It covers npm, npx, yarn, pnpm, pnpx, rush, rushx, bun, bunx, pip, pip3, uv, uvx, poetry, pipx and pdm. It also intercepts python -m pip ... invocations. The page notes that Aikido's paid Device Protection product builds on it and adds central policy, approval workflows and MDM deployment (Jamf, Fleet, Iru).

How it works

  • A local proxy intercepts downloads from the npm registry and PyPI. For pip the page calls it a MITM proxy, and Safe Chain writes a temporary pip config to inject its certificate and proxy settings.
  • On a developer machine, shell aliases (Bash, Zsh, Fish, PowerShell, PowerShell Core) route commands through Safe Chain. In CI, the --ci flag installs executable shims on PATH instead.
  • The age check has two modes for both npm and PyPI: too-young versions are removed from registry metadata during resolution, and direct download requests that bypass metadata are blocked using a cached list of newly released packages.
  • Urgent CVE-fix releases that Aikido has confirmed malware-free are exempted from the age check.

What to do

Install with the checksum-verified script, then restart the terminal so the aliases load:

curl -fsSL https://github.com/AikidoSec/safe-chain/releases/download/1.5.25/install-safe-chain.sh -o /tmp/install-safe-chain.sh \
  && echo "83069f6db4215cccf6a26bdd6e65a5c2366b9d24322b2d5d2862d47385e56682  /tmp/install-safe-chain.sh" | sha256sum -c - \
  && sh /tmp/install-safe-chain.sh \
  && rm /tmp/install-safe-chain.sh

Verify with npm safe-chain-verify, which should print "OK: Safe-chain works!". Test blocking with npm install safe-chain-test or pip3 install safe-chain-pi-test. For CI, pass --ci to the installer. For a custom location such as a Docker image, pass --install-dir.

Configuration, in priority order of CLI flag, then environment variable, then ~/.safe-chain/config.json:

  • Age window: --safe-chain-minimum-package-age-hours=48 or SAFE_CHAIN_MINIMUM_PACKAGE_AGE_HOURS.
  • Age exclusions: SAFE_CHAIN_MINIMUM_PACKAGE_AGE_EXCLUSIONS="@aikidosec/*" or per-ecosystem minimumPackageAgeExclusions in config.
  • Private registries: SAFE_CHAIN_NPM_CUSTOM_REGISTRIES and SAFE_CHAIN_PIP_CUSTOM_REGISTRIES (comma-separated hosts).
  • Self-hosted feed: SAFE_CHAIN_MALWARE_LIST_BASE_URL. The mirror must serve /malware_predictions.json, /malware_pypi.json, /releases/npm.json and /releases/pypi.json.
  • Logging: --safe-chain-logging=silent|normal|verbose, plus optional file logging via SAFE_CHAIN_LOG_FILE.

For a team, put a safe-chain: section in the repo's .aikido file. It can set only minimumPackageAgeHours, customRegistries and minimumPackageAgeExclusions. It merges over the home config, and arrays are combined. scanTimeout, malwareListBaseUrl and logFile* cannot come from the project file.

Caveats

  • If you rely on a pip.conf, set PIP_CONFIG_FILE explicitly. Otherwise Safe Chain's temporary config may override your user-level pip config and your index-url and credentials will not be picked up. Your original file is never modified.
  • Jenkins does not persist PATH changes from setup, so add ~/.safe-chain/shims and ~/.safe-chain/bin to PATH explicitly. Bitbucket needs the same PATH export. GitLab needs Safe Chain baked into the build image with the PATH set.
  • The Jenkins recipe assumes Node.js and npm are already on the agent.
  • If malware is detected, Safe Chain prompts you to exit the command rather than silently continuing.
  • The age check can be bypassed entirely by configuration. That is a risk if a developer lowers it locally and the project config does not pin it.
  • The page's claim of "no build data shared" is unverified here. The tool does fetch the malware list and a new-packages list from malware-list.aikido.dev unless you mirror it.

Technologies named here

Techniques named here

  • Minimum package age check