How it works
Package Firewall sits between your package managers and the public registries, on your own machine. It decides, version by version, what is allowed to download.
1. Interception
On macOS a network extension routes connections for the public registry hosts to a local proxy, pf-proxyd. Only these hosts are intercepted:
- npm:
registry.npmjs.org,registry.yarnpkg.com,registry.npmmirror.com - PyPI:
pypi.org,files.pythonhosted.org
The proxy terminates TLS with a certificate authority that is created on your machine and name-constrained to those hosts, so it can't be used to read any other traffic. Its private key is held by a separate system service and never written to disk in a form that can be exported.
2. Checks
For every package version, the proxy asks two questions:
- Is it on the malware list? The list is built from OSV malicious-package (MAL) reports for npm and PyPI, signed with Ed25519 and refreshed automatically. The proxy verifies the signature before using a list and refuses to roll back to an older one.
- Is it at least 48 hours old? The publish time comes from the registry's own metadata. If it can't be verified, the version is treated as too new.
3. Filtering metadata
When npm, pnpm, Yarn or Bun fetch a package's metadata, blocked versions are removed before the response reaches them, and dist-tags such as latest are repaired so they never point at a blocked version. PyPI metadata (the Simple index and JSON API) is filtered the same way for pip, uv and Poetry. Your package manager then resolves to a safe version on its own, with no errors.
4. Enforcing downloads
Tarballs and wheels are checked again at download time, so a lockfile or a direct URL can't skip the rules. A blocked download gets 403 Forbidden. If the proxy can't reach a decision, for example because the malware list is missing, the download is refused rather than let through.
5. Exceptions
Sometimes you need a release from this morning. The local allow list lets you allow one exact version on your machine, after confirming with Touch ID. Every allow is recorded in the activity history.
6. What's already installed
A scan runs every day over package manager caches and project folders and flags any package on the malware list that was installed before protection started, or restored from a cache without a download.
What isn't covered yet
- Packages restored from a local cache skip the download check; the daily scan covers them instead.
- Private registries, mirrors other than the hosts above, direct tarball URLs and Git dependencies.
- Ecosystems other than npm and PyPI.
Private registries and org-wide policy are part of the team features now in development.