BytesafeDependency Firewall

Enforce firewall use

Make the firewall the only route to public packages, and detect the clients that are still going around it.

A firewall only tells you what your builds pulled if your builds cannot pull from anywhere else. A developer with a stale machine-level config, a CI job with a hardcoded registry URL, or a lockfile written before the migration all resolve straight from the public registry, and the firewall never sees it.

There is no single setting that closes this. Organizations reduce the risk in different ways, depending on how much control they have over developer machines, build agents, and the network.

This page covers two that work well together and cover most setups. Treat them as a starting point rather than a complete list. Some organizations also block the main public registry hosts on the network so that a misconfigured client fails instead of resolving around the firewall, which works for those few hosts but is harder to carry through once mirrors, vendor feeds, and private hosting services are in the picture.

Commit the client configuration to the repository

Client configuration committed to the repository travels with every clone and every CI checkout. Machine-local configuration does not, and it is the usual reason one developer's build behaves differently from everyone else's.

For each ecosystem you use, commit the registry or index configuration at the repository root. The ecosystem pages show the file and its contents per client.

Commit the configuration, never the token. Every client can read its credential from an environment variable, so the committed file names the variable and the access token stays in each developer's shell and in your CI secret store.

Two things decide whether that configuration actually covers you.

The firewall has to be the only source

Package managers can be configured with several package sources at once, and will fall back between them or query them in parallel. If the public registry is still configured next to the firewall, some installs will be answered by it, and those installs never reach your rules. Nothing appears broken, which is what makes this easy to miss.

Every ecosystem has a way of saying this is the only source: replacing the index rather than adding a second one, clearing inherited sources before adding yours, or defining a mirror that covers every repository. That is the setting you want, and the ecosystem pages name it for each client.

Partial routing leaves the rest unchecked

Some clients can send only part of your dependencies to the firewall, typically the packages under one namespace or prefix, and leave everything else going directly to the public registry. That is occasionally deliberate, but it means only that slice is checked. The packages most likely to carry a supply-chain problem are the ones nobody chose by name, and those are exactly the ones outside the slice.

Route the whole ecosystem through the firewall unless you have a specific reason not to. If you do scope it, write down what is excluded, because the exclusion will not be visible in the firewall's own logs.

Confirm the firewall is in the path

An empty firewall log is not evidence that everything is going through the firewall. It is equally consistent with nothing going through it, because a request that matches no rule is not logged.

Log every request while you check. Add a rule matching all packages with { "block": false, "log": true }, run a build, and confirm entries appear:

{
  "id": "log-all-traffic",
  "executionPhase": "download",
  "selector": {},
  "ruleEffect": { "block": false, "log": true },
  "description": "Record every artifact request"
}

Depend on a package only the firewall can serve. Some organizations publish a small marker package to an internal upstream and depend on it from their projects. Because the name exists nowhere else, a build that resolves it must have gone through the firewall, and a build that cannot find it is pointed somewhere else. That turns a question about configuration into a build that either passes or fails, which CI can answer on every run.

Read the records you already have

  • Observations show which package versions the firewall actually served over a period. A dependency your team clearly uses that never appears is worth chasing.
  • Lockfiles record where each artifact came from. Entries pointing at a public registry host mean that install resolved around the firewall, and they keep doing so until the lockfile is regenerated.
  • Metrics show request volume per firewall. A number that does not move while a team is building is the clearest signal of all.

Once the log-everything rule has served its purpose, decide whether to keep it. It records every request, which is the point, and it costs a log entry per request.

Internal packages are unaffected

Making the firewall the only source does not cut off your own registry: point the firewall at it as an internal upstream, and internal names resolve from it in preference to any public package of the same name. Clients keep one source, and you keep the guarantee.

On this page