PicoSentry
Catch malicious packages before they bite. Offline supply-chain scanner — obfuscation, typosquatting, dependency confusion, exfiltration, IOCs, CVEs across 7 ecosystems. No internet required.
Quick start
pip install picosentry
picosentry scan ./your-project
That's it. Works offline, deterministic, no phone-home.
See it in action
git clone https://github.com/KirkForge/PicoSentry.git
cd PicoSentry
picosentry scan examples/pypi-obfuscated-setup/
🦞 PicoSentry
Target: /home/you/PicoSentry/examples/pypi-obfuscated-setup
Engine: v2.1.1 | Corpus: vef6b3b3115bb
Scan ID: 08057439b4ba08d8
Packages scanned: 0
Files scanned: 2
Duration: 20ms
The scan fires 5+ findings across obfuscation, post-install, and exfiltration rules. Re-run and the Scan ID and Corpus digest match exactly — that's the determinism guarantee.
What it detects
| Rule | What it catches | Example |
|---|---|---|
| L2-TYPO-001 | Typosquatted package names | reqursts instead of requests |
| L2-DEPC-001 | Dependency confusion | internal-pkg not on registry |
| L2-PYPI-OBFS-001 | Dynamic execution in setup.py | exec()/eval() in install scripts |
| L2-PYPI-OBFS-002 | Base64-decoded payloads | base64.b64decode(...) + dynamic use |
| L2-PYPI-POST-001 | Post-install code execution | setup.py runs code at install time |
| L2-NETEX-001 | Network calls during install | urllib.request, curl, wget at install |
| L2-IOC-001 | Known IOC behavior patterns | Hardcoded C2 host, exfil URL patterns |
| L2-CVE-001 | Known CVEs in dependency tree | OSV-matched vulnerabilities |
| L2-INTEL-001 | Suspiciously-new low-download packages | Package <30 days old with <100 downloads (package_intel.py, rules/package_age.py) |
Advisory findings also carry a reachable flag — True when the vulnerable package is actually imported/used in the scanned source, so you can triage present-but-unused CVEs (rules/advisory_check.py).
50 L2 rules (65 with L4 behavioral detectors) across npm, PyPI, Go, Cargo, Maven, RubyGems, and NuGet.
Full catalog: picosentry/scan/docs/rules/
Supported ecosystems
| Ecosystem | Typosquat | Dep Confusion | Obfuscation | CVE Match | License |
|---|---|---|---|---|---|
| npm | ✅ | ✅ | ✅ | ✅ | ✅ |
| PyPI | ✅ | ✅ | ✅ | ✅ | ✅ |
| Go | ✅ | ✅ | — | ✅ | ✅ |
| Cargo | ✅ | ✅ | — | ✅ | ✅ |
| Maven | ✅ | ✅ | — | ✅ | ✅ |
| RubyGems | ✅ | ✅ | — | ✅ | ✅ |
| NuGet | ✅ | ✅ | — | ✅ | ✅ |
Why PicoSentry?
| Capability | PicoSentry | pip-audit | osv-scanner | Trivy | Socket |
|---|---|---|---|---|---|
| Offline operation | ✅ | partial | partial | partial | ❌ |
| Deterministic output | ✅ | ❌ | ❌ | ❌ | ❌ |
| Malicious-behavior rules | ✅ | ❌ | ❌ | partial | partial |
| 7 ecosystems | ✅ | partial | ✅ | ✅ | partial |
| Kernel sandbox | ✅ | ❌ | ❌ | ❌ | ❌ |
Offline + deterministic + malicious-behavior rules in one package.
Status
| Component | Status | Notes |
|---|---|---|
picosentry scan |
Stable | Core scanner; 7 ecosystems; deterministic, offline; 50 rules, 6495 fixtures |
picosentry sandbox |
Stable | seccomp-bpf enforces; gRPC + HTTP daemon; L4 behavioral analysis; seccomp-trace is opt-in and argument-limited |
picosentry watch |
Stable | Deterministic regex + lexical classifier pre-filter for prompt injection (L5) and output validation (L6); not a semantic/LLM guarantee; CLI + HTTP server |
picosentry serve |
Beta | API server, dashboard, RBAC, multi-tenant Postgres backend — security review + regression tests in place. Auth hardening: MFA/TOTP enrollment, JWT jti revocation, account lockout, role-scoped API keys (services/auth.py) |
picosentry daemon |
Beta | Sandbox-as-a-service; HTTP + gRPC; auth, rate limiting, TLS/mTLS, audit |
picosentry admission |
Beta | K8s admission webhook; pod security validation + optional image scanning; fail-closed by default when image scanning is enabled; live-tested against a kind cluster |
picosentry corpus |
Stable | Export/import/validate/list/sign IoC packs; 3 built-in packs; deterministic signatures |
| Cross-layer correlation | Stable | Links findings across scan + sandbox + watch layers; persistence, dedup, and per-minute backpressure tested in CI |
| Plugin system | Stable | Loads, validates, dispatches; Ed25519 signature verify against a configured trusted-key allowlist; unsigned plugins load only when signing is not required |
| Postgres backend | Stable | psycopg2 pool + runtime placeholder translation + DDL auto-translation + dialect helpers; live PG 15/16 CI |
| Cluster mode | Beta | Gossip over HTTP(S) with shared cluster token + optional mTLS; monotonic versioning; 3-node integration test |
| Detection benchmarks | Stable | 6495 fixtures (5558 pos / 930 neg), 50 rules, 94.44% prec, 68.89% recall — see docs/model-card.md |
| Docker image | Stable | kirkforge/picodome:v2.1.1 on Docker Hub; multi-arch (linux/amd64 + linux/arm64); non-root user |
| PyPI package | Stable | pip install picosentry — v2.1.1 published |
"Beta" = works, has regression + security tests, suitable for controlled production use. Per-component reviews in docs/.
Install
pip install picosentry # core (offline-ready)
pip install picosentry[scan] # + online corpus management
pip install picosentry[serve] # + API server + dashboard
pip install picosentry[all] # everything
Docker: docker pull kirkforge/picodome:v2.1.1 — multi-arch, non-root.
More
- Technical manual — full install options, gRPC transport, plugin system, corpus management, repository structure, and sandbox details
CLI commands
picosentry scan (core scanner), sandbox (isolation), watch (LLM guards), serve (API server), daemon (sandbox-as-a-service), admission (K8s webhook), corpus (IoC packs), diff (compare scans), doctor (self-verification), firewall (network policy), rules (list/disable rules), init (project config), health (status check), version, update.
- Architecture — component diagram and trust boundaries
- Detection benchmarks — 6495 fixtures, 50 rules (50 L2 + 65 L4 behavioral), precision/recall per rule
- Security reviews — per-component security analysis
- Plugin development — write, sign, and deploy plugins
Supply chain: wheel builds are reproducible — SOURCE_DATE_EPOCH is pinned from the commit timestamp in release.yml, the Dockerfile, and CI, so the same source yields a byte-identical wheel (asserted by the CI reproducible-build job).
Design principles
- Deterministic — same inputs + same policy = same SHA-256 output
- Offline by default — no phone-home, no remote API calls
- Lightweight core — default install pulls only
pyyaml - Typed — full annotations,
py.typedshipped
Getting help
- Issues: GitHub Issues
- Security (not a public issue): SECURITY.md or private report
- Discussion: GitHub Discussions
- Contributing: CONTRIBUTING.md
License
BUSL-1.1 — see LICENSE and COMMERCIAL-LICENSE.md.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file picosentry-2.1.1.tar.gz.
File metadata
- Download URL: picosentry-2.1.1.tar.gz
- Upload date:
- Size: 727.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1d1727d21fe8c17a1e0839b3bac43a4b8ce1da831088559a418217f2fb259c50
|
|
| MD5 |
133e79d50d05486f22cdac7cd9532c88
|
|
| BLAKE2b-256 |
05d03ff7c193163666469a4f73e809d184e2b89a04a71ba647aecf7f0c55c654
|
File details
Details for the file picosentry-2.1.1-py3-none-any.whl.
File metadata
- Download URL: picosentry-2.1.1-py3-none-any.whl
- Upload date:
- Size: 924.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cc3ff973f3ea80dfebd1adbfb57f9324b799295973d1ec4d15c92102fa1f6daa
|
|
| MD5 |
c1cc432a973547f679baa71f56779cff
|
|
| BLAKE2b-256 |
d125611f1ac909f1a66fc2d9052fd783477086e3a496f8788eed851d0c735284
|