Skip to main content

agentlure

Detonate MCP servers against fake credentials before you install them.

agentlure runs an untrusted MCP server inside a sandbox planted with canary credentials and a sinkholed network, calls each of its tools once, and reports what the server actually tried to read or send out. The verdict is deterministic: no account, no LLM judge, no static pattern matching.

Quickstart

pip install agentlure
# or, with uv:
uvx agentlure scan --command "python3 path/to/server.py"

agentlure scan --config ~/.config/mcp.json --server my-server
agentlure scan --command "npx -y some-mcp-server"

Exit codes: 0 = CLEAN, 1 = SUSPICIOUS, 2 = MALICIOUS (see --fail-on below for CI gating).

Requires Linux, Python 3.9+, and a sandbox backend: Docker, Podman, or Linux namespaces (unshare + strace). agentlure refuses to run a target when no sandbox backend is available.

How a scan works

  1. Canaries are minted, fresh for every run: an AWS key pair, a GitHub token, an npm token, an SSH key pair, and a .env bundle (database URL, Stripe key, SendGrid key). Each value has a recognizable prefix and a random suffix, so a captured payload attributes to exactly one run.
  2. A synthetic HOME is planted with those canaries at the usual paths: ~/.aws/credentials, ~/.ssh/id_rsa, ~/.env, ~/.config/gh/hosts.yml, ~/.npmrc. The target's HOME points at the synthetic directory. Your real home is never the target's home.
  3. The target starts inside the sandbox with no real network egress. Its only reachable endpoint is a sinkhole proxy on loopback, injected through the standard HTTP_PROXY/HTTPS_PROXY environment variables. The proxy logs every request and searches the payload — URL, headers, body — for canary values in raw, base64, hex, and URL-encoded form, including encoded-inside-encoded payloads (for example a base64'd file riding in a query string).
  4. agentlure drives the server over MCP (stdio, JSON-RPC): initialize, tools/list, then one tools/call per tool with benign arguments synthesized from the tool's input schema (strings become "hello", integers 1, enums their first value, and so on).
  5. Behaviour is graded from strace and proxy evidence, and reports are written: a terminal summary, report.json, report.sarif (SARIF 2.1.0), and a standalone report.html. Reports contain masked canary values only; the full proxy capture is kept in network.jsonl next to the reports.

Evidence and verdicts

Evidence Meaning
canary_egress A canary value was found in a payload captured by the sinkhole.
canary_read The target opened a planted canary file.
unexpected_spawn The target executed a network/shell tool (curl, wget, nc, ncat, socat, bash, sh) outside its launch chain. A shell that is itself the launched command, or a wrapper shell exec'd while the server was still starting, does not count.
write_outside_workdir The target wrote, created, or deleted a file outside its sandbox workdir and outside the synthetic HOME.
  • MALICIOUS — any canary_egress.
  • SUSPICIOUS — any of the other three classes, without egress.
  • CLEAN — no evidence.

Reading a canary is not proof of theft — a server may legitimately look at its own configuration. Sending one out is. That is why only egress grades MALICIOUS.

For CI, --fail-on suspicious|malicious turns the exit code into a gate: the scan exits 0 when the verdict is below the chosen grade, and with the grade code (1 or 2) at or above it. Without --fail-on, the exit code is the grade code itself.

Sandbox backends

Backends are auto-detected in this order: Docker, Podman, namespace. --backend forces one.

  • Docker / Podman — run with a read-only root filesystem, --cap-drop ALL, no-new-privileges, memory/CPU/pids limits, and --network none; the sinkhole proxy runs inside the container on its loopback. The image (default agentlure-sandbox:latest, override with --sandbox-image or AGENTLURE_SANDBOX_IMAGE) must contain Python 3, strace, agentlure itself, and the runtime your target needs. These backends are implemented to the same interface as the namespace backend but are not covered by the project's own tests in v0.1 — the development environment has no container daemon. Prefer them for hostile targets once you have validated the image.
  • Namespace — user + mount + PID + network namespaces via unshare. The target's HOME is the synthetic home; the credential-bearing paths of the real home (~/.aws, ~/.ssh, ~/.config/gh, ~/.env) are additionally bind-masked with the canary versions when they exist, so absolute-path reads hit canaries too. The network namespace contains loopback only, with the sinkhole on it. The target is traced with strace -f. This backend is what agentlure selftest exercises.

Self-safety model

agentlure exists to run hostile code, so the scanner treats itself as part of the attack surface:

  • The target never runs outside a sandbox backend; there is no --no-sandbox flag and there will not be one.
  • Canary values are fake and minted per run. No real credential is ever planted, read, or passed into the sandbox. The canary manifest reaches the in-sandbox proxy through the environment and is scrubbed from the target's environment before launch.
  • The network namespace has no route out; the sinkhole terminates every connection. CONNECT tunnels are logged and closed, never forwarded.
  • Wall-clock timeouts, CPU rlimits, and process-group teardown bound every run.

Honest limits of the namespace backend: it redirects HOME, masks the known credential paths, kills the network, and watches syscalls, but it shares the host filesystem — a target that goes looking with absolute paths can see (and, with your user's permissions, modify) files outside the masked paths, and the PID namespace uses the host's /proc when mounting a fresh one is not permitted. For code you actively distrust, use a container backend or a throwaway VM.

Limitations (v0.1)

  • Linux only. Stdio MCP servers only — no remote/HTTP servers yet.
  • Each tool is called once, with schema-derived arguments. Servers that misbehave only on specific argument values, on a second call, or after a delay longer than the observation window will not be caught by this version.
  • A target that exfiltrates through a channel that ignores proxy environment variables gets no route out of the network namespace, so the attempt fails silently instead of producing evidence.
  • Verdicts are evidence, not proof of intent: a SUSPICIOUS grade means "look at this", and the HTML report shows exactly what was observed.

GitHub Action

- uses: 0xABCD01/agentlure@v0.1.0
  with:
    config: mcp.json
    server: my-server
    fail-on: malicious

Inputs: command or config (+ server), fail-on, version. Output: verdict. The full report is uploaded as a workflow artifact.

npm wrapper

npx agentlure ... works through a thin Node shim (in npm/): it delegates to uvx agentlure@0.1.0 when uv is present, else to an installed Python package (python3 -m agentlure), else it prints install instructions. The scanner itself is the Python package.

Selftest

The package ships six fixture servers (in agentlure/fixtures/) — three malicious (SSH-key reader, .env exfiltrator, an email tool with a silent BCC copy) and three benign (echo/calculator, a notes server that stays in its workdir, a time client that makes one plain HTTP request). From any install:

pip install agentlure
agentlure selftest        # expects MALICIOUS x3, CLEAN x3

From a source checkout, the unit tests run with python3 -m unittest discover.

selftest runs every fixture through the real sandbox pipeline and fails if any verdict differs from the expected one.


Created by Hafiar — bug hunter & pentester (@0xABCD01).

Metadata

Release files for agentlure 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for agentlure 0.1.1
File Size Uploaded Provenance Actions
agentlure-0.1.1.tar.gz 40.8 kB With provenance Details for agentlure-0.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for agentlure 0.1.1
File Interpreter ABI Platform Actions
agentlure-0.1.1-py3-none-any.whl Python 3 none any Details for agentlure-0.1.1-py3-none-any.whl

Total release size: 85.9 kB

Release files / agentlure-0.1.1.tar.gz

Download URL agentlure-0.1.1.tar.gz
Size 40.8 kB
Tags Source
SHA-256 checksum
How to use checksums
144b084e6f294d01a5594a2d016145dab55dd37063df0a8e642ed6087dd56ba2
BLAKE2b-256 checksum
How to use checksums
3a10042f331ca3ddbc74b809b401b046a6d563a6a7b5798049a489a79e7337cb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 6, 2026.

Transparency log

Release files / agentlure-0.1.1-py3-none-any.whl

Download URL agentlure-0.1.1-py3-none-any.whl
Size 45.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9572ebde5c68402d0cddf101888b5a4a19e621a2c6cecb7f50bb969403fa32d1
BLAKE2b-256 checksum
How to use checksums
d86e03a39fb926f4e64cbae44264559675b803603f94732df7b3cc1dd34c5c70
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 6, 2026.

Transparency log

Security for agentlure 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for agentlure-0.1.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 6, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page