Every package gets a decision before it reaches your build

Point your package managers at Kurra, a caching gateway for 14 ecosystems. It checks each package for known advisories, disallowed licenses, and look-alike names, then records the decision and its reason.

Activity

Sample data
  • Allowed3
  • Blocked3
  • Times in UTC
  1. Allowed@babel/core 7.25.2No matching advisory. License MIT is allowed.npm14:32:29
  2. Blockedorg.apache.logging.log4j:log4j-core 2.14.1Advisory GHSA-jfh8-c2jp-5v3q, critical. Fixed in 2.15.0.Maven14:32:24
  3. Allowedserde 1.0.210No matching advisory. License MIT is allowed.Cargo14:32:19
  4. Blockedexpresss 1.0.0Reputation check: the name resembles express.npm14:32:17
  5. Allowedrequests 2.32.3No matching advisory. License Apache-2.0 is allowed.PyPI14:32:12
  6. Blockedlodash 4.17.20Advisory GHSA-35jh-r3h4-6jhm, critical. Fixed in 4.17.21.npm14:32:07

Switch a client by changing its registry address

Your package managers work the way they do today. You change the address they use, and Kurra serves what the upstream has once it passes the checks.

  • A mirror fetches a package from its upstream the first time someone asks for it, then keeps a copy.
  • A hosted registry stores the packages your own teams publish and serves them like any other registry.
  • A token holds only the permissions and reaches only the registries you choose.
.npmrc
-registry=https://registry.npmjs.org/+registry=https://kurra.example.com/npm/npmjs/+//kurra.example.com/npm/npmjs/:_authToken=${KURRA_TOKEN}

Two decisions, each with a reason

Every package version is Allowed or Blocked. Kurra records the reason for each decision, so the person whose build stopped can see which rule stopped it.

Allowed

Nothing stopped it

Either no check found a reason to stop it, or a person allowed it. Kurra serves the package as normal.

Blocked

Kurra refuses to serve it

Clients get an error that names the rule and says what to do next. The reason names the cause, such as an advisory, a license, or an administrator.

A reason in the terminal, not a mystery

The message your package manager prints leads with the outcome, names the rule, and says what to do next.

People can also allow or block a package by hand. A manual decision never expires, and only a person can clear it.

$ npm install lodash@4.17.20
Access is denied: lodash 4.17.20 is blocked by Kurra policy because of advisory GHSA-35jh-r3h4-6jhm (critical).
Use 4.17.21 or later, or ask an administrator to review this decision.

14 ecosystems, one gateway

Tokens, roles, and activity work the same way in every ecosystem. Policy checks run wherever the ecosystem provides the data they need.

  • npmReputationRelease ageAdvisoriesLicenses
  • PyPIReputationRelease ageAdvisoriesLicenses
  • MavenReputationRelease ageAdvisoriesLicenses
  • NuGetReputationRelease ageAdvisoriesLicenses
  • GoReputationRelease ageAdvisoriesLicenses
  • CargoReputationRelease ageAdvisoriesLicenses
  • RubyGemsReputationRelease ageAdvisoriesLicenses
  • ComposerReputationRelease ageAdvisoriesLicenses
  • TerraformReputationRelease age
  • APTRelease ageAdvisories
  • APKRelease ageAdvisoriesLicenses
  • RPMRelease ageAdvisoriesLicenses
  • DockerReputation
  • HelmReputationRelease age

Compliance records, built in

Advisories, package licenses, software bills of materials, provenance, and an audit log are part of the cache itself, not a separate tool you add.

Advisories

Each version is checked against published advisories from npm and OSV the first time it is pulled. Cached versions are checked again later.

Package licenses

Set an SPDX allow list or deny list. If Kurra can’t read a package’s license, it allows the package.

Reputation check

Flags package names that look like typosquats of popular packages, before anything is fetched.

Minimum release age

Refuses a version until it has been published for the number of days you set. This covers every ecosystem except Docker and OCI Helm charts, which state no publish time.

Software bill of materials

Kurra generates a CycloneDX bill of materials the first time a Docker or Helm image is cached.

Upstream verification

Kurra checks the signatures, checksums, and attestations that upstream registries publish, and records the result. A file that doesn’t match a published checksum is never cached or served.

Provenance

For packages you host, Kurra verifies SLSA provenance from a Sigstore bundle you supply. It stores public keys and never signs anything.

Activity and audit log

Activity records each decision with its reason and the time it was made. The audit log behind it is tamper-evident.

Give each token only what it needs

A token can hold fewer permissions than its owner, but never more, and can reach only the registries you choose. It expires after 90 days unless you set another lifetime.

  • An organization owns its tenants, and organization settings override tenant settings.
  • Admin, Security, Publisher, Reader, and Auditor roles come with every tenant.
  • Sign in with GitHub, or with single sign-on.
  • A CI job can trade its own identity for a short-lived token, so you don’t store a secret.

Tokens

Sample data
NamePermissionsRegistriesLast usedExpires
release-publishernpm:publishacme-npm2 hours agoin 61 days
ci-buildregistries:readAll registries1 hour agoin 88 days
audit-exportaudit:readAll registries27 hours agoin 5 days

Use Kurra cloud, or run Kurra yourself

Either way, your packages are stored in a bucket you own, and each tenant is kept separate from the others.

Storage you own

Each tenant connects its own S3-compatible bucket. Kurra doesn’t keep a bucket of its own.

Self-hosted

Run Kurra with Docker Compose or a Helm chart, inside your own network.

Separate tenants

A tenant is a team or business unit in your organization. Its registries, tokens, roles, usage, and activity belong to it alone.

Put a decision in front of every install

Find the code, the documentation, and the latest changes on GitHub.

View Kurra on GitHub