Skip to content

Releases: Pantheon-Security/medusa

MEDUSA v2026.7.0

Choose a tag to compare

@rosschurchill rosschurchill released this 24 Jun 07:52
5f217ed

Claude Code supply-chain detection, broader language coverage, and rule-level observability.

Highlights

  • 🛡️ Claude Code compromise detection — medusa scan --git structurally vets .claude/ for poisoned hooks (curl|bash, base64→exec, credential exfil, reverse shells), over-broad permissions (Bash(*), bypassPermissions), wildcard-tool subagents, and dropper skills — before you clone.
  • 🎯 Always-on AI attack-signature scanner — catches jailbreak / prompt-injection payloads in data (.jsonl/.csv) and prose regardless of LLM-context confidence; invisible-unicode / bidi (Trojan Source, CVE-2021-42574) recovery.
  • 🦀 Native Rust security ruleset (22 rules) + .rs discovery fix — TLS-off, command injection, untrusted deserialization, raw SQL, unsafe memory, weak crypto, SSRF. Out-of-box, no toolchain.
  • 🐘 Native PHP security ruleset (16 rules) + .php discovery fix — SQLi, command/eval, LFI/RFI, path traversal, unserialize() object injection, unrestricted upload, reflected XSS, SSRF, weak crypto.
  • 🔬 Rule diagnostics (--trace-rules) — per-rule trace + timing + hang-survivable heartbeat; found & fixed a real catastrophic-backtracking ReDoS; ReDoS/nested-set lint (CR-050).
  • ⚡ Context-aware screening mode, large-file byte-cap sampling, placeholder-secret FP fix, scan-engine perf.

Verification

  • Full gate: pytest tests/ 560 passed; cross-platform CI green (Ubuntu/Windows/macOS × Py 3.10–3.12).
  • Self-scan adds 0 new findings; solana-pay 0→24 real Rust findings; clean code stays silent.

🤖 Generated with Claude Code

MEDUSA v2026.6.0

Choose a tag to compare

@rosschurchill rosschurchill released this 10 Jun 15:47
519a9b6

MEDUSA v2026.6.0 — code-review hardening + paid-code strip

A reliability, security, and correctness release. Combines the v2026.5.12 content (40,000+ rules + FP-hardening + integrity rewrite) with 20 fixes from a full multi-agent code review, and makes the free package fully standalone.

Reliability / correctness

  • --fail-on now actually fails the build (was a silent no-op — every CI gate was passing regardless of findings)
  • medusa scan --git no longer crashes on a default run (NameError)
  • --quick incremental cache now persists (was silently doing a full scan every time)
  • A FIFO/socket/device in the scan tree no longer hangs the whole scan
  • Per-scanner timeouts can no longer be swallowed; scanner crashes/timeouts are now recorded and summarised
  • Atomic cache writes; unreadable directories warned (no silent coverage loss); hardened config/rule-load guards; distinct internal-error exit code

Security

  • git clone hardened (no credential prompt, no token leak on timeout); cleartext http:// clones rejected; clone blob-size bound
  • Report files written 0o700 (they can embed detected secrets); defense-in-depth HTML/Markdown escaping

Output / housekeeping

  • Analyzer/rule counts corrected (79 / 40,000+); tightened ship-gate tests; suppressed nested-set FutureWarning console spam (notably on Windows)
  • Fixed long-standing CI workflow permission bug and invalid ruff/mypy version config

Standalone free product

Licensing, the REST API, and runtime rules have been removed from the package — the free scanner is fully self-contained and runs entirely locally.

Validation

441 tests passing; wheel smoke-tested in a clean venv on Linux and Windows; CI matrix green across Windows/macOS/Linux × Python 3.10–3.12.

MEDUSA v2026.5.11

Choose a tag to compare

@rosschurchill rosschurchill released this 28 May 07:32

`medusa scan --git` hotfix + 54-test ship gate suite

Fixed

  • `medusa scan --git` crashed on every invocation — Every `medusa scan --git ` in v2026.5.10 failed immediately with `NameError: name 'include_user_mcp_configs' is not defined` before scanning a single file. `_scan_git_repo()` was missing the parameter in both its function signature and the call site. Two-line fix.

Tests added

  • `TestScanGitRepoRegression` (`tests/test_git_scan.py`) — locks in the `--git` fix with signature inspection + end-to-end tests with mocked clone so this parameter-forwarding class of bug can never ship silently again.

  • `tests/test_ship_gate.py` — 54 new tests covering every major user-facing feature: `--fail-on`, `--exclude`, `--workers`, `--no-report`, `--no-cache`, `--quick`, `--force`, `--include-user-mcp-configs`, all output formats (`json`/`markdown`/`all`), custom `--output` paths, `--no-ai-safe`, HMAC tamper detection, `full_hash` cache mode, rule fingerprint invalidation, `secrets scan`/`purge` safety gates, and `MedusaParallelScanner` direct constructor params. These are now part of the pre-release gate.

Upgrade

```bash
pip install --upgrade medusa-security
```

Full changelog: https://github.com/Pantheon-Security/medusa/blob/main/CHANGELOG.md

v2026.5.10 — Security hardening patch

Choose a tag to compare

@rosschurchill rosschurchill released this 24 May 11:16

Security hardening patch — five fixes from external security review

Fixed

  • VS Code extension command injection — exec() replaced with execFile throughout scanner.ts. Binary path and args passed as argv array, never interpolated into a shell string. Shell metachar validation added on medusaPath (rejects ;|&\$()<>`).
  • --fail-on ignored cached findings — total_issues now counts cached scan results. Previously a re-scan with --fail-on high would silently pass if findings were cached.
  • --fail-on crashed on dict-backed findings — _get_severity() helper handles both object (.severity) and dict (.get('severity')) issue shapes.
  • Tool cache returned stale dummy path — _find_tool() calls shutil.which() to verify the cached tool exists before trusting it. Stale entries are evicted.
  • Full-file hash when --fail-on active — cache previously hashed only first 8 KB. Changes beyond that were invisible to threshold checks.
  • User-home MCP configs opt-in — ~/.config/Claude/claude_desktop_config.json and ~/.cursor/mcp.json now require --include-user-mcp-configs (were silently included in every scan).

Security

  • VS Code extension: eliminated OS command injection vector in all three scan entry points. CVSS 3.1 estimate: 8.8 (High) → 0.
  • Scanner core: --fail-on threshold now reliable in CI pipelines regardless of caching state.

Full changelog: https://github.com/Pantheon-Security/medusa/blob/main/CHANGELOG.md

v2026.5.9 — Agentic Commerce Coverage: UCPScanner + AP2Scanner + 45 hand-tuned rules

Choose a tag to compare

@rosschurchill rosschurchill released this 20 May 11:10

v2026.5.9 — Agentic Commerce Attack Coverage

Google's UCP (Universal Commerce Protocol) launched 2026-01-11 with Shopify,
Mastercard, Visa, Stripe, PayPal, Walmart, and Target. AP2 (Agent Payments
Protocol) is the companion standard for signed payment mandates. AI agents
will use these to spend money on users' behalf — and they ship with new
attack surface.

The headline

Three new dedicated scanners + 45 hand-tuned positive-pattern rules.

Scanner Detects
🛒 UCPScanner UCP discovery over plain HTTP, hardcoded UCP signing keys, unbounded agent mandates, missing fraud signals, malicious JSON-LD @context, PCI data in agent code
💳 AP2Scanner Long-lived payment tokens, signature-verify bypass (verify=False), private keys from filesystem, algorithm downgrade (HS256, none), card-data-in-logs
🎯 PISCANCodeScanner Prompt-injection-in-code: raw user input → messages.append, f-string prompt interpolation, untrusted HTTP tool output → chat.completions.create

Every rule uses positive detection — they fire on attack-shape code, not
on the absence of defensive code. This is the lesson the project learned the
hard way: negative-lookahead "X without Y on the same line" patterns produced
3,623 hits on the audit corpus (mostly FPs). The new shape produces 2 hits on
the same corpus, both potentially actionable.

Validation corpus

Each scanner was audited against real-world UCP/AP2/MCP codebases sourced
via MEDUSA's MinerHub research pipeline:

  • 12 UCP/AP2 repos: agentic-commerce-skills-plugins, AP2 (Google official),
    fastucp, ucp-merchant-server, ai-shopping-agent-ucp, Retail-Agentic-Commerce,
    ap2java, ucpjava, ucp-samples, agentic-payments-bot, ucp-merchant,
    agent-payment-protocols
  • 4 MCP servers: IMCP, hexstrike-ai, damn-vulnerable-MCP-server, MasterMCP
  • Synthetic positives covering attack-shape code for each of 5 rule classes

Result: 2 hits across 12 reference implementations. Both are
MEDUSA-UCP-DISC-001 — UCP discovery served over plaintext HTTP — and both
are configurations a security reviewer would triage. No spammy FPs.

What's detected (45 active rules across 5 files)

UCP (10 rules) — MEDUSA-UCP-DISC-001, AGENT-005, CRED-001..003,005,
AP2-005..006, BRIDGE-003, PI-001. CWE-319 (cleartext), CWE-798
(hardcoded creds), CWE-200 (PCI), CWE-345 (JSON-LD trust).

AP2 (5 rules) — TOKEN-003, CRYPTO-001..003, PSP-003. CWE-307
(no rate limit on auth), CWE-326 (weak crypto), CWE-321 (hardcoded
keys), CWE-117 (log injection).

MCP-SCAN (11 rules) — tool poisoning, reverse shells in tool handlers,
eval/exec on tool input, command injection, dynamic instruction loading,
tool output → exec, path traversal, infinite loops.

PI-SCAN (9 rules) — direct user input → LLM messages, f-string prompt
injection, raw HTTP tool output → LLM, role-field tampering (ChatInject),
system-prompt + user-input concatenation.

TUA-SCAN (10 rules) — hardcoded crypto keys, ECB mode, predictable PRNG
seeds, plaintext secret storage, AI-hallucinated package imports, deprecated
security APIs, LLM-guided fuzzing tools, untrusted tool chaining, embedding
inversion exposure.

Bug fix

parallel.py was dropping issue.rule_id when converting ScannerIssue →
JSON findings dict. Meant medusa scan --format json output had no rule IDs
— broke per-rule filtering, analytics, and post-hoc auditing. Two-line fix.

Try it

pip install -U medusa-security==2026.5.9
cd your-ucp-or-ap2-project
medusa scan .

Documentation

Quality

  • pytest tests/ → 419 passed, 10 skipped, 0 failed
  • Benchmark corpus regression → 5/5 passed (with refreshed baseline)
  • Security hardening → 55/55 passed
  • Self-scan on MEDUSA itself → 894 files, 0 crashes, 0 hits from new SHIP rules (correctly — we don't have the vulns these rules detect in our own code)

Tier

Free. No license required.


Previous release: v2026.5.8 — medusa secrets: scan AI chat & shell histories for leaked credentials with interactive [y/n/s/a/q] purge.

v2026.5.8 — medusa secrets: scan & purge credentials in AI chat & shell history

Choose a tag to compare

@rosschurchill rosschurchill released this 20 May 05:49

v2026.5.8 — medusa secrets

Your PyPI token might be in your Claude chat history right now.
v2026.5.8 ships the tool to find it — and the tool to fix it.

The headline

Developers paste credentials into AI assistants every day. The assistants keep
those conversations in plaintext on disk. Anyone with read access to $HOME
can harvest production secrets in seconds.

medusa secrets scan finds them. medusa secrets purge cleans them up.

$ medusa secrets scan
  ...
  Total: 13 credentials across 1 file(s).
  Report:  /home/ross/.medusa/secrets-scan/secrets-20260519-074452.json
$ medusa secrets purge

  [CRITICAL] PyPI API token (pypi)
      /home/ross/.claude/history.jsonl:125:94
      pypi-AgEIc***...***
    redact?  [y/n/s/a/q/?]: y
  ...
  ✓ /home/ross/.claude/history.jsonl  (13 redacted)
      backup → /home/ross/.medusa/secrets-scan/backups/20260519-074452/...

What's detected (21 issuers)

Category Providers
🤖 AI providers Anthropic · OpenAI · HuggingFace · Replicate · Cohere
📦 Package registries PyPI · npm
🐙 Source forges GitHub PAT (classic + fine-grained + OAuth + App) · GitLab PAT
☁️ Cloud AWS access keys · GCP service-account JSON
💳 Payments / comms Stripe live + restricted · Slack bot/user · SendGrid · Twilio · Discord webhooks
🔑 Cryptography PEM private keys (RSA · DSA · EC · OpenSSH · PGP · encrypted)

Where it scans

AI chat histories — Claude Code, Claude Desktop, Cursor, Zed, VS Code Copilot,
Gemini CLI, Aider, Codex CLI.

Shell histories — bash, zsh, fish, python REPL, node REPL, psql, mysql, irb,
redis-cli, sqlite.

Filter with --source ai-chats or --source shell. Or scan a specific file
(e.g. a ChatGPT export) with --path <file>.

Safety properties

  • 🔒 Local-only. No telemetry. No network calls. Reports mode 0o600 under ~/.medusa/secrets-scan/. Never written to project trees.
  • 🙈 Masked by default. Output is pypi-AgEIc***...*** — safe to screenshot. --reveal requires typed I UNDERSTAND to reveal full values.
  • 💾 Backup before write. Every redaction is preceded by a byte-identical backup; cp restores it.
  • 🧩 JSONL-safe. Redaction marker contains no JSON-unsafe characters. Modified lines are re-parsed; a parse failure aborts the write.
  • 🛑 Refuse on drift. If the source file changed between scan and purge, the purger refuses rather than risk clobbering an edit.

Try it

pip install -U medusa-security==2026.5.8
medusa secrets scan

Documentation

Quality

  • 28 new unit tests for the secrets feature; full suite 419 passed / 10 skipped / 0 failed
  • Benchmark corpus regression: 5/5 passed
  • Security hardening tests: 55/55 passed
  • Self-scan on MEDUSA itself: 879 files scanned, 0 crashes
  • End-to-end manual verification against real chat-history layouts on Linux: scan + report write + interactive purge + JSONL re-parse + backup-and-restore round-trip all clean

Tier

Free. No license required.


Previous release: v2026.5.7 — Indirect PI rules, supply chain import-pattern scanner, macOS/Windows multiprocessing fix.

v2026.5.7 — Indirect PI Rules, Supply Chain Scanner, Cross-Platform Multiproc Fixes

Choose a tag to compare

@rosschurchill rosschurchill released this 13 May 08:32

What's New in v2026.5.7

New Features

Feature Details
🕵️ Indirect PI Rules (101/102) 50 new patterns for social authority injection and covert action concealment — adversarial attack patterns used to manipulate AI agents without triggering obvious injection keywords
📦 Supply Chain Import Scanner Detects malicious package names in dependency manifests (npm, pypi, go, cargo, maven) without requiring CVE version matching. Rules with fixed: none/n/a/unfixed always fire.
🔒 Report Payload Obfuscation Reports default to obfuscating dangerous strings so the report itself can't be used as a prompt injection vector. Pass --no-ai-safe to disable for verbatim findings.
🛠️ garak + llm-guard in AI Tools medusa install --ai-tools now installs garak (LLM red-team framework) and llm-guard alongside modelscan

Bug Fixes

Fix Impact
🧩 FP over-suppression: security parent dirs Repos stored under any *security* parent directory had ALL findings suppressed (e.g. mcp-exploit-demo: 0→13 findings, IMCP: 0→80 findings)
🍎 macOS/Windows multiprocessing Batch Trivy/Semgrep/GitLeaks caches now rehydrated in spawn-mode workers via Pool initializer — findings were missing on non-Linux platforms
🏠 Project-root scan boundary Batch scanners always target the project root. Previously, including a path outside the project (e.g. ~/.cursor/mcp.json) could expand the batch scan to $HOME
📦 gradle.lockfile picked up Added to special_exact_names so Trivy can scan Gradle dependency lockfiles for CVEs

Installation

pip install medusa-security==2026.5.7

Note

This release supersedes v2026.5.6, which was withdrawn. Pin directly to 2026.5.7.

v2026.5.5 — Security Hardening

Choose a tag to compare

@rosschurchill rosschurchill released this 18 Apr 10:07

MEDUSA v2026.5.5 — Security Hardening

Patch release addressing 8 findings from a red-team review of the MEDUSA scanner codebase. No CVEs are disclosed against earlier versions — these are defense-in-depth improvements.

What changed

Argument injection defense (C-1)

A malicious repo containing a file literally named --config=https://evil.tld/rce.yaml would previously have had the filename re-parsed as an option by semgrep and trivy, causing them to fetch attacker-controlled rule YAML from the network. This is blocked at two layers now: a -- separator before trailing path args, plus a defensive reject of any file whose basename starts with -.

Git URL SSRF defense (H-1, M-2)

medusa scan --git <URL> previously accepted any http(s)/ssh URL with no validation. Now defended with a hostname allowlist (github.com, gitlab.com, bitbucket.org, codeberg.org, plus subdomains) and DNS-rebinding-resistant private IP rejection (is_private/is_loopback/is_link_local/is_reserved/is_multicast on every resolved address). New --allow-any-host flag opts out of the hostname allowlist; private-IP rejection still applies.

Cache integrity (H-2)

~/.medusa/cache/file_cache.json is now HMAC-signed with a machine-local key at ~/.medusa/cache/.hmac_key (mode 0600). An attacker with write access to a dev workstation or CI runner can no longer forge cache entries to silently suppress findings. The v5.4 → v5.5 upgrade path discards the unsigned cache silently and rebuilds on the next scan. Cached findings are also now included in the generated report (previously silently dropped).

Markdown XSS prevention (M-1)

Generated markdown reports now use a dynamic code-fence length based on the content — source code containing ``` can no longer break out of the fence and inject raw HTML into a GitHub / GitLab markdown preview. Filenames with backticks are sanitized before interpolation into inline code spans.

Other hardening

  • L-1 + M-3: Removed two dead HTML builder functions that interpolated severity strings into style attributes without escape.
  • L-3: scan_history.json load is now crash-safe on corrupted or malicious input.

Testing

  • 55 new tests in tests/test_security_hardening.py
  • Full suite: 378 pass + 55 new security tests
  • 11 pre-existing failures (unrelated) confirmed unchanged vs v2026.5.4

Deferred

These two findings from the same review are tracked for separate sprints:

  • License HMAC forgery (medusa/core/licensing.py) — uses a keyless SHA-256 truncated to 16 hex chars. Needs Ed25519 migration + license server coordination.
  • IDE setup symlink race (medusa/ide/claude_code.py) — local attacker only.

Upgrade

pip install --upgrade medusa-security

No breaking API changes. The existing cache file is silently discarded on first scan (unsigned) and rebuilt. First scan after upgrade will be a full rescan.

Install footprint

  • Wheel: 3.2 MB (medusa_security-2026.5.5-py3-none-any.whl)
  • Source: 3.1 MB (medusa_security-2026.5.5.tar.gz)
  • 27 FP pattern YAML files bundled

v2026.5.4 — FP Patterns YAML Refactor

Choose a tag to compare

@rosschurchill rosschurchill released this 16 Apr 20:58

MEDUSA v2026.5.4 — FP Patterns YAML Refactor

Summary

Pure refactor release. Moves 583 false positive filter patterns from a 6,746-line Python file (medusa/core/fp_patterns_db.py) into 27 per-scanner YAML files under medusa/core/fp_patterns/. Zero behavior change — the regression benchmark produces byte-identical findings.

Why

  • Data/logic separation. FP patterns were data masquerading as Python code. YAML is the right format for data.
  • Editable without a Python diff. Contributors tuning FP rules no longer need to touch Python. A new pattern is one YAML entry.
  • Countable with standard tools. Pattern counts are now trivially derivable (grep, yq) — previously required AST parsing.
  • Attack surface slightly reduced. yaml.safe_load rejects arbitrary Python object construction; the old Python data file was executable code at import time.

What Changed

Added

  • medusa/core/fp_patterns/ — 27 YAML files (26 per-scanner + _universal.yaml for cross-scanner patterns)
  • load_known_fp_patterns() loader in fp_filter.py with strict schema validation
  • FPPatternSchemaError — raised on unknown keys, invalid FPReason enum values, or missing required fields
  • RULE_PROMOTION.md — documented workflow for promoting rules from medusa-rules into production, with smoke testing and benchmark validation

Removed

  • medusa/core/fp_patterns_db.py (6,746 LOC) — data migrated to YAML

Changed

  • README.md — FP pattern count corrected: 514 → 583 (97.7% FP reduction rate)
  • pyproject.toml — package-data now ships core/fp_patterns/*.yaml

Behavior Guarantees

Every one of these was verified before release:

  • KNOWN_FP_PATTERNS loads 583 patterns (matches source file count)
  • FalsePositiveFilter._FP_BY_SCANNER bucket dict is byte-identical to pre-migration
  • Known duplicate pattern names (go_unsafe_package, shellcheck_single_quotes) preserved — not deduped
  • Regression benchmark: 7 issues, 291 FPs filtered, 97.7% reduction — unchanged
  • All 40 smoke tests pass (test_basic, test_fp_filter, test_regression)

Net Impact

  • −2,713 LOC repo-wide
  • −6,746 LOC Python
  • +3,505 LOC YAML
  • +141 LOC loader

Security Notes

No CVEs. Migration is security-neutral with a marginal improvement: YAML data files cannot execute code; the old Python data file could.

Upgrade

pip install --upgrade medusa-security

No config changes required. No breaking API changes.

MEDUSA v2026.5.3 — CVE Database Update

Choose a tag to compare

@rosschurchill rosschurchill released this 08 Apr 20:45

CVE Database Update

Updated CVEMiner database to 2026-04-08 build.

Previous Now
CVEs 200 184 + 125 critical = 309 total
Generated 2026-03-18 2026-04-08

Install / Upgrade

pip install --upgrade medusa-security