Supply Chain
Coding agents install a lot of packages, and a freshly compromised dependency is one of the most direct ways to poison a sandbox. The Supply Chain pane configures the per-workspace policy Bromure Agentic Coding applies to every package fetch. As the pane's own description says: Bromure scans every package fetch (npm, PyPI, Cargo, RubyGems, Maven, NuGet, Go modules, Packagist) through the host MITM and applies these policies before the agent sees the response; the in-VM .npmrc / pip.conf can only further restrict these settings — they cannot loosen them. Use the per-package allowlists for surgical overrides.
The pane groups five independently toggled layers: Age gate, OSV vulnerability check, Package filtering, Install scripts, and Lockfile-pinned installs (scroll for the last three). This page documents the settings; the full pipeline — ecosystem coverage, the Security Log, response headers, and compromise detection — is covered in the Supply-chain protection chapter.
How enforcement works
All checks run in the host-side proxy, never inside the VM. Reputation-service API keys (socket.dev, Delpi) are held on the host only and never exported into the VM. When a check fires, the proxy blocks the download with an HTTP 451 response carrying a plaintext reason (for example, "npm package [email protected] published 4 hours ago — policy requires 2 days minimum"); npm, pip, and cargo print that text verbatim, so both the agent and you see exactly why an install failed. Blocked responses carry the header X-Bromure-Block: supply-chain; rewritten responses carry X-Bromure-Rewritten: supply-chain.
Policy edits apply live: saving the workspace pushes the new policy to running sessions immediately — no VM restart — and each change is confirmed with a [supply-chain] policy engaged line in the Security Log (Window menu → Security Log…).
Note: Packages already present in npm's or pip's local cache never touch the network, so nothing is checked or logged for them. A quiet Security Log during an install can simply mean everything was cached.
Age gate
The age gate refuses package versions younger than a configurable cutoff, on the theory that just-published releases are the ones most likely to be a freshly compromised package. It is the only layer on by default.
- Refuse packages younger than the cutoff — the master toggle. On by default.
- Minimum age — the cutoff in days (stepper, 0–90). Default: 2 days.
- Exempt packages — an allowlist in the format
npm:axios(one ecosystem) or justaxios(every ecosystem), case-insensitive. Click Add entry to append a row.
Floating references (pkg@latest, semver ranges) are never hard-blocked: the proxy rewrites the registry metadata so too-fresh versions simply do not exist from the agent's point of view, and the package manager resolves to the newest allowed version. Only pinned references to too-fresh versions get the 451, stating the package's age and the required minimum.
Note: Maven, NuGet, and Go modules do not carry per-version timestamps in their standard metadata responses, so the age gate does not currently block those three ecosystems. npm, PyPI, Cargo, RubyGems, and Packagist are fully covered (for PyPI, Bromure looks up publish times on demand from the PyPI JSON API).
OSV vulnerability check
When Look up packages on api.osv.dev (free, no key required) is on, each downloaded artifact's ecosystem, package, and version are checked against the OSV database — a free aggregation of the GitHub Advisory Database, PyPI advisories, Go's vulnerability database, RubySec, and others. Any advisory at or above the Block at severity threshold blocks the download with a 451.
- Off by default — as the pane notes, a low-severity CVE in a transitive subpackage shouldn't interrupt a workflow.
- Block at severity offers Low and above, Medium and above, High and above (the default), or Critical only.
- Covers all eight ecosystems; checks run at artifact-download time, not on metadata fetches.
Package filtering
The Package filtering radio selects a reputation provider: None, socket.dev, or Delpi. The two providers work differently — socket.dev is a pre-flight lookup the proxy consults before letting a fetch through, while Delpi replaces the npm registry outright — so they are mutually exclusive. Stored API keys are kept when you switch, so flipping between providers is non-destructive.
socket.dev
With socket.dev selected, paste an API token into API key (the Get an API key link opens socket.dev's token page). Both toggles below stay disabled until a key is entered, and an empty key disables socket.dev entirely regardless of the toggles. The key is stored host-side only and never enters the VM.
- Block compromised packages (rogue install scripts, malware-flagged, typosquats, suspicious telemetry) — blocks on attack-shaped supply-chain-risk signals: definitive malware indicators at any severity; noisier signals such as obfuscated code, install scripts, typosquatting, or shell access only when socket.dev rates them high or critical (so a package with a benign
postinstallis not blocked). Off by default. - Block packages with known CVEs — blocks on socket.dev's vulnerability bucket at or above the CVE block threshold (default High and above; the picker is disabled until this toggle is on). Off by default.
Note: socket.dev has no Cargo support. With socket.dev filtering enabled, every crates.io artifact yields no verdict and triggers the unverified-package hold described below — effectively a prompt per crate version. Disable socket.dev for Rust-heavy workspaces, or expect to answer prompts.
Delpi
With Delpi selected and an API key entered (the Get an API key link opens landh.tech), the proxy re-routes every npm registry request — metadata, tarballs, audit, everything addressed to registry.npmjs.org — to Delpi's npm-compatible secure registry at depi-npm-proxy.landh.tech, attaching your key as a host-injected Bearer token. Delpi serves pre-vetted packages, so instead of a per-package lookup, the whole registry is replaced. The other layers (age gate, OSV, script stripping) still apply on top: Delpi replaces socket.dev, not the local policy.
While the key field is empty, an orange warning reads Enter an API key — Delpi stays off without one. If Delpi rejects the key, the npm install fails with a clear Bromure error, the rejection is recorded in the Security Log, and a one-shot alert is raised. Delpi affects npm only; other ecosystems are untouched.
Install scripts
Strip preinstall / install / postinstall / prepare from npm tarballs on the fly removes the hooks malicious npm packages use to run code at install time. Bromure rewrites the tarball in flight — removes the script keys from the package's package.json, recomputes the tar checksum, re-gzips — and scrubs the integrity hashes from the registry metadata so npm's own verification still passes for unpinned installs. Strips are logged in orange in the Security Log; on any parse failure the original tarball passes through untouched (this layer fails open rather than break a well-formed install).
Binding compilers that genuinely need install scripts (better-sqlite3, node-canvas, …) go in Allow install scripts for, format npm:better-sqlite3.
Off by default; npm only (PyPI sdists are never rewritten — setup.py is arbitrary code).
Lockfile-pinned installs
Lockfile-pinned installs (npm ci, pip --require-hashes) pin tarball integrity hashes in the lockfile, so Bromure cannot rewrite those tarballs without breaking verification. By default they pass through unmodified and silently.
Turn on Prompt before passing lockfile-pinned tarballs through unmodified (npm ci, pip --require-hashes) to be asked instead: the first lockfile-pinned fetch in a batch pops a host dialog titled Pass through npm ci (lockfile-pinned install) from workspace "<name>"? with the choices Allow for 15 minutes, Allow once, Allow for the rest of the session, and Don't allow. The whole batch follows the decision (concurrent fetches coalesce onto one prompt); denying blocks with a 451 and is remembered for 60 seconds.
Note: Although the label mentions
pip --require-hashes, detection is currently implemented for npm'snpm cionly — pip hash-pinned installs do not trigger the prompt.
When a reputation source is unreachable
If an enabled reputation source (OSV or socket.dev) cannot produce a verdict — network down, rate-limited, auth failure, unsupported ecosystem — Bromure fails closed rather than silently allowing. The download is held and a dialog asks, per package and version, whether to accept the unverified package; denying blocks with a 451. Approvals are keyed per package@version, so one answer cannot blanket an entire dependency graph.
This is deliberate protection against an attacker inducing rate limits to sneak packages through. It also means fully offline work with OSV or socket.dev enabled will prompt for every uncached package — disable those layers for offline use. In headless SSH/CLI sessions the same question is asked inside the workspace's tmux; no answer means deny.
Settings reference
| Setting | Type | Default |
|---|---|---|
| Refuse packages younger than the cutoff | Toggle | On |
| Minimum age | Stepper, 0–90 days | 2 days |
| Exempt packages | List (npm:axios or axios) | Empty |
| Look up packages on api.osv.dev (free, no key required) | Toggle | Off |
| Block at severity (OSV) | Picker: Low / Medium / High and above, Critical only | High and above |
| Package filtering | Radio: None / socket.dev / Delpi | None |
| API key (socket.dev) | Secure field | Empty |
| Block compromised packages | Toggle (needs a socket.dev key) | Off |
| Block packages with known CVEs | Toggle (needs a socket.dev key) | Off |
| CVE block threshold | Picker (enabled with the CVE toggle) | High and above |
| API key (Delpi) | Secure field | Empty (Delpi stays off without one) |
| Strip preinstall / install / postinstall / prepare from npm tarballs on the fly | Toggle | Off |
| Allow install scripts for | List (npm:better-sqlite3) | Empty |
| Prompt before passing lockfile-pinned tarballs through unmodified | Toggle | Off |
API keys entered here live in the workspace's profile.json on the host (never in the VM); all reputation calls originate from the host proxy. For the Security Log, per-ecosystem interception details, and the compromise-detection alarm that pairs with these policies, see the Supply-chain protection chapter.