BytesafeDependency Firewall

Rules and selectors

Field-level reference for firewall rules, selectors, selector functions, effects, and exceptions.

A firewall's policy consists of rules and exceptions inside its configuration. This page documents every field. For the mental model, see Rule evaluation.

Rule

{
  "id": "delay-new-versions",
  "disabled": false,
  "executionPhase": "versions",
  "selector": { "maxAgeHours": 168 },
  "ruleEffect": { "block": true, "log": true },
  "description": "Block versions younger than 7 days"
}
FieldTypeDescription
idstringUnique within the firewall. Referenced by exceptions and log entries
disabledbooleanSkip the rule without deleting it. Default false
executionPhasestringversions, download, or upload. A versions rule filters metadata responses and is also enforced when a client fetches a matching version directly. The dashboard rule form labels versions as filter versions
selectorobjectWhich packages the rule applies to. See below
ruleEffectobjectWhat happens on match. See below
descriptionstringFree text, shown in the dashboard and useful in logs

Evaluation order

Rules are not evaluated in configuration order. A request is evaluated against the cheaper rules first, so it pays for an expensive check only once every cheaper rule has allowed it. Rules of equal cost keep their configuration order, inherited rules before the firewall's own.

The first matching rule with block: true ends evaluation. Two things follow. The block a client sees, and the rule recorded in the log entry, is not necessarily the first rule you configured. And rules after it are never evaluated, never log, and cost the request nothing: a package stopped by a maxAgeHours rule is never scanned for malware.

Treat the order as an implementation detail that can change. If you need a rule to be evaluated regardless of what else matches, do not rely on ordering; give it a selector that cannot overlap with the others.

Selector

All set fields must match (AND). Empty fields match everything.

FieldTypeDescription
upstreamIdstringMatch packages served from this upstream
internalstring"internal", "external", or empty for any. Refers to whether the package resolves from an upstream marked internal
packageNamestringExact name, or one wildcard: prefix*, *suffix, or *
versionstringExact version, same wildcard support. Compared as text, never parsed
versionRangestringVersion range in the ecosystem's own notation, compared by version semantics. See Version ranges
maxAgeHoursnumberWhole hours. Matches versions published more recently than this. 168 is 7 days
functionobjectNamed selector function with options. See Selector functions

Wildcards

packageName and version accept at most one *, at the start or the end:

PatternMatches
@acme/*Everything in the @acme scope
*-betaNames ending in -beta
*Everything
lodashExactly lodash

Package name matching

packageName is matched in the naming form the ecosystem itself considers canonical, so a selector written the way the package appears on the registry works:

EcosystemMatching
NuGetCase-insensitive. Newtonsoft.Json and newtonsoft.json are the same package
PyPICase-insensitive, and -, _, . are interchangeable (PEP 503). zope.interface, zope_interface, and Zope.Interface all select zope-interface
npm, Maven, Go, condaExact, case-sensitive. React does not select react, and a Maven coordinate or Go module path must be written exactly

NuGet and PyPI have their own naming rules, and the firewall follows them. Everywhere else the name is matched as written, so a rule selects only the package it names.

Write the name the way the registry shows it. Most npm names are lowercase, but older ones such as JSONStream are not, and a rule written jsonstream does not match.

Wildcards are normalized the same way, so a NuGet selector Microsoft.* matches microsoft.extensions.logging. version is always compared exactly and is never normalized.

Exceptions use the same matching, which matters most there: an exception meant to unblock a package has to select it to take effect.

Version ranges

version and versionRange answer different questions. version compares text, so 1.* selects anything whose version string starts with 1.. versionRange parses both sides and compares them as versions, so >=1.2.0 <2.0.0 knows that 1.10.0 is newer than 1.9.0. Use version to match a naming shape, versionRange to match a real interval.

The two are independent fields. Set both and a version has to satisfy both.

Each ecosystem keeps its own range notation:

EcosystemNotationExamples
npmsemver ranges^1.2.0, ~1.2.3, >=1.2.0 <2.0.0, 1.x, 0.0.1 - 0.0.3 || >2.0.1
Gosemver ranges. A leading v on the package version is accepted, so v1.5.0 matches >=1.2.0 <2.0.0>=1.2.0 <2.0.0
NuGetsemver ranges, not NuGet interval notation>=1.0.0 <2.0.0
Maveninterval notation[1.0,2.0), [1.0,2.0]
PyPIPEP 440 specifiers>=1.0,<2.0, ~=1.4.2
condanot supported. The dashboard hides the field, and the API rejects a range on a conda firewall

Semver ranges support || for alternatives, X - Y for an inclusive span, x, X, or * as a wildcard component, and the operators =, !=, >, <, >=, <=, ~, ^. As in npm itself, a prerelease only matches a range that mentions a prerelease: 1.2.0-beta.1 does not satisfy ^1.2.0.

NuGet ranges go through the semver parser, deliberately, so that range syntax is the same across ecosystems that can share it. NuGet's own bracket intervals are therefore not accepted, and [1.0.0,2.0.0) is rejected when you save the rule. NuGet versions keep their own rules, so a four-part version such as 1.5.0.3 still parses and compares correctly.

Saving a rule whose range the ecosystem cannot parse fails with an error. At request time, a package version the ecosystem cannot parse does not match the range.

Selector functions

FunctionPhasesEcosystemsOptions
vulnerabilitiesdownloadall except CondamaxCvssScore (0 to 10), maxEpssScore (0 to 1)
malwaredownload, uploadallminimumConfidence (known_malware/suspicious/weak_indicator)

effort (known/deep)
install-scriptsdownload, uploadnpm, PyPInone
deprecatedversions, downloadnpm, PyPI, NuGetnone
unlistedversions, downloadNuGetnone
secretsuploadallignoredFiles, excludeTestFiles
licensedownloadall; Conda supports unknown onlylicenseSet, mode (deny/allow), unknown
trust-downgradeversionsnpmnone

Full semantics, options, and dashboard availability per function: Selector functions.

The API rejects rules and exceptions whose function does not support the firewall's ecosystem. Full config imports and rollbacks apply the same validation.

Effect

FieldTypeDescription
blockbooleanStop the request
logbooleanWrite a firewall log entry on every match

{ "block": false, "log": true } is a dry-run rule, the standard way to trial a policy.

Exceptions

An exception waives one rule for requests matching its own selector, with an expiry and a reason. Field-level reference: Exceptions.

On this page