# Medusa's 40,000 patterns came from papers, and one of them hung the scanner

> An AGPL Python scanner for AI, agent and MCP codebases whose headline pattern count jumped fourfold in a single release, whose large-file and confidence-based gates both leaked payloads, and whose secrets purge makes a byte-identical copy of the file it cleans.

**Pantheon-Security/medusa** — AI-first security scanner. NEW in v2026.7: Claude Code compromise detection — vet .claude/ hooks, permissions & skills before you clone — plus an always-on AI attack-signature scanner and native Rust & PHP rules. Also: medusa scan --git to vet any repo, medusa secrets scan for leaked API keys. 40,000+ patterns, zero setup.

- Repository: https://github.com/Pantheon-Security/medusa
- Website: https://pantheonsecurity.io
- Stars: 999 · Forks: 154
- Language: Python
- License: AGPL-3.0
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/pantheon-security-medusa

## The pattern count quadrupled in one release and the rules are patterns

The number in the headline is 40,000 or more detection patterns, and the release notes explain how it got there. One version describes the largest pattern release to date: 9,600 becomes 40,000 or more, harvested from 8,466 AI-security research papers, false-positive-hardened, with a structural rule-integrity scanner added alongside. That is an unusual provenance claim for a scanner, and it is also the softest number in the project, because a ruleset assembled from literature at that scale is exactly the kind of thing that needs policing.

It gets policing. The newest release adds per-rule diagnostics that log which rule fired and how long it took, writing to a rule trace file and a slow rules file, plus a heartbeat that survives a hang. The stated reason is that this found and fixed a real catastrophic-backtracking denial of service in a rule, and the release also adds a lint that blocks bad patterns at author time.

Meanwhile the language coverage arrives as out-of-the-box rules rather than as analysers: 22 native Rust rules and 16 native PHP rules, none of which needs a toolchain, covering disabled TLS verification, command injection, untrusted deserialisation, raw SQL, unsafe memory operations, SQL injection, path traversal and object injection through unserialize. The file is explicit that external linters such as bandit, eslint and shellcheck are auto-detected only if you already have them. So the Rust and PHP coverage is pattern matching, and the comparison to a compiler-backed analyser is not on offer.

## Two coverage limits are named in the same release that adds the feature

The newest version adds what the file calls an always-on attack-signature scanner, and the description leads with the reason: it closes a false-negative gap. Jailbreak and prompt-injection payloads sitting in data files with .jsonl and .csv extensions, and in prose, are now caught regardless of how confident the scanner was about the surrounding language-model context. Also in that release is invisible-unicode and bidirectional text recovery, aimed at Trojan Source and the 2021 bidi vulnerability class.

Read together, those two items describe what a scanner misses in two different ways. The first is a gate: payloads in files the tool was reading were only flagged when it felt confident about the context, which is a reasonable design for reducing noise and a bad one for missing an injection hidden in a CSV. Turning the gate off for signatures is the fix.

The second way is a size limit, and it appears in the engine notes as large-file byte-cap sampling. Above a cap, a file is sampled rather than read end to end. Nothing in the release notes says what the cap is, or whether a sample covers the beginning, the end or both, so a very large generated file or a vendored bundle is the case where this tool's answer should not be trusted. There is a context-aware screening mode for vetting a repository target as well, which is a fourth knob describing how much of a file the engine believes it has understood.

## The secrets purge keeps a byte-identical copy of the secrets it removes

The feature scans for credentials in the places developers actually paste them: Claude Code, Cursor, Copilot, Zed and Gemini chat histories, plus bash, zsh, psql, mysql and Python REPL histories, across 21 issuer types. The sample output shows what a hit looks like:

```bash
medusa secrets scan
```

```text
Scanning 118 file(s)...

── claude-code ──────────────────────────────────────────────
/home/ross/.claude/history.jsonl  (13 finding(s))
[CRITICAL] Anthropic API key (anthropic)
    /home/ross/.claude/history.jsonl:1005:13
    sk-ant-api03***...***
[CRITICAL] PyPI API token (pypi)
    /home/ross/.claude/history.jsonl:125:94
    pypi-AgEIc***...***
```

The purge is interactive with per-file choices, and the file stresses two properties: the redaction is JSONL-safe, so a rewritten history still parses line by line, and the backup is mandatory and byte-identical. That second property is the one to think about. A byte-identical backup of a history file is a second copy of every credential in it, on the same disk, with the same permissions. Redacting the original is the goal; the guarantee that nothing is lost is what produces the duplicate. Anyone running this should decide where that backup goes before running it, and treat rotation of the exposed keys as the actual remedy, since a copy of a leaked key sitting in a home directory does not get better with age.

## The repository ships the scanner's own config and a document about rule promotion

Look at what sits at the root and the project's priorities come into focus. There is a configuration file for the scanner, checked into the repository alongside its own results, which makes this repository the tool's first test case rather than a place where the tool is merely mentioned. There is a directory holding bandit configuration, so the scanner is scanned by the linter it also auto-detects. There is a document with a name like RULE_PROMOTION.md, sitting next to a changelog, a security policy and a code of conduct.

A ruleset of that size needs governance, and the governance artefact is a file about how rules get promoted rather than a paragraph in the readme. That is the right shape for the problem, because the failure mode of a 40,000-pattern ruleset is not that patterns are missing but that a hundred people can add one without anybody reviewing it.

The rest of the root is distribution: a Dockerfile whose name is a claim about its own complexity, a formula directory for a package manager, a manifest file, a packaging script kept only for older installer versions, the two documentation directories, an examples directory, media, tests, scripts and the package itself. Everything needed to run, lint, package and distribute the scanner is in one repository, which is convenient and also means a single compromise reaches all of it.

## The release notes and the tags do not describe the same releases

The readme keeps a collapsed list of previous releases, and it names v2026.5.12 as the big pattern release, then v2026.5.10, v2026.5.9, v2026.5.8, v2026.5.7 and v2026.5.5. The tags tell a different story. The three most recent are v2026.7.0 from 2026-06-24, v2026.6.0 from 2026-06-10 and v2026.5.11 from 2026-05-28.

So the readme documents a version, v2026.5.12, that is not among the recent tags, and the tags include a version, v2026.5.11, that the readme's own list skips. One of the two histories is incomplete, and neither says which. The practical consequence is small unless you are auditing what you are running: if you want to know whether a fix landed, the changelog and the tag list have to be reconciled by hand.

There is a second gap. The last push on record is 2026-08-10, which is about seven weeks after the newest tag. Whatever is on the default branch today is newer than the newest release, and the newest release is what an installer gets. The version scheme is calendar-based, which makes the year and month legible at a glance and makes a release that is two months behind the branch line obvious to anyone who checks.

## Two units for the same coverage claim, and one of them is undefined

The readme leads with pattern counts and known vulnerability coverage: 40,000 or more patterns and 200 CVE detections, with Log4Shell, Spring4Shell, the XZ Utils backdoor, LangChain remote code execution, MCP remote code execution and React2Shell named in the banner. The package manifest leads with something else: 79 analyzers. Neither number is defined in the files a reader sees. How many patterns make an analyzer, and how one CVE detection is counted, is left to documents behind links.

Two more claims in the banner deserve a second reading. Parallel scanning is described as 10 to 40 times faster than sequential, a range wide enough that it is describing hardware rather than a benchmark. And the caching is described as content-hash keyed and correct in continuous integration, which is a specific promise: the release history shows a cached-findings bug in the fail-on behaviour, a stale tool-cache path fix and the addition of HMAC integrity to the cache, all of which are the ways a cache like this goes wrong.

The dependency list explains how the tool reaches zero setup without giving anything up. It ships eleven runtime packages and nothing else: a command line library, a terminal renderer, a progress bar, an HTTP client, a YAML parser, a process library, an XML parser chosen specifically because it is hardened against entity attacks, a TOML writer and reader, and a path specification matcher for ignore rules. Language analysis is not delegated, and neither is XML parsing.

## Repository vetting looks inside .claude/ before you clone

The newest feature is aimed at a specific file directory and a specific failure. Running the scanner against a repository URL structurally inspects the .claude directory and looks for four shapes of compromise: hooks that fetch and execute, hooks that decode and execute, hooks that exfiltrate credentials, and reverse shells; permissions written so broadly that anything can run, such as a wildcard on Bash or the bypass flag on permissions; subagents granted wildcard tools; and skills that are really droppers.

The framing is precise because the attack is precise. An editor configuration is code that runs before you have read any of the repository, on a machine that already has your keys and your shell. That is why this belongs in a scanner at all, and it is why the file bothers to say the inspection happens before you clone.

The companion change in the same release history is quieter and just as relevant. An earlier version notes that user-home model context protocol configurations were made opt-in, which means the scanner used to read configuration outside your project by default and now asks. For a tool that reads chat histories, shell histories and home directory configuration, the default that stays inside the checkout is the one that matters, and it is worth checking which defaults your version has.

## Conclusion

Medusa is worth running on a repository that holds agent configuration, editor rules or MCP server definitions, because that is where a poisoned hook or an over-broad permission hides and where ordinary linters look straight past it. It is worth running locally and on a schedule rather than trusting as a gate. Three things to know first. Coverage has two stated holes: files above a byte cap are sampled rather than read in full, and until the newest release, payloads sitting in data files and prose were only caught when the scanner was confident about the surrounding context. The pattern count is the softest number in the project, since it quadrupled in one release, it is regex-shaped rather than a language analyser, and the tool's own diagnostics exist because a pattern once caused catastrophic backtracking. And the secrets feature reads your chat and shell histories and writes a backup of the file before redacting it, so the purge leaves the credentials on disk in a second copy. The license is AGPL, which matters if you ever wrap it in a service you operate.

## FAQ

### What does Medusa scan for in AI projects?

AI and machine learning applications, LLM agents, MCP servers, RAG pipelines and traditional code, with 40,000 or more detection patterns and 200 CVE detections including Log4Shell, Spring4Shell, the XZ Utils backdoor, LangChain and MCP remote code execution. It also detects weaponised editor configurations across more than 28 file types, plus native Rust and PHP rules that need no toolchain.

### How do I install the medusa-security scanner?

It is published on PyPI as medusa-security, and the package manifest requires Python 3.10 or later, declaring a console-only environment with classifiers through Python 3.13. The repository also carries a Dockerfile named for being simple and a formula directory for a package manager, while the visible quick-start commands are the subcommands, starting with medusa secrets scan.

### Does Medusa send my code or history anywhere?

For the secrets subcommands the file states local-only with no telemetry. Those commands read Claude Code, Cursor, Copilot, Zed and Gemini chat histories along with shell and REPL histories, and an earlier release changed user-home MCP configurations to opt-in rather than scanning them by default. The repository targeting command takes a repository URL and inspects it before you clone.

### What does the --trace-rules option in Medusa do?

It logs which rule fired and how long it took, writing a per-rule trace file and a slow rules file, and it runs a heartbeat that survives a hang. The release notes say it was added after a real catastrophic-backtracking denial of service was found and fixed, together with a lint that blocks bad patterns at author time.

## Sources

- [License: AGPL-3.0](https://github.com/Pantheon-Security/medusa/blob/main/LICENSE)
- [Pantheon-Security/medusa on GitHub](https://github.com/Pantheon-Security/medusa)
- [Project website](https://pantheonsecurity.io)
- [README](https://github.com/Pantheon-Security/medusa/blob/main/README.md)
- [Releases](https://github.com/Pantheon-Security/medusa/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/pantheon-security-medusa
