Product

Overview

How it works Watch it work All 35 features Screenshots How ForgeRepo™ is secured

Keep bad packages out

Malware scanning Typosquat detection Dependency confusion protection Cooling off new releases Allow lists and block lists

When something goes wrong

Kill switch Who has it Lockdown and degraded modes Vulnerability monitoring

Developers and approvals

Requests and auto approve Check, walk and review Waivers Dry run
Formats

Languages

Private npm registry PyPI proxy and private index Private NuGet feed and proxy Maven repository proxy RubyGems mirror Composer and Packagist proxy

Apple, containers and Linux

CocoaPods CDN mirror Swift package registry Docker registry mirror RPM mirror for dnf and yum APT mirror for Debian and Ubuntu

Use it as

An npm firewall Artifacts, SBOMs and lifecycle More than one node SSO, roles and allow lists
Learn

Guides

Learn secure development Secure coding Secure pipelines Unsafe vs safe Security and development

Supply chain

Supply chain attacks, 2016 to 2026 Software supply chain security
Compare Side by side, all four ForgeRepo™ vs JFrog ForgeRepo™ vs Sonatype ForgeRepo™ vs Cloudsmith
Docs

Start

Getting started Download All documentation Questions

For developers

npm setup pip setup docker login Push a Docker image CI basics

For administrators

First setup Rules and their order Six incidents, walked through Backup and upgrade
Pricing Install it

Keep bad packages out

Allow lists and block lists for every package type

Every package your developers and pipelines pull goes past one set of rules. Whitelist mode lets through only what somebody approved. Blacklist mode lets through everything except what you name. Either way the rule is enforced on the server, for every request.

A rule is a name, a kind (allow or deny), an optional version range and a priority. The name can be exact (lodash), a scope (@acme/*) or a wildcard. The range takes anything npm itself understands: 1.1.1, 1.2.*, ^1.2.0, ~1.2.0, >=4.17.21 or 1.2.3 || 1.4.5. PyPI rules take the specifiers pip uses, and image rules take tags, globs like 1.25.*, or digests.

The other types each take their own spelling, and a bare version always means exactly that version:

  • NuGet: ids ignore case, so Microsoft.Extensions.* is a rule. Ranges take NuGet's brackets ([13.0,14.0)), floating versions (13.*) and comparators (>=13.0 <14).
  • Maven: names are groupId:artifactId, like org.apache.logging.log4j:log4j-core or org.apache.maven.plugins:*, with Maven's brackets such as [2.17,2.18).
  • RubyGems and CocoaPods: gem requirements like ~> 4.0 or >= 1.2, < 2.
  • Composer: vendor/name or symfony/*, with composer.json constraints like ^3.0.
  • Swift: identities like apple.swift-log or apple.*, with semver ranges.
  • RPM and APT: exact package names, and exact versions or comparators like >=3.0.7, compared the way rpm and dpkg compare them.

When two rules match, the higher priority wins, then the narrower scope, then the exact name over a pattern, then deny over allow. If nothing matches, whitelist mode blocks and blacklist mode allows. It is the same order every time, and the Rules page says so at the top.

The part that makes this work in practice is the metadata. When npm asks which versions of a package exist, the versions a rule does not allow are removed from the answer and latest moves back to the newest allowed one. Every other type works the same way: the PyPI project page, the NuGet version list, maven-metadata.xml, the gem info file, the pod shards, the Composer and Swift release lists are all trimmed to what the rules allow. RPM and APT mirrors do this when set to a filtered index, and otherwise refuse the download. So npm install lodash quietly picks an allowed version rather than failing. A lockfile that names a blocked version by hand gets a 403 with the reason in it.

Case is handled on purpose. A deny matches whatever the case, because a block you can dodge by typing Event-Stream is not a block. An allow matches exactly, because approving JSONStream must not also approve jsonstream, which is a different package by a different author.

packages.example.com/_admin/
The Rules page. Type, pattern, kind, version range, priority, and an optional application and environment.

In short

  • Whitelist or blacklist, with the whitelist as the default
  • Exact names, scopes like @acme/*, wildcards and each type's own version ranges
  • Blocked versions are removed from every type's version list or index before the client sees them
  • Rules can be limited to one application, one environment, or both
  • Audit only learning mode serves everything and opens a request for whatever no rule covers
  • Import and export as JSON or CSV with no limit on size, in one transaction
  • Cache the ticked rules downloads approved versions now, so the kill switch has something to serve

In the documentation

Goes well with

  • Requests and auto approve A blocked install opens a request. Clean ones can approve themselves, risky ones wait for a person.
  • Dry run Replay up to 90 days of real downloads against a rule before anybody switches it on.
  • Tokens, apps and environments Every download is tied to a token, an application and an environment. Rules can be scoped to them.

One container, about two minutes

A Linux box with Docker, or one without it, and a reverse proxy for TLS. The installer does the rest and it is safe to run twice. Free, MIT licensed, nothing to sign up for.