Safeguard
Supply Chain

Blocking Malicious Packages at the Proxy Level With Artifactory

Once a compromised dependency reaches a laptop or CI runner, you are doing incident response. Blocked at the Artifactory proxy, it is a log line. Here is the configuration that makes that happen.

Safeguard Team
Product
6 min read

The cheapest place to stop malicious packages is the proxy: route every npm, PyPI, Maven, and container pull through Artifactory, then configure its remote repositories so that known-bad, unvetted, or suspiciously new packages are never cached in the first place. Everything downstream of the proxy inherits the protection for free. Everything upstream of it, you cannot control anyway.

This post covers the concrete Artifactory malicious package defenses that work: repository layout, exclude patterns, scan-gated downloads, and the dependency confusion settings most teams miss.

Why block malicious packages at the proxy level?

Because the proxy is the only chokepoint you actually own. Developer laptops, CI runners, and container builds all resolve dependencies at slightly different times with slightly different caches. Trying to police each of them individually is a losing game; forcing them all through one Artifactory instance turns thousands of resolution points into one policy decision.

The history of registry attacks shows why timing matters. When ua-parser-js was compromised in October 2021, the malicious versions shipped a credential stealer and were live on npm for hours before removal. The event-stream incident in 2018 hid a wallet-targeting payload inside a transitive dependency for weeks. In January 2022, the maintainer of colors and faker intentionally published sabotaged versions that broke thousands of builds in a day. In each case, teams that pulled straight from the public registry got the bad version the moment they built. Teams behind a proxy with even a modest quarantine window mostly did not.

A proxy also gives you the audit trail. When the next incident hits, "which of our builds downloaded version 1.2.99 and when" is a single query against Artifactory's download logs instead of a company-wide forensic exercise.

How do you configure Artifactory to block malicious packages?

Four layers, in order of effort:

  1. Repository layout. Create a remote repository per public registry (npmjs, PyPI, Maven Central), local repositories for internal packages, and a virtual repository that aggregates them. Clients — .npmrc, pip.conf, settings.xml — point only at the virtual repository. Nothing in your fleet should be able to name registry.npmjs.org directly; enforce that with egress rules.
  2. Include and exclude patterns. Every remote repository supports path patterns. Exclude your internal package names and scopes from all remotes (more on that below), and consider an include-list model for high-risk ecosystems: some teams only proxy packages that have passed an intake review, which turns the registry firehose into a curated catalog.
  3. Scan-gated downloads. JFrog Xray policies can be set to block download rather than merely warn, so an artifact with a malicious-package flag, a critical CVE, or a banned license never leaves quarantine. JFrog Curation extends this to block packages before they are fetched at all, using rules like minimum package age, maintainer changes, and known-malicious lists. A minimum-age rule of 7 to 14 days alone would have blunted most of the npm compromises of the last five years, because malicious versions are usually yanked within days.
  4. Cache bans. Blocking new downloads is not enough if the bad version is already cached. When an advisory lands, ban the version and purge it from the remote cache so builds fail loudly instead of resolving a poisoned artifact from local storage.

How does the proxy stop dependency confusion?

Dependency confusion — demonstrated at scale by Alex Birsan in 2021 — works because a resolver asked for an internal package name will happily accept a higher-versioned impostor from the public registry. The proxy is exactly where you break that.

  • Reserve a namespace: publish all internal packages under one npm scope or Maven group, and register the scope publicly so nobody else can claim it.
  • Exclude that namespace from every remote repository. If a request for @yourco/anything reaches the npmjs remote, Artifactory should refuse to forward it, full stop.
  • Order resolution in the virtual repository so local repositories are consulted before remotes, and never let a remote answer for a name that exists locally.

With those three settings, the confusion attack has no path: internal names resolve internally or fail.

What does proxy-level blocking still miss?

Be honest about the limits. A proxy enforces policy on package identity and metadata; it does not understand your code.

  • A compromised version of an established, well-aged package (the xz-style long game) passes age and reputation rules.
  • Malicious postinstall scripts execute on the client, not the proxy — you still want install-script controls and lockfile discipline in CI.
  • The proxy cannot tell you whether a vulnerable function is actually reachable from your code, which is what decides urgency when a real advisory drops. That is SCA's job, running against your lockfiles and call graph, not the registry.

Treat the proxy as the outer wall: it stops the drive-by attacks cheaply and buys you time on everything else. Layer scanning and continuous monitoring of new advisories behind it, and you have defense in depth rather than a single bet.

FAQ

Can Artifactory detect malicious packages by itself?

Base Artifactory is storage and proxying; detection comes from what you attach to it. Exclude patterns and repository layout are native, while malicious-package intelligence requires Xray or Curation (or an external scanner gating promotion between repositories).

Do exclude patterns protect against typosquatting?

Only partially. Excludes reliably protect names you control (internal scopes), but you cannot enumerate every plausible typo of every public package. Minimum-age rules and known-malicious feeds catch most typosquats because they are new and short-lived by nature.

Should CI bypass the proxy for speed?

No — CI is the highest-value target because its credentials and artifacts flow to production. Point CI at the same virtual repository, and let Artifactory's caching make it faster than the public registry, not slower.

What about packages that were cached before they were flagged?

Rescan the cache when advisories land, ban the affected versions, and purge them so subsequent builds fail instead of silently resolving the cached copy. A blocked build is annoying; a poisoned artifact in production is a breach.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.