Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Meridian Range: a compass reticle ring, its graticule drawn in fine dashed arcs, enclosing a snow-capped mountain range, with a shield carrying an M standing at the centre. The wordmark MERIDIAN RANGE sits below.

Meridian Range

A defensive range for MCP and AI-agent attacks.

Reproduce a published insecure default (ATTACK-OK) and ship a detection. The detection is the deliverable, not the exploit.


OWASP run modules detections license

Design · Attack catalog · Quick start · Adding an attack


Every module opens with its own recording, driven from a real browser against the actual affected SDK release, and ending in command output the attacker received.

Attack 01, CORS session hijack
CVE-2026-34237. An MCP server on the developer's own machine is assumed private because "only localhost can reach it." That assumption rests entirely on the browser. The affected transport answers every request with Access-Control-Allow-Origin: * and discloses the session id on the SSE endpoint event, so a page opened once can read that session, replay it, and drive run_command. The clip ends with the canary output at the attacker's collector, under the same session id.
Attack 02, DNS rebinding
CVE-2025-66414. The attack that survives the fix for 01. Checking Origin stops a cross-origin page; it does not stop the attacker's own page from becoming same-origin with the target. One DNS answer flips and the same tab, at the same URL, with no second click, is talking to the MCP server on the developer's machine. The clip ends with the command output printed in the page itself.

Reading a CVE tells you a flaw exists. It does not tell you what it looks like in your telemetry at 03:00, which is the only form of that knowledge a defender can act on. So each module takes one published CVE, reproduces it end to end until the attack actually lands, and then answers the question that matters: what signal did that leave, and what rule fires on it? A module is finished when both halves exist and the isolated VM has run them green.

Design

A module is a directory. Everything one attack owns lives in modules/<NN-slug>/: its manifest, its scenario, its compose file, its detection, its evidence, its writeup. There is no central catalog to edit and no registry to update, because range discovers modules by globbing modules/*/module.yml. Adding an attack means adding one directory and changing nothing else.

A shared engine does the rest: engine/harness/ holds the scenario SDK and the transport clients, engine/cli/ implements the ./range command, and engine/compose.yml is the sealed base every module is merged on top of.

Meridian Range design view in three bands. Band 1, author: a module is one directory holding module.yml, scenario.ts, compose.yml, lab.env, detection, evidence and README. Band 2, the shared engine: the range CLI, the harness with its scenario SDK and transport clients, the sealed compose base with internal true and no published ports, and the vulnerable servers pinned per SDK release. Band 3, running the loop: a reproduce lane of range up, run, ATTACK-OK, verify and matrix, feeding a detect lane of telemetry, ATR rule, detect-test and export, ending at module done. A final band lists what is present today: module 01 CORS session hijack and module 02 DNS rebinding, both VM-verified, plus the catalogued backlog.

Defensive by construction Every module ships the full loop: reproduce, then detect. An exploit without a detection is not a module here.
Anchored to real CVEs Each attack maps to published CVEs (CVSS per anchor) and to the OWASP LLM Top 10 plus the emerging MCP Top 10.
Manifest-driven Each module.yml is the source of truth for its own attack. The catalog table and the OWASP map are generated from them, never hand-edited.
Detections you can take with you Machine-readable ATR rules carry their own test_cases, run offline as unit tests, and export to Sigma or Elastic with ./range export.
Contained by default An isolated VM, a no-egress Docker network, one module deployed at a time, benign canaries only.

Attack catalog

Built from the module manifests. CVSS shown per anchoring CVE. See the OWASP map for the full LLM / MCP / ASI / CWE breakdown, and docs/BACKLOG.md for what is queued next.

# Attack OWASP Anchor CVE (CVSS) Repro Detect Blog
01 CORS Session Hijack LLM06 CVE-2026-34237 (6.1) soon
02 DNS Rebinding LLM06 CVE-2025-66414 (7.6) soon

Legend: ✅ shipped and VM-verified · 🧪 authored, pending VM verification (./range verify).

Quick start

Everything below runs on the lab VM and nowhere else. Mark the VM once with sudo touch /etc/meridian-vm, or prefix a single command with MERIDIAN_ON_VM=1.

./range list                 # what modules exist
./range up 01                # sealed tier: internal network, no published ports
./range run 01               # reproduce -> [ATTACK-OK]
./range verify 01            # the gate; writes modules/01-*/evidence/vuln.txt
./range matrix 01            # the same attack against every SDK version it declares
./range down                 # tear down everything on this host

On the authoring host, nothing starts and everything is offline:

./range check                # manifests, module structure, detections, the no-ports gate
./range detect-test          # detection rules against their own test cases
./range export --format sigma --out /tmp/pack
./range plan 01 --tier split-host --side victim   # print the deploy command, run nothing
./range sync --build 01      # push to the VM and rebuild that module's server there

Full walkthrough: docs/getting-started.md. Every command carries a [dev] or [VM] marking in ./range --help: [VM] refuses to run anywhere else.

Adding an attack

./range new 03 tool-poisoning --name "Tool Description Poisoning"

That scaffolds the whole module directory from the template, and ./range check then enforces that shape on every commit. The ordered checklist and the contribution mechanics are in docs/CONTRIBUTING.md.

The two modules that exist are worth reading end to end: module 01, CORS session hijack is the full study, from the transport defect to the detection and the one-line fix. Module 02, DNS rebinding is a separate attack that defeats the Origin control which stops module 01.

About

A defensive range for MCP and AI-agent attacks: reproduce a published insecure default, then ship the detection.

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages