Note
The Python version of SCFW is deprecated and is maintained only for security updates. It remains available on the v3 branch.
Supply Chain Firewall (SCFW) is a command-line tool for preventing the installation of malicious npm and PyPI packages. It is intended primarily for use by engineers to protect their development workstations from compromise in a supply-chain attack.
Given a command for a supported package manager, Supply Chain Firewall collects all package targets that would be installed by the command and evaluates them against known-malicious and compromised open source packages.
Interested in SCFW for your business use-case? Enroll as a design partner.
In local mode, SCFW identifies malicious packages using the open-source malicious-software-packages-dataset and OSV.dev API. Local mode is useful for experimenting, single-developer mode.
SCFW can use Datadog Code Security as a backend, allowing you to define custom ALLOW or BLOCK policies that apply to all of your SCFW deployment from Datadog. The outcomes of completed runs of the scfw CLI are also reported into Code Security, providing valuable observability into how package managers and third-party code are used across your fleet. Datadog only sees package metadata (ecosystem, name, version, artifact source) and the commands being run: no package source code is ever reported to Datadog by Supply Chain Firewall.
Features:
- Datadog Security Research's threat intelligence feed, in addition to public ones.
- Centralized policy management allowing to manage in which situations to allow or block a package installation across a fleet of developer endpoints.
- Centralized logging, so you can be alerted when a developer attempts to install a malicious package that gets blocked.
Supply Chain Firewall is distributed as a single Go binary with no runtime dependencies.
Download the binary for your operating system and architecture from the latest GitHub release. Before running these commands, replace the value of scfw_expected_checksum with the SHA-256 checksum published for that binary on the release page:
# Replace this placeholder with the checksum from the release page.
$ scfw_expected_checksum="<expected-sha256-checksum>"
# Detect the operating system used in the release artifact name.
$ case "$(uname -s)" in
Darwin) scfw_os=darwin ;;
Linux) scfw_os=linux ;;
*) echo "Unsupported operating system: $(uname -s)" >&2; exit 1 ;;
esac
# Detect the CPU architecture used in the release artifact name.
$ case "$(uname -m)" in
x86_64) scfw_arch=amd64 ;;
arm64|aarch64) scfw_arch=arm64 ;;
*) echo "Unsupported architecture: $(uname -m)" >&2; exit 1 ;;
esac
# Download the binary for the detected platform.
$ scfw_binary="scfw-${scfw_os}-${scfw_arch}"
$ curl -fLO "https://github.com/DataDog/supply-chain-firewall/releases/latest/download/${scfw_binary}"
# Calculate the downloaded binary's checksum.
$ scfw_actual_checksum=$(sha256sum "${scfw_binary}" | awk '{print $1}')
# Stop if the downloaded binary does not match the published checksum.
$ if [ "${scfw_actual_checksum}" != "${scfw_expected_checksum}" ]; then
echo "Checksum verification failed" >&2
exit 1
fi
# Install the verified binary in a directory on PATH.
$ chmod +x "${scfw_binary}"
$ sudo install "${scfw_binary}" /usr/local/bin/scfwIf Go 1.26 or later is installed, install SCFW with go install:
$ go install github.com/DataDog/supply-chain-firewall/scfw@latestThis installs the scfw binary to $(go env GOPATH)/bin; be sure that directory is on your PATH.
To check whether the installation succeeded, run the following command and verify that you see output similar to the following.
$ scfw --help
Supply Chain Firewall, a tool for preventing the installation of malicious software packages.
Usage:
scfw [command]
Available Commands:
configure Configure the environment for using Supply Chain Firewall.
run Run a package manager command through Supply Chain Firewall.
...To get the most out of Supply Chain Firewall, run the scfw configure command after installation to configure the environment. Via this command, users can also ensure that all commands for supported package managers are passively run through scfw.
# --dd-* parameters are optional
$ scfw configure \
--alias-npm \
--alias-pip \
--alias-poetry \
--dd-api-key=<your-api-key> \
--dd-app-key=<your-app-key> \
--dd-site=<your-dd-site>When passing these values via shell variables, e.g. in scripts, prefer this = form: --dd-api-key=$DD_API_KEY --dd-app-key=$DD_APP_KEY --dd-site=$DD_SITE.
This does two things:
- Adds shell aliases to your
.bashrc,.bash_profile,.zshrc, and.zprofile(whichever already exist) so thatnpm,pip/pip3, and/orpoetrytransparently run throughscfw. Restart your shell (or source the relevant rc file) for the aliases to take effect. - Optionally, if provided, stores your Datadog API key and application key securely in your system's keychain, so credentials don't need to be kept in plaintext or supplied on every command.
scfw configure is idempotent and may be re-run at any time to change your configuration. Alias options are additive, so aliases configured by an earlier invocation remain in place unless their corresponding --remove-alias-* option is passed. The command manages its own clearly indicated block of your shell rc files and never touches anything else you've added.
Available configure options:
| Flag | Description |
|---|---|
--alias-npm |
Add a shell alias to run all npm commands through scfw. |
--remove-alias-npm |
Remove the npm shell alias managed by scfw. |
--alias-pip |
Add shell aliases to run all pip/pip3 commands through scfw. |
--remove-alias-pip |
Remove the pip/pip3 shell aliases managed by scfw. |
--alias-poetry |
Add a shell alias to run all poetry commands through scfw. |
--remove-alias-poetry |
Remove the poetry shell alias managed by scfw. |
--scfw-home |
Directory Supply Chain Firewall can use as a local cache. |
--remove |
Remove all Supply Chain Firewall managed configuration. |
--dd-api-key |
Datadog API key used for policy evaluation and reporting. |
--dd-app-key |
Datadog application key used for policy evaluation and reporting. |
--dd-site |
Datadog site parameter used for policy evaluation and reporting (default: datadoghq.com). |
When inspecting package manager commands, Datadog credentials and the Datadog site parameter may alternatively be provided via environment variables DD_API_KEY, DD_APP_KEY, and DD_SITE, respectively. This is particularly useful in CI environments where secrets are injected per job. Environment variables always take precedence over stored credentials sourced from the system keychain.
| Package manager | Supported versions | Inspected subcommands |
|---|---|---|
| npm | >= 7.0 | install (including aliases) |
| pip | >= 22.2 | install |
| poetry | >= 1.7 | add, install, sync, update |
Supply Chain Firewall may only know how to inspect some of the "installish" subcommands for its supported package managers. These are shown in the above table. Any other subcommands are always allowed to run.
Note that scfw will refuse to run inspected subcommands on an unsupported version of a supported package manager. In order to get the most out of scfw, please verify that you are running a supported version of your package manager and upgrade accordingly before using this tool.
Before uninstalling, be sure to run scfw configure --remove to remove any Supply Chain Firewall-managed configuration you may have previously added to your environment.
$ scfw configure --removeThen remove the scfw binary, e.g. by deleting it from $(go env GOPATH)/bin if it was installed via go install.
To inspect a package manager command with Supply Chain Firewall, prepend scfw run -- to the command you intend to run:
$ scfw run -- npm install react
added 1 package in 226ms
$ scfw run -- pip install some-evil-package
Package some-evil-package-1.0.0:
- Datadog Security Research has determined that package some-evil-package-1.0.0 is malicious.
The command was blocked. No changes have been made.
Note that, once shell aliases have been configured via scfw configure --alias-npm/--alias-pip/--alias-poetry, the explicit scfw run -- prefix is no longer needed: commands for these package managers run through scfw automatically.
scfw run supports the following options:
| Flag | Description |
|---|---|
--executable |
Package manager executable to use for running commands (default: environmentally determined). |
--error-on-block |
Treat blocked commands as errors, i.e. exit non-zero (useful for scripting and CI). |
--allow-on-warning |
Non-interactively allow commands with only warning-level findings, instead of prompting. |
--block-on-warning |
Non-interactively block commands with only warning-level findings, instead of prompting. |
The SCFW_ON_WARNING environment variable (allow or block) has the same effect as --allow-on-warning/--block-on-warning and takes precedence over them when set, which is useful for enforcing a consistent policy across a CI environment without changing every invocation. In a non-interactive context (no attached terminal), a warning-level result is blocked by default unless one of these mechanisms is used, so a warning can never be silently ignored.
We welcome contributions to Supply Chain Firewall. Refer to the CONTRIBUTING guide for instructions on setting up for development.
