Cross-platform supply-chain guard for every package manager on your machine. Silently blocks too-young versions, known-malicious packages and unsigned publishes — across npm, cargo, pypi, nuget — without touching your build tools.
# Three commands, once.
$ sakimori proxy install-ca # trust the proxy's root CA
$ sakimori proxy install-daemon # auto-run in the background
$ sakimori install-gate install # route your shell through it
# Business as usual, permanently safer.
$ npm install react
# → proxy silently drops versions < 7d old
# → npm picks the newest older version
# → no error, no broken build, just a measurably safer dependency
Works on macOS, Linux, and Windows. Also ships a CI mode
(deps check + eBPF/ETW supervisor) for pipelines.
Supply-chain attacks follow a predictable timeline:
T+0T+12–72hMost victims install between hours 0–12. pnpm 10.x introduced
minimumReleaseAge
to solve this for npm only — versions younger than the threshold
become invisible to the resolver, which silently falls back to the
newest older one.
sakimori brings the same behaviour to all four major ecosystems (crates.io, npm, pypi, nuget) and any package manager that talks to them, by sitting as an HTTPS proxy and rewriting the registry's metadata responses in-flight. No resolver integration. No config in your package manifests.
┌───────────────────┐ ┌────────────────────┐
│ npm / cargo / │ │ │
user ───► │ pip / uv / │ ─────►│ sakimori proxy │ ──► real registry
│ dotnet / poetry │ HTTPS│ (localhost:8910) │ (metadata + tarball)
└───────────────────┘ └─────────┬──────────┘
│
▼
rewrites metadata:
- drop versions < --min-age
- drop unsigned versions (--require-provenance)
- retarget npm dist-tags.latest
- returns 403 for pinned tarball fetches
to too-young versions
The proxy's root CA is installed into the system trust store once;
from then on, every HTTPS request your package managers make through
HTTPS_PROXY=http://127.0.0.1:8910 gets transparently filtered.
| ecosystem | silent auto-fallback | hard deny on pinned fetch |
|---|---|---|
| crates.io | ✅ sparse-index JSONL rewrite (drops too-young lines from /<prefix>/<name>) |
✅ 403 on .crate download to a denied version |
| npm | ✅ packument rewrite (drops versions + retargets dist-tags.latest) |
✅ 403 on .tgz download |
| pypi | ✅ Warehouse JSON API (/pypi/<pkg>/json) + PEP 691 Simple JSON + PEP 503 Simple HTML via JSON-API lookup |
✅ 403 on files.pythonhosted.org tarball download |
| nuget | ✅ registration-page rewrite (/v3/registration*/...) + flat-container index via registration lookup |
✅ 403 on .nupkg download |
All four ecosystems' metadata paths now rewrite silently — pnpm-style
minimumReleaseAge across the board, no fail-hard in the common case.
Pick whichever fits your setup.
brew install bokuweb/sakimori/sakimori
# ↑ the repo-is-its-own-tap convention; no separate `brew tap` needed.
Auto-updated on every release via the homebrew-formula.yml
workflow — the formula lives at
HomebrewFormula/sakimori.rb
in this repo.
# macOS (Apple Silicon)
curl -fsSL https://github.com/bokuweb/sakimori/releases/latest/download/sakimori-aarch64-apple-darwin.tar.gz \
| sudo tar -xz -C /usr/local/bin
# macOS (Intel)
curl -fsSL https://github.com/bokuweb/sakimori/releases/latest/download/sakimori-x86_64-apple-darwin.tar.gz \
| sudo tar -xz -C /usr/local/bin
# Linux (x86_64 musl static)
curl -fsSL https://github.com/bokuweb/sakimori/releases/latest/download/sakimori-x86_64-unknown-linux-musl.tar.gz \
| sudo tar -xz -C /usr/local/bin
# Windows (PowerShell)
Invoke-WebRequest -Uri https://github.com/bokuweb/sakimori/releases/latest/download/sakimori-x86_64-pc-windows-msvc.tar.gz -OutFile c.tgz
tar -xzf c.tgz -C "$env:USERPROFILE\.local\bin"
Every release also ships a .sha256 sidecar. The archive contains
the sakimori binary (Linux also ships sakimori.bpf.o for the
supervised-run mode).
docker run --rm -p 8910:8910 \
-v sakimori-conf:/etc/sakimori-xdg \
ghcr.io/bokuweb/sakimori-proxy:v0 \
--listen 0.0.0.0:8910 --min-age 7d
Mount /etc/sakimori-xdg as a volume to persist the generated
root CA across container restarts. See Docker image.
cargo install --git https://github.com/bokuweb/sakimori sakimori
The Linux eBPF supervised-run mode additionally needs
rustup toolchain install nightly --component rust-src +
cargo install bpf-linker. Not required for proxy / deps / install-gate.
Three commands, once per machine. Each is idempotent.
# 1. Generate the proxy's root CA and install it into the system
# trust store. macOS uses `security`, Linux uses
# `update-ca-certificates`, Windows uses elevated
# `Import-Certificate` (triggers one UAC prompt).
sakimori proxy install-ca
# 2. Register the proxy as a background service so it's always up.
# macOS: ~/Library/LaunchAgents/com.sakimori.proxy.plist
# Linux: ~/.config/systemd/user/sakimori-proxy.service
# Windows: Task Scheduler /sakimori-proxy
sakimori proxy install-daemon
# Follow the printed `launchctl bootstrap …` / `systemctl --user enable --now`
# / `schtasks.exe /Create …` line.
# 3. Append HTTPS_PROXY + CA bundle env vars to your shell rc.
# Detects zsh / bash / fish / PowerShell from $SHELL (or your OS).
sakimori install-gate install
Open a new shell — everything's wired:
$ env | grep -E 'HTTPS_PROXY|CARGO_HTTP_CAINFO'
HTTPS_PROXY=http://127.0.0.1:8910
CARGO_HTTP_CAINFO=/Users/you/.config/sakimori/ca.pem
$ sakimori doctor
sakimori doctor
────────────────────────────────────────────────────────────
✓ CA certificate /Users/you/.config/sakimori/ca.pem (644 bytes)
✓ CA private key /Users/you/.config/sakimori/ca.key
✓ Proxy reachable accepted TCP on 127.0.0.1:8910
✓ $HTTPS_PROXY http://127.0.0.1:8910
✓ install-gate rc /Users/you/.zshrc
✓ Daemon unit /Users/you/Library/LaunchAgents/com.sakimori.proxy.plist
────────────────────────────────────────────────────────────
6 check(s): 0 fail, 0 warn
From here, npm install / pnpm add / yarn add / cargo add /
cargo build / pip install / uv add / poetry add /
dotnet add package / dotnet restore all flow through the proxy.
$ curl -s https://index.crates.io/se/rd/serde | wc -l # direct
315
$ curl -sx http://127.0.0.1:8910 https://index.crates.io/se/rd/serde | wc -l
306 # the 9 most recent versions are invisible to cargo's resolver
cargo picks the newest remaining in-range version — no error, just safer. Same shape on the other three ecosystems.
Reverse each step (same flags):
sakimori install-gate uninstall # strip block from shell rc
sakimori proxy uninstall-daemon # remove launchd / systemd / Task Scheduler unit
sakimori proxy uninstall-ca # remove CA from system trust store
rm -rf ~/.config/sakimori # delete CA + key (optional)
proxy startStart the MITM HTTPS proxy in the foreground. install-daemon
wraps this for background use; run it directly when you want logs
on stdout or you're running the proxy yourself in Docker.
sakimori proxy start [OPTIONS]
Options:
--listen <ADDR> [default: 127.0.0.1:8910]
--min-age <DURATION> [default: 7d]
Grammar: `<N>{d,h,m,s}`. Versions younger than this are
invisible to the resolver.
--fail-on-missing Treat unknown publish dates as deny
(default: fail-open / allow through).
--require-provenance Strict mode. Drop every npm package
version without a Sigstore provenance
claim. Forces publishers to have gone
through OIDC-authenticated CI.
(npm only for now.)
--osv Consult OSV.dev on every decision.
Versions flagged as malicious
packages (MAL-* or advisories
mentioning "malicious") are hard-
denied regardless of --min-age.
Live API, per-version cached.
--osv-mirror Same blocking rule as --osv, but
consumed from the sakimori-hosted
pre-filtered snapshot. O(1) in-memory
lookup after a single ~10-minute
background refresh. ~10 min behind
OSV publish time in exchange for
not hitting api.osv.dev per request.
Combine with --osv to additionally
fall back to the live API for
entries the mirror hasn't indexed.
--osv-mirror-url <URL> Override mirror URL (e.g. self-hosted).
--network-allow <HOST> Hostname egress allow-list (repeatable).
Patterns: `host.example.com` (exact) or
`*.example.com` (any subdomain, excludes
apex). When set, the proxy default-denies
every CONNECT/HTTP whose target host
doesn't match, returning 403. Off by
default — without any flag, every host
passes through.
--network-allow-file <PATH> Read additional `--network-allow`
patterns from a file (one per line;
`#` comments / blank lines skipped).
--config-dir <PATH> Override CA / config directory.
Defaults to $XDG_CONFIG_HOME/sakimori
on Unix, %LOCALAPPDATA%\sakimori on
Windows.
First-run side effect: generates a self-signed root CA at the config dir and prints the OS-specific trust command. Subsequent runs reuse the existing CA.
Egress allow-list closes the eBPF-by-IP gap: when you also run
sakimori run with a network policy, the kernel layer enforces by
resolved IP and loses against CDN rotation. The proxy's hostname
filter sees the SNI / Host: value the client actually asked for,
so an entry like *.githubusercontent.com matches every rotating
CDN IP automatically — the same convention step-security/harden-runner
users are used to:
sakimori proxy start \
--network-allow api.github.com \
--network-allow '*.githubusercontent.com' \
--network-allow registry.npmjs.org
proxy install-ca / uninstall-caAdd / remove the root CA from the OS trust store. Cross-platform:
| OS | Mechanism | Privilege prompt |
|---|---|---|
| macOS | security add-trusted-cert -k /Library/Keychains/System.keychain |
sudo |
| Linux | copy to /usr/local/share/ca-certificates/ + update-ca-certificates |
sudo |
| Windows | Import-Certificate -CertStoreLocation Cert:\LocalMachine\Root |
UAC via Start-Process -Verb RunAs |
If you're not elevated, sakimori prints the exact shell command and exits — no silent reruns with privileges.
sakimori proxy install-ca [--config-dir <PATH>]
sakimori proxy uninstall-ca [--config-dir <PATH>]
proxy install-daemon / uninstall-daemonWrite a user-level service unit so the proxy runs in the background at login and restarts on failure.
| OS | Unit | Location |
|---|---|---|
| macOS | launchd plist (KeepAlive, RunAtLoad, Background ProcessType) |
~/Library/LaunchAgents/com.sakimori.proxy.plist |
| Linux | systemd --user unit (Restart=on-failure, WantedBy=default.target) |
~/.config/systemd/user/sakimori-proxy.service |
| Windows | Task Scheduler v1.4 XML (LogonTrigger, RestartOnFailure 99×1m, Hidden) |
%LOCALAPPDATA%\sakimori\sakimori-proxy.task.xml |
``` sakimori proxy install-daemon [OPTIONS]
Options: --listen
$ claude mcp add sakimori \
-- python -m otcore.mcp_server <graph>