Dependency Firewall

The dependency firewall that
blocks threats before they reach your code.

DevGuard sits between your builds and the public registries. Every npm, Go, PyPI and container image request is checked against the malicious package database first - known-bad releases are refused on the way in, not reported after the fact.

Screening every request to

registry.npmjs.orgproxy.golang.orgpypi.orgdocker.ioghcr.io
ci-runner — build
$
npm error 403 Forbidden
npm error X-Malicious-Package: blocked
{
"error": "Forbidden",
"message": "This package has been blocked
by the malicious package firewall",
"reason": "Package @ctrl/tinycolor is flagged
as malicious (ID: MAL-2025-47141)",
"blocked": true
}
237 726malicious-package advisories every request is checked against, as of September 2026.

Enterprise setup

Close the direct route. Keep exactly one way in.

In a typical enterprise deployment, public registries are unreachable from developer machines, CI runners and container builds. DevGuard’s dependency proxy is the one permitted egress - nothing enters unchecked.

Internal network
Developer machinesCI/CD pipelinesContainer builds
Direct access blocked
DevGuard
Dependency Firewall
Public registries
registry.npmjs.orgnpmproxy.golang.orgGopypi.orgPyPIdocker.io · ghcr.io · quay.ioOCI
Four ecosystems, one gateway
npm, Go modules, PyPI and OCI container images are proxied through the same control point. Container pulls are served on OCI-spec-compliant endpoints, so unmodified OCI clients work.
Scoped per organisation, project or repository
Each scope gets its own proxy URL and its own rule set. A platform team can set a baseline centrally while an individual repository tightens it further.
A cache that verifies what it serves
Packages are cached on disk and every cache read is checked against its SHA-256 hash. The malicious database is consulted before the cache.

What the firewall knows

Built on the public record of malicious packages.

DevGuard tracks the MAL advisories published through OSV, the feed the OpenSSF malicious-packages project contributes to. The database is rebuilt several times a day and every DevGuard instance syncs it automatically, so a newly named package is refused without anyone touching a configuration.

MAL advisories in the database0

The malicious package database

Advisories and the specific versions they affect, imported from OSV. The database is rebuilt several times a day and running instances sync it on their own.

npm221 544234 071
PyPI11 73216 873
Go1818

Coverage by ecosystem

Every ecosystem is tracked in the database. Those marked in amber can be routed through the firewall today, alongside OCI container registries.

proxy.blocked

@ctrl/transmission@7.3.1

403

MAL-2025-47143

chalk@5.6.1

403

MAL-2025-46969

@ctrl/deluge@7.2.2

403

MAL-2025-47131

Every refusal, named

A blocked request carries the advisory that caused it, so the developer who hit it can see what was found rather than a generic network error.

dependency-proxy-configs
1# deny by default, allow what you trust
2*
3!pkg:npm/react@*
4!pkg:pypi/requests*
5!pkg:go/github.com/spf13/*
6!docker.io/library/nginx:*
7
8# never, at any version
9pkg:npm/@ctrl/tinycolor@*
resolved requests
  • pkg:npm/react@19.2.0allow
  • pkg:pypi/requests@2.32.3allow
  • pkg:npm/left-pad@1.3.0deny
  • pkg:npm/@ctrl/tinycolor@4.1.1deny

Policy in a file everyone already knows how to read

Rules follow gitignore semantics: one pattern per line, # for comments, * for wildcards, ! to allow an exception, and the last matching rule wins. Deny everything and open it up package by package, or block a handful of names.

72h
publishedheldinstallable
  • chalk@5.6.1held
  • react@19.2.0installable

A cooldown before anything new gets in

A minimum release age is configurable per scope, so a version has to have been published for that long before a build may pull it - the window in which a compromised release is usually caught and withdrawn.

Why it matters

The npm worm of 2025 spread faster than any review could.

In September 2025 a self-replicating worm - later called Shai-Hulud - used stolen maintainer credentials to publish malicious versions of widely used npm packages, then harvested more credentials from every machine that installed them. Packages such as chalk, debug and the @ctrl scope were compromised at versions teams had every reason to trust.

Read the CISA advisory on the npm compromise
291
advisories published across 15 and 16 September 2025, the two days the first wave moved through npm.
1 433
advisories published in the two weeks from 20 November 2025, when the second wave hit.

Rollout

One line per package manager.

The proxy speaks each ecosystem’s native protocol, so adopting it is a registry setting - not a migration. Point the package manager at the DevGuard URL for your organisation, project or repository and every request from then on is screened. The documentation walks through each ecosystem step by step.

npm
registry in .npmrc
Go
GOPROXY
Python
index-url in pip.conf
Container images
the registry you pull from

DevGuard is open source and can be self-hosted, so the proxy - and the packages it caches - can stay entirely inside your own infrastructure.

Put a control point in front of your supply chain.

We are glad to walk through how the dependency firewall fits your network, what an egress policy around it looks like and how other teams have rolled it out across their pipelines.