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

Dependency confusion protection

Dependency confusion is simple and nasty. Somebody publishes a package on public npm, PyPI, NuGet or Docker Hub with the name of one of your internal packages, at a higher version, and your build picks theirs. ForgeRepo™ closes that door in two places.

Reserved names

Reserved names are the names that belong to you, for the four types you can publish to: npm scopes like @acme/*, PyPI projects or prefixes like acme-*, image namespaces like acme/*, and NuGet ids or prefixes like Acme.*. An exact name works too. PyPI names fold -, _, . and case the way PyPI does, and NuGet ids ignore case. A reserved name is never fetched from any upstream registry, not even a copy cached before it was reserved, and npm search leaves public packages under those names out. Until you publish something under a reserved name, asking for it answers 404 and says why.

Patterns, not a fallback chain

The obvious way to use more than one registry is to ask each in turn until one answers. That is exactly how dependency confusion works. ForgeRepo™ routes by pattern instead, for every package type: @acme/* can only ever come from the registry written against it, and so can com.acme:* on Maven or acme/* on Composer. RPM and APT mirrors are one address each, so there is nothing to confuse. A near miss goes to your supplier, who says 404, and the install stops. The match is case insensitive, so @ACME/thing cannot escape to the public registry either.

There is a fall back switch per registry for anybody who really wants the default asked on a 404. It is off unless you turn it on, and the docs tell you to leave it off for internal scopes.

Doing the routing here, rather than with a per scope line in every developer's .npmrc, also keeps the rules, the cache, the audit trail and the kill switch in the path for your internal packages.

packages.example.com/_admin/
Settings, Registries. Upstream registries with their patterns, and the reserved names beside them.

In short

  • Reserve exact names, scopes and prefixes for npm, PyPI, images and NuGet
  • Reserved names are never fetched from outside, not even from an old cached copy
  • One upstream per pattern for every type, first match wins, no silent fallback
  • Case insensitive routing, so a change of case cannot escape
  • Every change to the reserved list is in the audit trail

In the documentation

Goes well with

  • Private npm registry npm, pnpm, Yarn and Bun. Publish your own packages under reserved names, mirror the rest.
  • Typosquat detection lodahs, reqeusts, l0dash, python-numpy. Lookalike names are caught and warned about, or refused.
  • Allow lists and block lists Whitelist or blacklist by name, scope, wildcard or version range, for every type. A blocked version is not even listed to the client.

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.