MCPcopy Index your code
hub / github.com/bokuweb/sakimori

github.com/bokuweb/sakimori @v0.34.4

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.34.4 ↗ · + Follow
1,133 symbols 3,349 edges 76 files 181 documented · 16%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

sakimori

CI release license

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.


Why this exists

Supply-chain attacks follow a predictable timeline:

  1. Attacker publishes a malicious version at T+0
  2. Community notices, yanks it at T+12–72h

Most 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.

How it works

            ┌───────────────────┐       ┌────────────────────┐
            │  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 coverage

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.


Install

Pick whichever fits your setup.

Homebrew (macOS / Linux)

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.

Pre-built binary (macOS / Linux / Windows)

# 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 / OCI

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.

From source

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.


Desktop quick start

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.

Observable proof that it works

$ 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.

Uninstall

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)

Feature reference

proxy start

Start 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-ca

Add / 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-daemon

Write 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

Extension points exported contracts — how you extend this code

Core symbols most depended-on inside this repo

Shape

Function 744
Class 168
Method 164
Enum 46
Interface 11

Languages

Rust97%
TypeScript2%
Python2%
Ruby1%

Modules by API surface

crates/sakimori/src/cli.rs52 symbols
crates/sakimori-core/src/actions.rs45 symbols
crates/sakimori-proxy/src/rewrite_pypi.rs39 symbols
crates/sakimori-core/src/policy.rs35 symbols
crates/sakimori-core/src/tamper.rs34 symbols
crates/sakimori/src/resolve_refresh.rs32 symbols
crates/sakimori/src/doctor.rs32 symbols
crates/sakimori-proxy/src/proxy.rs31 symbols
crates/sakimori-proxy/src/parser.rs30 symbols
crates/sakimori-core/src/deps/watch/action.rs30 symbols
crates/sakimori-proxy/src/rewrite_nuget.rs29 symbols
crates/sakimori/src/install_gate.rs28 symbols

For agents

$ claude mcp add sakimori \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page