Skip to main content

Open-source iterative threat modeling powered by LLMs - STRIDE + MAESTRO frameworks with DREAD scoring

Project description

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 to run: docker compose up[coming soon]
  • Multi-Provider LLM: Anthropic, OpenAI, or Ollama (fully local/air-gapped)
  • Dual Framework Support: STRIDE (traditional) + MAESTRO (AI/ML) auto-detected or run in parallel
  • DREAD Risk Scoring: Automatic risk assessment with 5 dimensions (0-50 scale) for severity classification
  • Structured Input Templates: Tagged templates for component descriptions with assumption enforcement in the prompts
  • Iterative Refinement: 1–15 configurable iteration passes with gap analysis
  • Code-as-Input: Semantic code extraction via context-link MCP — --code /path/to/repo grounds threats in actual implementation
  • Image-as-Input: Architecture diagram support via --diagram arch.png (vision API) or --diagram flow.mmd (Mermaid text)
  • Deterministic Fallback: Rule engine ensures known threats aren't missed[Coming Soon]
  • Export Formats: JSON (simple/full), SARIF (GitHub Security integration)
  • CI/CD Ready: CLI + GitHub Action with SARIF upload for automated threat detection

Quick Start

Step 1: Install

Choose the method that works best for you:

PyPI (Recommended):

pip install paranoid-cli
paranoid --version

Docker [Coming Soon]:

docker pull theastiv/paranoid:latest

docker run --rm \
  -v $(pwd):/workspace \
  -e ANTHROPIC_API_KEY=sk-ant-xxx \
  theastiv/paranoid:latest \
  paranoid run /workspace/system.md

Standalone Binary (No Python Required):

Download the pre-built binary for your platform from GitHub Releases:

Platform Binary
Linux x86_64 paranoid-linux-x64
macOS ARM64 (Apple Silicon) paranoid-macos-arm64
Windows x64 paranoid-windows-x64.exe
# Linux/macOS
chmod +x paranoid-linux-x64
./paranoid-linux-x64 --help

From Source (Development):

git clone https://github.com/theAstiv/paranoid
cd paranoid
pip install -e .

Step 2: Configure

Option A: Interactive Wizard (Recommended)

paranoid config init

# Follow prompts to configure:
#   - LLM Provider (Anthropic/OpenAI/Ollama)
#   - API Key
#   - Model name
#   - Default iterations

paranoid config show

Option B: Environment Variables

cp .env.example .env

Edit .env and add your provider configuration:

# Anthropic (Recommended)
ANTHROPIC_API_KEY=sk-ant-api03-xxxxxxxxx
DEFAULT_PROVIDER=anthropic
DEFAULT_MODEL=claude-sonnet-4-20250514

# OR OpenAI
OPENAI_API_KEY=sk-xxxxxxxxx
DEFAULT_PROVIDER=openai
DEFAULT_MODEL=gpt-4-turbo

# OR Ollama (fully local, no API key)
OLLAMA_BASE_URL=http://localhost:11434
DEFAULT_PROVIDER=ollama
DEFAULT_MODEL=llama3

# Optional: path to context-link binary for --code flag
# If unset, Paranoid looks for bin/context-link then PATH
CONTEXT_LINK_BINARY=/usr/local/bin/context-link

Step 3: Run Your First Threat Model

# Run with an example
paranoid run examples/stride-example-api-gateway.md

# With your own system description
paranoid run my-system.md

# See all options
paranoid run --help

Expected Output:

Configuration:
  Provider: anthropic
  Model: claude-sonnet-4-20250514
  Iterations: 3
  Framework: STRIDE

[>] summarize: Generating system summary...
[OK] summarize: Summary generated: 196 chars
[>] extract_assets: Identifying assets and entities...
[OK] extract_assets: Identified 14 assets/entities
[>] extract_flows: Extracting data flows and trust boundaries...
[OK] extract_flows: Identified 12 flows, 6 boundaries
[>] generate_threats [iter 1]: Generating threats (iteration 1/3)...
[OK] generate_threats [iter 1]: Generated 10 threats
...
[OK] complete: Pipeline complete: 2 iterations, 17 threats

================================================================================
THREAT MODEL COMPLETE
================================================================================
Total Threats:      17
Iterations:         2
Duration:           115.0 seconds
Output:             stride-example-api-gateway_threats.json

Expected Runtime:

  • Claude Sonnet: ~30-60 seconds (3 iterations)
  • GPT-4: ~45-90 seconds (3 iterations)
  • Ollama (local): 2-5 minutes (depends on hardware)

CLI Reference

Running Threat Models

# Basic usage (auto-detects framework from input)
paranoid run system.md

# Structured templates (auto-detects STRIDE vs MAESTRO)
paranoid run examples/stride-example-api-gateway.md
paranoid run examples/maestro-example-rag-chatbot.md

# JSON output (simple format - lightweight, ~2-3 KB)
paranoid run system.md --output threats.json

# JSON output (full format - complete models + DREAD + events, ~45 KB)
paranoid run system.md --format full -o complete.json

# SARIF export for GitHub Security integration
paranoid run system.md --format sarif -o threats.sarif

# Force dual framework (STRIDE + MAESTRO in parallel)
paranoid run system.md --maestro

# Override iteration count (1-15)
paranoid run system.md --iterations 7

# Override framework auto-detection
paranoid run system.md --framework MAESTRO

# Quiet mode (suppress real-time output, show only summary)
paranoid run system.md --quiet

# Verbose mode (show detailed event data with complete models)
paranoid run system.md --verbose

# Code-as-input: ground threats in actual source code (requires context-link binary)
paranoid run system.md --code /path/to/repo

# Image-as-input: include architecture diagram (PNG/JPG via vision API)
paranoid run system.md --diagram architecture.png

# Image-as-input: Mermaid diagram as text (all providers)
paranoid run system.md --diagram flow.mmd

# Combined: description + diagram + code context
paranoid run system.md --diagram arch.png --code /path/to/repo

Configuration Management

# Interactive setup wizard
paranoid config init

# Reconfigure (overwrite existing config)
paranoid config init --force

# Display current configuration
paranoid config show

# Config file location: ~/.paranoid/config.json

Version Info

# Show version, Python version, dependencies, and current configuration
paranoid version

Output Formats

JSON Simple (default, ~2-3 KB)

Lightweight threat summaries for CI/CD dashboards and quick reviews.

{
  "execution": {
    "total_threats": 17,
    "iterations_completed": 2,
    "duration_seconds": 115.0
  },
  "threats": [
    {
      "name": "JWT Token Forgery",
      "category": "Spoofing",
      "target": "API Gateway",
      "impact": "Complete authentication bypass",
      "likelihood": "Medium",
      "mitigation_count": 3
    }
  ]
}

JSON Full (~45 KB)

Complete Pydantic models with DREAD scores and full pipeline event audit trail. Suitable for detailed analysis, archival, and integration with other tools.

paranoid run system.md --format full -o complete.json

SARIF (GitHub Security Integration)

SARIF 2.1.0 format for GitHub Security tab, GitLab, VS Code, and Azure DevOps:

paranoid run system.md --format sarif -o threats.sarif

GitHub Actions Integration:

name: Threat Model

on: [push, pull_request]

jobs:
  threat-model:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Run threat modeling
        run: |
          pip install paranoid-cli
          paranoid run system.md --format sarif -o threats.sarif
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}

      - name: Upload to GitHub Security
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: threats.sarif

Code-as-Input (--code)

Ground threats in actual source code using the context-link MCP binary. When --code is provided, Paranoid extracts a semantically relevant slice of the codebase and threads it through every pipeline node.

paranoid run system.md --code /path/to/repo
paranoid run system.md --code /path/to/repo --iterations 5
paranoid run system.md --diagram arch.png --code /path/to/repo  # combined

How it works:

  1. Three-tier extraction funnel (50KB budget, ~12.5K tokens):

    • Semantic search: semantic_search_symbols finds symbols relevant to the threat model description
    • Code body extraction: get_code_by_symbol fetches full source for top results
    • File skeletons: get_file_skeleton fills remaining budget with structural outlines
  2. Code summary step: A summarize_code() node condenses the raw 50KB CodeContext into a focused ~2KB CodeSummary (tech stack, entry points, auth patterns, data stores, security observations). This runs concurrently with summarize() to hide latency.

  3. Full pipeline threading: The CodeSummary is passed to all downstream nodes — extract_assets, extract_flows, generate_threats, and gap_analysis — so threats reference actual implementation details.

  4. Deterministic fallback: If the summarize_code() LLM call fails, a code-metadata extractor produces the CodeSummary from file extensions, import patterns, and keyword matches. The pipeline never silently drops code context.

Requirements:

  • context-link binary at bin/context-link (relative to working directory), on PATH, or at the path set by CONTEXT_LINK_BINARY
  • Binary discovery order: explicit CONTEXT_LINK_BINARY env var → ./bin/context-linkshutil.which("context-link")
  • If the binary is not found, Paranoid logs a warning and continues without code context

Error handling: Every MCP failure degrades gracefully — binary not found, subprocess crash, tool call error, and index timeout all produce a warning and allow the pipeline to continue with text-only input.


Image-as-Input (--diagram)

Supply an architecture diagram alongside your text description. Paranoid passes it to every pipeline node for richer threat coverage.

# PNG or JPG via vision API
paranoid run system.md --diagram architecture.png
paranoid run system.md --diagram architecture.jpg

# Mermaid (.mmd) as text — works with all providers
paranoid run system.md --diagram flow.mmd

# Combined with code context
paranoid run system.md --diagram arch.png --code /path/to/repo

Supported formats:

Format Mechanism Size Limit
PNG Vision content block (base64) 5MB
JPG/JPEG Vision content block (base64) 5MB
Mermaid .mmd <architecture_diagram> XML tag (text) 100KB

Provider support:

Provider PNG/JPG Mermaid
Anthropic (all models) Full support Full support
OpenAI gpt-4o, gpt-4o-mini Full support Full support
OpenAI other models Not supported (use gpt-4o) Full support
Ollama Logs warning, continues without image Full support

How it works:

  • PNG/JPG: The image is base64-encoded and passed as a vision content block in the provider's native format (Anthropic image content block; OpenAI image_url data URI). Each prompt's <architecture_diagram> instruction is replaced with a vision-specific directive.
  • Mermaid: The .mmd file is read as UTF-8 text and injected as <architecture_diagram> XML in the prompt. All providers parse Mermaid syntax natively — no rendering required.
  • Pipeline threading: DiagramData threads through all 5 pipeline nodes: summarize, extract_assets, extract_flows, generate_threats, and gap_analysis.

Structured Input Templates

Paranoid supports rich XML-tagged templates for better context and assumption enforcement. See Input-template.md for the full template reference and examples/ for working examples.

STRIDE Template (traditional systems): Component description with technology stack, interfaces, data handling, and 6 structured assumption sections.

MAESTRO Template (AI/ML systems): Extended component description with mission alignment, agent profile, and 9 structured assumption sections.

Model Configuration

Use Claude Sonnet (or newer) for reliable structured output generation.

Model Status Notes
claude-sonnet-4-20250514 Recommended Validated end-to-end, reliable for production
claude-haiku-4-5-20251001 Not recommended Fails with JSON parsing errors on complex outputs
GPT-4 Turbo Supported Works well, slightly slower
Ollama (Llama 3 70B+) Supported Fully local, no external API calls

Architecture

  • Backend: FastAPI + SQLite + sqlite-vec
  • Frontend: Planned (v1.0 is CLI-only)
  • LLM Providers: Anthropic / OpenAI / Ollama (protocol-based, swappable)
  • Pipeline: Plain async functions (no LangChain, no LangGraph)
  • Embeddings: Local via fastembed (ONNX, BAAI/bge-small-en-v1.5)
  • Models: Pydantic v2 for all data validation
  • Frameworks: STRIDE (traditional) + MAESTRO (AI/ML security)
  • Code context: context-link MCP binary (Go) + MCPCodeExtractor async context manager
  • Image input: backend/image/ package — encoder.py (PNG/JPG base64), mermaid.py (text load), validation.py (size/format)

Python API:

from backend.pipeline.runner import run_pipeline_for_model
from backend.providers.anthropic import AnthropicProvider
from backend.models.enums import Framework

provider = AnthropicProvider(api_key="your-key")

async for event in run_pipeline_for_model(
    model_id="web-app-001",
    description="E-commerce web application...",
    framework=Framework.STRIDE,
    provider=provider,
    max_iterations=3,
):
    print(f"[{event.step}] {event.message}")

Testing

# Run unit/integration tests (no API key required)
pytest tests/ -v

# Run pipeline integration test (requires API key)
python test_pipeline.py

# Validate structured input parser (no API key required)
python examples/test_structured_input.py

# Lint
ruff check backend/ cli/
ruff format backend/ cli/

Validated Results (2026-03-24):

  • Parser validation: PASSING (no API key required)
  • STRIDE pipeline: PASSING (15-25 threats)
  • STRIDE+MAESTRO dual framework: PASSING (24 threats, 213s, 2 iterations)
  • Assumption enforcement: VALIDATED
  • Gap-driven iteration stopping: VALIDATED

Troubleshooting

Authentication errors:

  • Check your API key is correct in .env or ~/.paranoid/config.json
  • For Anthropic, ensure billing is set up and key starts with sk-ant-api03-

Module not found:

pip install -e .  # or: pip install paranoid-cli

Ollama connection refused:

ollama serve  # start Ollama first, then run paranoid

--code flag: context-link binary not found:

# Option 1: set env var pointing to the binary
export CONTEXT_LINK_BINARY=/path/to/context-link

# Option 2: place binary at bin/context-link relative to working directory

# Option 3: add context-link to PATH

If the binary is missing, Paranoid logs a warning and continues without code context.

--diagram with OpenAI and vision errors: Only gpt-4o and gpt-4o-mini support JSON structured output together with vision. Other OpenAI models that support vision do not support JSON mode simultaneously. Switch to gpt-4o or use Anthropic.

--diagram with Ollama: Ollama does not support vision for most models. Paranoid logs a warning and continues without the image. Use --diagram flow.mmd (Mermaid text) instead — all providers support Mermaid.

macOS binary "developer cannot be verified":

xattr -d com.apple.quarantine paranoid-macos-arm64

Windows "Windows protected your PC": Click "More info" then "Run anyway", or add an exception in Windows Defender.

Platform Support

Platform PyPI Docker Binary
Ubuntu 20.04+ Yes Yes Yes
Debian 11+ Yes Yes Yes
RHEL 8+ Yes Yes Yes
macOS 11+ (Intel) Yes Yes No
macOS 11+ (ARM64) Yes Yes Yes
Windows 10+ Yes Yes Yes
WSL2 Yes Yes Yes

Documentation

Developer docs:

Development Status

v1.2.0 — CLI production-ready, available on PyPI and as standalone binaries.

Completed: Core pipeline (8 nodes, iteration logic, SSE, dual framework), LLM providers (Anthropic/OpenAI/Ollama), STRIDE + MAESTRO prompts, structured input templates, JSON + SARIF export, DREAD scoring, CLI with config wizard, code-as-input via context-link MCP (--code), image-as-input via vision API and Mermaid text (--diagram), packaging and release automation.

Future (v2.0+): RAG retrieval integration, deterministic rule engine, REST API routes, frontend (Svelte UI).

License

Apache 2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

paranoid_cli-1.2.0.tar.gz (113.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

paranoid_cli-1.2.0-py3-none-any.whl (112.8 kB view details)

Uploaded Python 3

File details

Details for the file paranoid_cli-1.2.0.tar.gz.

File metadata

  • Download URL: paranoid_cli-1.2.0.tar.gz
  • Upload date:
  • Size: 113.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for paranoid_cli-1.2.0.tar.gz
Algorithm Hash digest
SHA256 de76dcf063c76a316dd36ac83c48359833845d059883c67038830dc3e40c5f5d
MD5 51bf2383cbb868f6a2cf22dd536b14a7
BLAKE2b-256 299c20eacdcd68958c1a00df8dac2903dd817b751a64db64d581b384c69ed06f

See more details on using hashes here.

Provenance

The following attestation bundles were made for paranoid_cli-1.2.0.tar.gz:

Publisher: release.yml on theAstiv/paranoid

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file paranoid_cli-1.2.0-py3-none-any.whl.

File metadata

  • Download URL: paranoid_cli-1.2.0-py3-none-any.whl
  • Upload date:
  • Size: 112.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for paranoid_cli-1.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8d4e2c76b268c9a7d0d1c47458c90f5b8ca3511a9df8dd4e42fef857f9f01cc2
MD5 b1297a53f887ae195c734a3446c1956b
BLAKE2b-256 177d67b9f497803e0501f1628a1348216ab9a0394c5e55d684baafa9729f6c3c

See more details on using hashes here.

Provenance

The following attestation bundles were made for paranoid_cli-1.2.0-py3-none-any.whl:

Publisher: release.yml on theAstiv/paranoid

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page