Protected in one config line.
Point your package manager at your Upwarden instance. Every install from then on flows through the firewall — malicious versions stripped, floating ranges rolled back to the last safe version, builds still green.
Upwarden Cloud is live. The endpoints below are real and ready — <ecosystem>.pkg.upwarden.io. You need a project API key (vk_…) from the dashboard first; every endpoint rejects unauthenticated requests.
Self-hosting is not available yet. Everything in this view is a preview of the planned setup, published so you can review the shape before it ships — not instructions you can follow today. Run it in your own network, with nothing leaving it: join the early-access list. To start protecting builds now, switch to .
1 · Get a project API key
Every Cloud endpoint requires one — an unauthenticated request is rejected, so this step is not optional. Create a key in the dashboard under your project's API keys, copy the vk_… value once (it is shown only at creation), and put it in the environment variable each config below expects.
In CI you do not need a key at all — setup-upwarden exchanges an OIDC token for short-lived credentials, so nothing long-lived is stored in your workflow.
2 · npm protocol — npm, bun, yarn, pnpm
One file covers all four; they read the same registry config.
registry=https://npm.pkg.upwarden.io/
//npm.pkg.upwarden.io/:_authToken=${VG_NPM_API_KEY}
3 · Python — pip, uv
$ export PIP_INDEX_URL=https://${VG_PYPI_API_KEY}@pypi.pkg.upwarden.io/simple/
Not pip.conf. pip does not expand ${VAR} inside its config file — environment variables and config files are separate mechanisms there, so a ${…} written into pip.conf is sent literally and the install fails. Use the shell form above, or paste the key into pip.conf in full.
4 · Rust — cargo
# The env var name is derived from the REGISTRY NAME below. Rename the # registry and this must change with it: CARGO_REGISTRIES_<NAME>_TOKEN, # uppercased with hyphens turned into underscores (my-reg -> MY_REG). [source.crates-io] replace-with = "upwarden" [registries.upwarden] index = "sparse+https://crates.pkg.upwarden.io/index/"
$ export CARGO_REGISTRIES_UPWARDEN_TOKEN=${VG_CRATES_API_KEY}
The two names must match. Cargo derives the variable from the registry name in your config — call the registry something else and it becomes CARGO_REGISTRIES_<THAT>_TOKEN, uppercased with hyphens replaced by underscores — a registry named my-reg uses CARGO_REGISTRIES_MY_REG_TOKEN. Nothing on our side reads the variable; we only see the resulting header, so a mismatch looks exactly like a bad key.
A 401 after a working start is normal-looking and usually a typo. config.json is served anonymously on purpose, because cargo reads it before authenticating to discover whether auth is required. So a mistyped token gives you a successful bootstrap and then a 401 on the first real fetch — the registry is up; the credential is wrong.
5 · Go, Maven, NuGet & RubyGems
Same pattern — point each ecosystem's standard registry setting at its Upwarden endpoint:
- Go —
GOPROXY=https://go.pkg.upwarden.io,direct - Maven — mirror
https://maven.pkg.upwarden.io/maven2in~/.m2/settings.xml - NuGet — add
https://nuget.pkg.upwarden.io/v3/index.jsonas apackageSource - RubyGems — point Bundler's mirror at
https://rubygems.pkg.upwarden.io
Each takes the same credential as the ecosystems above. All get the same proxy, content scan, behavioral signals and silent rollback — Maven adds JVM bytecode analysis on top.
npm protocol — npm, bun, yarn, pnpm
Anything that speaks the npm registry protocol is covered. Set the registry once and every install resolves through Upwarden.
# PREVIEW — self-hosting is not available yet. Planned setup, not a working config. $ npm config set registry https://upwarden.example.com/
# PREVIEW — self-hosting is not available yet. Planned setup, not a working config.
registry=https://upwarden.example.com/
# PREVIEW — self-hosting is not available yet. Planned setup, not a working config.
[install]
registry = "https://upwarden.example.com/"
# PREVIEW — self-hosting is not available yet. Planned setup, not a working config.
npmRegistryServer: "https://upwarden.example.com/"
bun is first-class. Because bun reads the standard registry config, it's covered exactly like npm — something wrapper-based tools don't offer. Private and scoped packages keep working: your existing tokens pass straight through to the upstream registry, untouched.
Python — pip, poetry, uv
Point the index URL at Upwarden's /simple/ endpoint.
# PREVIEW — self-hosting is not available yet. Planned setup, not a working config. $ export PIP_INDEX_URL=https://upwarden.example.com/simple/
# PREVIEW — self-hosting is not available yet. Planned setup, not a working config.
[global]
index-url = https://upwarden.example.com/simple/
# PREVIEW — self-hosting is not available yet. Planned setup, not a working config. $ export UV_INDEX_URL=https://upwarden.example.com/simple/
# PREVIEW — self-hosting is not available yet. Planned setup, not a working config. $ poetry source add --priority=primary upwarden https://upwarden.example.com/simple/
Rust — cargo
cargo uses a sparse index. Replace crates.io with your Upwarden sparse endpoint in .cargo/config.toml.
# PREVIEW — self-hosting is not available yet. Planned setup, not a working config.
[source.crates-io]
replace-with = "upwarden"
[registries.upwarden]
index = "sparse+https://upwarden.example.com/cargo/"
Go, Maven, NuGet & RubyGems
These use the same pattern — point each ecosystem's standard registry setting at your Upwarden endpoint:
- Go — set
GOPROXYto your Upwarden Go endpoint. - Maven — add an Upwarden
<mirror>in~/.m2/settings.xml. - NuGet — add your Upwarden feed as a
packageSourceinnuget.config. - RubyGems — point Bundler's mirror at your Upwarden RubyGems endpoint.
All four get the same proxy, content scan, behavioral signals and silent rollback as npm and PyPI — Maven adds JVM bytecode analysis on top. Ask us for the exact per-ecosystem snippet for your setup.
Verify it works
Install anything. A normal, safe package installs as usual — the only added latency is a single proxy hop. To see the firewall act, request a version known to be blocked and watch it roll back:
$ npm install lodash upwarden › lodash@4.17.22 — BLOCKED (malware signature match) upwarden › resolving to last safe version → 4.17.21 added 1 package — lodash@4.17.21 ✓ build green
What happens on a block
- Floating ranges (
^1.2.0,~=1.2, cargo semver) resolve around blocked versions automatically — silent rollback to the highest safe version. - Exact pins to a blocked version fail loudly with an actionable
[UPWARDEN]message that names a safe version to use. - Lockfile installs keep working as long as the locked version stays safe. If it later becomes blocked, you get a clear error and a one-command fix.
- Brand-new versions are quarantined and scanned. Requests are briefly held for a verdict; if none is reached, the request fails closed rather than letting an unscanned artifact through.
- Registry downtime doesn't stop you — Upwarden keeps serving cached manifests, so builds keep working.
Keep your builds green and your malware out
Self-serve in a minute, or talk to us about an enterprise deployment.