BytesafeDependency Firewall

Upstreams and caching

How a firewall resolves packages from multiple registries, why internal upstreams win, and what the cache flag does.

A firewall is not a package store. It hosts no packages of its own: it resolves them from upstreams, the registries listed in its configuration, and can cache copies of what it has served. Understanding how upstream responses are combined explains where any given version comes from, and why marking an upstream internal changes resolution.

How resolution works

For a package request, the firewall queries its upstreams for metadata and combines the results:

Resolve upstreams
Apply rules
Client
Firewall queries upstreamsrequest metadata from each
Internal upstreammetadata response
External upstream Ametadata response
External upstream Bmetadata response
Did any internal upstream return the package?
Keep internal responses only
Keep all responses
Merge and deduplicate versions
Versions-phase rules filter the list
Return result to client

Three properties follow:

  • An unreachable or failing upstream is skipped, not an error. A misconfigured upstream credential shows up as missing packages, not a failed install.
  • Each version is served once. Duplicate version numbers across upstreams are deduplicated in the merged list.
  • Rules see the upstream. Every candidate version carries which upstream it came from, which is what the upstreamId and internal selector fields match against.

Internal upstreams

Marking an upstream internal declares that it is the authority for the packages it hosts. The resolution consequence is the internal-wins step above: if any internal upstream knows a package name, external copies of that name are not served at all.

This is the structural defense against dependency confusion: an attacker publishing your internal package name on a public registry cannot outbid your registry with a higher version number, because the public copy never enters the merge.

Internal is about ownership and trust, not network location. A SaaS-hosted private registry is still internal in this sense.

Caching

Each upstream has a cache flag. When enabled, the firewall caches upstream responses, metadata for a short interval and fetched artifacts, so repeated installs do not re-fetch from the upstream every time.

Three details worth knowing:

  • Caching applies to internal upstreams, the registries you own. See Configure upstreams.
  • Maven Central is always cached (repo1.maven.org, repo.maven.apache.org), regardless of the flag.
  • Cache entries are tied to the firewall's config version, so a change to rules or upstreams is never answered from entries built under the previous version. The change itself propagates across the cluster within a few seconds.

A cache entry is a copy of what has passed through, not a package store: entries expire, nothing in them is addressable as a registry, and a cached artifact is still evaluated against the rules on every request.

Caching is about latency and upstream load. If a cached upstream is unreachable, the firewall can fall back to a stale cached response rather than failing the request, which softens a short outage. Do not plan around it as an availability guarantee: it only covers what has already been fetched and cached.

Publishing

Publishes are the reverse direction: the firewall receives the upload, runs upload phase rules on it, and forwards it to the upstream whose ID is set as the firewall's publishTarget, authenticating with that upstream's credentials. Publishing does not write to any other upstream.

On this page