Paranoid
Open-source, self-hosted, iterative threat modeling powered by LLMs.
Paranoid takes system descriptions (text, diagrams, or code via MCP) and produces comprehensive STRIDE + MAESTRO threat models through an LLM-powered pipeline with deterministic fallback. Configure 1–15 automated iteration passes, then review threats in a human-in-the-loop approve/reject cycle.
Features
- Zero Infrastructure: SQLite + sqlite-vec. One command:
docker compose up - Multi-Provider LLM: Anthropic, OpenAI, Ollama (fully local/air-gapped), or AWS Bedrock
- Dependency Capability Engine: static-analysis visibility into what an npm dependency can do (network, filesystem, process, dynamic code, native addons), diffed against its own GitHub source — see below
- Dual Framework: STRIDE (traditional) + MAESTRO (AI/ML) — auto-detected or run in parallel
- DREAD + CVSS Risk Scoring: automatic 5-dimension DREAD (0–10) and/or a standalone CVSS v3.1 base-score calculator, selectable per run
- ATT&CK / ATLAS Enrichment: every threat — LLM-generated, rule-engine, or dependency — is mapped to MITRE ATT&CK/ATLAS techniques (deterministic rule table, pattern-ID regex, or embedding similarity depending on origin), never self-attributed by the LLM
- Iterative Refinement: 1–15 configurable iteration passes with gap analysis
- Model Routing: per-pipeline-step fast/main model selection (e.g. Haiku for extraction, Sonnet for threat generation); the routed extraction steps cost about two-thirds less (measured), and the steps that write the threat text never leave the main model
- Code-as-Input: Semantic code extraction via context-link MCP (
--code /path/to/repo) - Image-as-Input: Multiple architecture diagrams per run — up to 5 named views (deployment, data flow, etc.) via a repeatable
-don the CLI (-d arch.png -d flow.mmd) or the API'sdiagrams[]field, rendered with a proper ELK layout - Deterministic Rule Engine: 362 curated patterns (STRIDE, MAESTRO, OWASP, MITRE ATT&CK/ATLAS, CAPEC, cloud misconfigs) across 16 seed files
- Export Formats: JSON, SARIF (GitHub Security), Markdown, PDF
- Multi-User Collaboration: Projects with owner/editor/viewer RBAC, threaded comments, assignments, activity log
- CI/CD Ready: CLI + GitHub Action with SARIF upload
Quick Start
# Install
pip install paranoid-cli
# Configure
paranoid config init
# Run (the examples are in the repo, not the package: clone it, or fetch one)
curl -fsSLO https://raw.githubusercontent.com/theAstiv/paranoid/main/examples/stride-example-api-gateway.md
paranoid run stride-example-api-gateway.md # saved to the database; add -o threats.json for a file
Docker (web UI + API):
git clone https://github.com/theAstiv/paranoid && cd paranoid
cp .env.example .env # add your API key
mkdir -p data # must be writable by uid 1000: `sudo chown 1000:1000 data` if yours differs
docker compose up --build # web UI at http://localhost:8000/app
Note: the dependency capability engine, Bedrock, model routing, multiple diagrams, CVSS and ATT&CK/ATLAS mapping need v1.6.0 or later (
pip install "paranoid-cli>=1.6.0"). The dependency engine also needs Semgrep onPATH(pip install semgrep); the Docker image includes it.
Try the full demo (Black Hat India Arsenal 2026)
examples/arsenal-deps/ is "MediaDrop", a fictional image-upload service with 8 real npm dependencies and three diagrams of the same system. Every command below runs against it.
# 1. Dependency capabilities inside a threat model (heatmap + drift in the web UI)
paranoid run examples/arsenal-deps/description.md \
--manifest examples/arsenal-deps/package.json \
--lockfile examples/arsenal-deps/package-lock.json --deps-source both
# A reconstructed (inert) event-stream-style incident: capability delta + drift, no LLM call
python examples/arsenal-deps/inject_incident.py --source both --no-llm
# 2. Three diagrams, ATT&CK/ATLAS techniques, CVSS next to DREAD
paranoid run examples/arsenal-deps/description.md -n 2 \
-d examples/arsenal-deps/diagrams/architecture.mmd \
-d examples/arsenal-deps/diagrams/upload-flow.mmd \
-d examples/arsenal-deps/diagrams/deployment.png \
--step-model extract_assets=main --step-model extract_flows=main \
--scoring-method both
# 3. Iterations + model routing, SARIF for GitHub code scanning
paranoid run examples/arsenal-deps/description.md -n 3 -v \
--manifest examples/arsenal-deps/package.json \
--lockfile examples/arsenal-deps/package-lock.json \
--format sarif -o mediadrop.sarif
CLI runs are saved to the local database (paranoid models list); start the web UI against the same DB_PATH to open them at http://localhost:8000/app. Set ANTHROPIC_EFFORT=medium for Claude: at the default effort a run takes about three times as long. Measured costs, timings and their sample sizes are in Benchmarks.
What the dependency engine claims: capability visibility plus change and discrepancy triage: what a dependency can do, what changed in a release, and what ships in the npm tarball that isn't in the repo. It doesn't claim to catch supply-chain attacks; see what it does not catch.
Documentation
| Guide | Description |
|---|---|
| Getting Started | Install, configure, and run your first threat model |
| CLI Reference | All flags, subcommands, and output formats |
| Configuration | All environment variables and config options |
| Web UI Guide | Browser interface walkthrough |
| Authentication | Multi-user setup, JWT, PATs, RBAC |
| API Reference | REST API — 83 route handlers across 13 route modules, plus /health and / in main.py |
| GitHub Action | Automated threat modeling in CI/CD |
| Architecture | System design, pipeline, data model |
| Benchmarks | An 11-model comparison on AWS Bedrock, routing savings per step, multi-diagram extraction, iterations, wall time, reliability and dependency-engine gates — dated, with sample sizes and caveats |
| Deployment | Docker, PyPI, binary, production hardening |
Other docs:
- CHANGELOG.md — Release history
- CONTRIBUTING.md — How to contribute
- SECURITY.md — Vulnerability reporting policy
- TESTING.md — Testing and CI guide
- Input-template.md — Structured input template reference
- examples/ — Working STRIDE and MAESTRO examples
Dependency capability engine
Static-analysis visibility into what an npm dependency can actually do — network access, filesystem, process spawning, dynamic code, native addons, and more — compared against its declared GitHub source, so a version bump that quietly adds a capability shows up before you install it.
# What can this package do? Fetches npm tarball + GitHub source, runs Semgrep.
paranoid deps scan chalk@5.3.0 --source both
# Did capabilities change between two versions? (this is the *shape* of
# checks that would have caught the real ua-parser-js/event-stream
# supply-chain compromises: a patch release quietly adding a capability
# nothing in the diff would obviously explain. These two specific versions
# are both clean — the actual malicious 0.7.29 was unpublished — this just
# shows the delta computing cleanly against real registry data.)
paranoid deps diff ua-parser-js 0.7.28 0.7.30 --source both
# Sweep every direct dependency in your project's package.json
paranoid deps scan-manifest path/to/your-project/package.json
Requires Semgrep on PATH (pip install semgrep) —
see SEMGREP_BINARY, DEPS_CACHE_DIR, DEPS_MAX_TARBALL_MB in
Configuration. Source is
always fetched read-only; nothing scanned is ever executed or installed.
What deps scan reports: a CapabilityProfile per source — categories
(network, filesystem, process, dynamic_code, native_ffi,
persistence, authentication, environment, crypto, deserialization,
build_install), each backed by file:line evidence and a real source
snippet, plus any postinstall/preinstall lifecycle hooks.
What drift signals mean: with --source both, paranoid deps scan
compares the npm tarball against the package's own GitHub source for one
version, per file. paranoid deps diff is a separate comparison — did this
package's capabilities change between two releases — computed from two
tarball scans; with --source both it additionally reports drift for the
newer version alone, using the same per-file logic described here:
- matched / explained_by_sourcemap / explained_by_build — the tarball file's capabilities are all accounted for by the corresponding GitHub file, a valid source map, or a declared build step. No signal.
- relocated (weak, informational) — a capability new to that file but already present elsewhere in the package. Worth a look, not proof of anything.
- signal (strong) — a capability novel to the entire GitHub-side scan. This is the actionable finding: shipped code does something the published source doesn't explain anywhere.
- generated_unverifiable (informational) — a file declared by the
package's own GitHub manifest (never the tarball's — the tarball is
attacker-controlled, so trusting its self-declaration would let an
attacker excuse any file just by listing it) that a non-npm build
toolchain (e.g. esbuild's Go build,
cargo build.rs) produces outside ofnpm run build. Can't be verified against source either way; never contributes a strong signal. - unverifiable — the tarball file's GitHub counterpart couldn't be fetched (a skipped symlink, an over-long path). Excused only against the package-wide GitHub category set, so a genuinely novel category still signals.
- Added
postinstall/preinstallhooks are graded separately: a non-allowlisted addition is a strong signal on its own (theua-parser-js-shaped compromise, caught without needing a previous version to diff against).
What it does not catch:
- Runtime-fetched payloads. A package that
fetch()s andeval()s a remote payload at runtime shows up as anetwork/dynamic_codecapability — the engine flags that the capability exists, not what the fetched code will do. - Obfuscation beyond the flagged shapes. The scanner recognizes specific,
deliberate evasion patterns (aliased
require/Function, concatenated or computed property calls, low-levelprocess.binding, etc. — seebackend/deps/rules/js/dynamic_code.yaml), not every possible way to hide a call. A sufficiently determined, hand-crafted obfuscation can still slip past static analysis; this is capability visibility and drift triage, not a guarantee of detection. - Generated files with no declared build step, or generated outside a recognized non-npm toolchain marker, still count as ordinary shipped code and can trip a signal even when they're legitimately build output.
- Non-JS/TS package ecosystems. Layer 1 is npm/JS+TS only; PyPI and other ecosystems aren't covered yet.
Read this as "here's what changed and what looks unexplained," not "this dependency is safe" or "this dependency is malicious" — every signal is meant to be triaged by a person, not acted on automatically.
Supported platforms
| Platform | PyPI | Docker | Binary |
|---|---|---|---|
| Ubuntu 20.04+ | ✓ | ✓ | ✓¹ |
| macOS 11+ ARM64 | ✓ | ✓ | ✓ |
| Windows 10+ | ✓ | ✓ | ✓ |
| WSL2 | ✓ | ✓ | ✓¹ |
¹ From v1.6.0 (paranoid-linux-x64). The v1.5.0 release has no Linux binary: its macOS build overwrote it, as both were named paranoid.
Full platform matrix: docs/deployment.md
Development Status
v1.6.0 — dependency capability engine, multi-user collaboration (accounts, projects, roles), AWS Bedrock, per-step model routing, multiple diagrams with ELK rendering, ATT&CK/ATLAS mapping and CVSS v3.1 scoring. See the CHANGELOG.
v1.5.0 — Non-technical users can open the web app, paste an API key, link a Git repo, and get a threat model — no terminal required.
Future: OIDC/SSO federation.
License
Apache 2.0
Metadata
Release files for paranoid-cli 1.6.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| paranoid_cli-1.6.0.tar.gz | 1.0 MB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| paranoid_cli-1.6.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 2.1 MB
Release files / paranoid_cli-1.6.0.tar.gz
| Download URL | paranoid_cli-1.6.0.tar.gz |
|---|---|
| Size | 1.0 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d32fa744da5415a1f21b86112dac496f792810d05b2e3f7bc8cf3ef15cda2d15
|
|
BLAKE2b-256 checksum How to use checksums |
9e58ba363a3e148349b939c8d92e28bc2340b40549f1cd5e4bc51827d5745db0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logRelease files / paranoid_cli-1.6.0-py3-none-any.whl
| Download URL | paranoid_cli-1.6.0-py3-none-any.whl |
|---|---|
| Size | 1.1 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f12a5cd75485c0ddb0c3bf0f80d980353d5a4481961a18980ea12aa6c33c60a0
|
|
BLAKE2b-256 checksum How to use checksums |
79de48b3ae867121a829b482a06855e765c4d930336cb58ade7bce24e7d648ce
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logSecurity for paranoid-cli 1.6.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for paranoid_cli-1.6.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.