Security analysis for MCP servers + agent skills
Find the gap between what it says and what itdoes.
Divergence compares claims, schemas, source code, installed-set context, and—on supported Linux hosts—sandboxed runtime behaviour. Capabilities stay posture. Contradictions become risk.
v1.1.0 is a release candidate. The package, signed tag, and GitHub release are not published yet.
Candidate evidence
Precision you can reproduce.
Release-candidate evidence on a project-authored synthetic corpus. Dynamic results were measured on verified unprivileged Linux arm64; independent review and x86-64 reproduction remain open.
The thesis
A capability is not a verdict.
A shell server spawning processes may be doing exactly what it promised. The risk begins when it reaches for something it did not declare—an outbound connection, a credential path, a hidden parameter, or a write behind a read-only claim.
Conventional pattern matchers react to dangerous-looking words. Divergence asks a different question: do the artifact’s independent representations agree?
Posture
What it can do.
Informative and non-urgent. A broad capability is not evidence of deception.
Risk
Where its stories disagree.
Every finding carries both halves of the contradiction and exact evidence.
How it works
Four representations. One measurable gap.
Each surface is analyzed independently. Set algebra finds the mismatch, then emits risk only when the contradiction has concrete evidence.
01 · Claims
What it says
Names and natural-language descriptions become a fixed capability set—not a verdict.
02 · Schema
What it permits
Parameters, MCP annotations, and skill tool grants expose the declared interface.
03 · Source
What it reaches
Reachable filesystem, network, process, environment, secret, and eval capabilities.
04 · Runtime
What it actually touches
Optional behaviour observed only inside the verified fail-closed Linux sandbox.
Capabilities
Static first. Dynamic when it earns its place.
The deterministic core ships independently. Optional tiers add evidence without weakening the offline default or silently turning partial analysis into a clean result.
Offline and non-executing
Local targets are parsed without running them. Remote acquisition, dynamic execution, external baselines, and A9 all require explicit opt-ins.
Python, TypeScript, and shell
Tree-sitter reachability follows handlers and skill entrypoints into filesystem, network, subprocess, environment, secret, and dynamic-evaluation sinks.
Fleet analysis
Detect shadowing, preference manipulation, trigger hijacking, and toxic flows that cannot exist inside a single artifact.
Approval ledger
Approve a fingerprint, then classify later mutations as cosmetic, capability-expanding, or semantics-inverting.
JSON, SARIF, and GitHub Action
Emit deterministic machine-readable results and SARIF 2.1.0, with controls to fail CI on risk or incomplete analysis.
Sandbox and adjudication
Observe runtime behaviour inside the Linux boundary. Separately, an evidence-only command backend can adjudicate a capped contested subset when explicitly requested.
The benchmark
Lead with the false-positive traps.
The candidate corpus contains 110 synthetic artifacts: 50 risk-positive and 60 benign or control samples. Every result carries its denominator and provenance.
| Scanner | Trap false positives | Precision | Recall |
|---|---|---|---|
| Divergence static | 0/35 | 100% | 27/50 |
| Divergence + dynamic | 0/35 | 100% | 49/50 |
| Semgrep 1.173.0 | 5/35 | 81.1% | 30/50 |
| Keyword baseline | 20/35 | 52.9% | 27/50 |
Run it yourself
From clone to first scan.
Python 3.12 and uv are required. Static analysis is local, offline, and non-executing by default.
Run from source today
git clone https://github.com/vignesh-chaturvedi/divergence.git
cd divergence
uv sync --frozen --extra dev
uv run divergence scan <path>Fail CI on risk and write SARIF
uv run divergence --fail-on-risk scan <path> \
--sarif divergence.sarifOne-shot installation
uvx --from divergence-mcp==1.1.0 divergence --helpThis command becomes available only after the v1.1.0 PyPI publication.
Before you run it
Questions worth answering plainly.
Security tooling earns trust by explaining its boundary, not hiding it in a footnote.
Does Divergence execute the artifact?
No by default. Static scans parse local files without executing them. Runtime observation happens only when you explicitly pass --dynamic and the verified Linux sandbox is available.
Does it upload my MCP configuration?
The deterministic static path and sandbox execution stay local. Raw source, artifact files, MCP configs, and credentials are never sent through the built-in A9 contract; it receives normalized evidence only. Remote acquisition, external scanners, and adjudication remain separate explicit opt-ins.
Which platforms are supported?
Static analysis is cross-platform. The fail-closed sandbox uses Linux kernel facilities; macOS and Windows remain visibly static-only.
Is Divergence a runtime firewall?
No. It analyzes artifacts before and between runs and emits findings for existing tools to enforce. Inline request interception is intentionally out of scope.
Can a clean dynamic result prove safety?
No. Dynamic evidence only covers paths that actually execute. Divergence reports observed coverage and keeps incomplete analysis visible rather than treating it as clean.
Is v1.1.0 published?
Not yet. Local release engineering is complete, but independent review, Linux x86-64 reproduction, a non-author real-world run, and protected publication remain.