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.
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
$ npm install @ctrl/tinycolornpm error 403 Forbiddennpm 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}Enterprise setup
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.
What the firewall knows
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.
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.
Every ecosystem is tracked in the database. Those marked in amber can be routed through the firewall today, alongside OCI container registries.
@ctrl/transmission@7.3.1
403MAL-2025-47143
chalk@5.6.1
403MAL-2025-46969
@ctrl/deluge@7.2.2
403MAL-2025-47131
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.
1# deny by default, allow what you trust2*3!pkg:npm/react@*4!pkg:pypi/requests*5!pkg:go/github.com/spf13/*6!docker.io/library/nginx:*7 8# never, at any version9pkg:npm/@ctrl/tinycolor@*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.
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
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 compromiseRollout
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.
DevGuard is open source and can be self-hosted, so the proxy - and the packages it caches - can stay entirely inside your own infrastructure.