Skip to main content
Glama
AgentLatch

AgentLatch

Official
by AgentLatch

AgentLatch — Local-First AI Agent Security Scanner and MCP Traffic Monitor

CI GitHub Marketplace License: MIT Demo video

Find selected security risks in AI-agent projects before you run them, and see what your agent does with its MCP tools while it runs. AgentLatch is an open-source, local-first AI agent security toolkit with two parts:

  • Static scanner (agent-latch scan): checks Python agent code, agent manifests (tools, permissions, authentication) and prompt templates, optionally audits pinned Python dependencies, and reports evidence in your terminal, JSON or SARIF. Run it from the command line, as a pre-commit hook or as a GitHub Action.

  • Runtime proxy for MCP, preview (agent-latch-runtime): sits between an AI agent and a Model Context Protocol (MCP) server and records every tool list, tool call, result and prompt, with secrets masked. Monitor only: it never blocks or changes traffic.

Example AgentLatch scan showing detected security findings

Project status: early proof of concept. AgentLatch is not a complete vulnerability scanner, runtime protection system, security score, or certification. A clean scan means only that the enabled checks did not report a finding. The runtime proxy records traffic and runs one preview gate, ALR04, on MCP tool definitions. It reports findings and does not block calls.

What AgentLatch does so far

AgentLatch checks an AI agent at three points, and you can use each on its own:

  1. Static scan: reads an agent project's code, prompts and manifests before anything runs, and reports risky patterns with the file and line.

  2. Runtime monitor (preview): sits between an agent and its MCP server, records the tool traffic with secrets masked, and flags tool definitions that contain instruction-like content.

  3. Tamper-evident ledger (preview): seals that record in a hash chain, so an edited, deleted or rebuilt log shows up when you verify it.

Everything runs on your machine and nothing is uploaded. The only network use is the opt-in --dependencies audit. AgentLatch reports findings and never blocks a tool call, and a clean result is not a security guarantee.

What stays on your machine: project files flow through the AgentLatch scanner to reports and CI, all locally. An optional dependency audit, off by default, sends only package names and versions to an advisory service.

Every section below follows the same four steps: what it does, Run it (copy-paste), See the result (the command that shows the output), and Go deeper (links).

I want to…

Go to

Scan an agent project on my laptop

1. Static scan

Fail a pull request on risky changes

2. Static scan in CI

See what my agent asks its MCP tools to do

3. Runtime monitor

Prove the runtime log was not edited

4. Tamper-evident ledger

Hook up Claude, ChatGPT or Cursor

5. Connect your app

Related MCP server: SentinelGate

Contents

Install once

Requires Python 3.11+. pipx keeps AgentLatch in its own environment (Windows and other options: Getting started).

pipx install agentlatch-security

Sections 3 to 5 use the runtime proxy, which needs the runtime extra (it adds FastMCP). Install this instead if you want everything:

pipx install "agentlatch-security[runtime]"

Or use a virtual environment:

python3 -m venv .venv && source .venv/bin/activate
python -m pip install "agentlatch-security[runtime]"

Check it:

agent-latch -V

On PyPI, AgentLatch is published as agentlatch-security. It installs the agent-latch and agent-latch-runtime commands. The PyPI package named agentlatch is a separate project.

1. Static scan (local)

What it does: reads the files of an agent project (Python code, prompts, YAML, manifests) and reports risky patterns. It never imports or runs the code it checks. No configuration or manifest is needed: every folder and text file is scanned.

The scan, end to end: source files are parsed and never run, checked by static rules and taint analysis, mapped to OWASP Agentic categories ASI01 to ASI10, and reported as text, JSON or SARIF.

Run it:

agent-latch scan /path/to/my-agent

Try it on the deliberately insecure example in this repository:

git clone https://github.com/AgentLatch/agent-latch.git
agent-latch scan agent-latch/examples/vulnerable-agent

Common options:

agent-latch scan --config agent-manifest.yaml        # also audit a manifest's declared tools (optional)
agent-latch scan . --project-ignores                 # your own repo: apply its .agent-latch-ignore
agent-latch scan . --min-severity medium             # hide low and info findings (still counted)
agent-latch scan . --dependencies                    # add known-vulnerability checks (sends package names to PyPI)
agent-latch scan . --fail-on high                    # exit 1 on high-severity findings, for CI
agent-latch scan . --exclude tests/                  # skip a path for one run
agent-latch scan . --format sarif --output results.sarif
agent-latch --interactive                            # guided mode

Suppressions written inside the scanned project (.agent-latch-ignore, inline ignore comments) are not applied unless you add --project-ignores, so a project you scan cannot hide its own findings.

See the result: the terminal shows each finding with its rule, file and line, and OWASP mapping. This is real output for the example above (shortened):

Findings: 12

[HIGH] MAN001 (ALR09) High-risk tool without human approval
  agent-manifest.yaml:29:1
  Tool 'run_shell' can perform high-impact actions with no approval gate declared. ...
  Gate: ALR09 Human approval for sensitive actions
  OWASP Agentic: ASI02 Tool Misuse and Exploitation; ASI05 Unexpected Code Execution (RCE); ...
agent-latch scan . --plain                     # plain text, for logs and pipes
agent-latch scan . --format json               # machine-readable
agent-latch scan . --format sarif --output results.sarif   # for code scanning and SARIF viewers
echo $?                                        # 0 passed, 1 findings at or above --fail-on, 2 error

What the rules look for: how one piece of untrusted text can travel from a web page to a shell command. Each red marker is a shipped rule (AG003, AG004, PY002), and breaking any one link stops the chain.

How one bad input becomes an action: untrusted web content reaches an LLM agent, then a tool call with no approval gate, then a shell call. AgentLatch flags AG003, AG004 and PY002.

AgentLatch demo video: scanning a vulnerable AI agent

Go deeper: Getting started (ignores, output formats, exit codes) · Rule reference · Agent manifest

2. Static scan in CI (GitHub Actions and pre-commit)

What it does: runs the same scan on every pull request, or before every commit, and fails the check when a finding meets your threshold.

Run it, GitHub Actions: save this as .github/workflows/agent-latch.yml (Marketplace listing):

name: agent-latch
on: [push, pull_request]

permissions:
  contents: read
  security-events: write  # needed to upload results to code scanning

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: AgentLatch/agent-latch@v0.5.0
        with:
          fail-on: high
          # min-severity: medium      # optional: hide low and info findings
          # project-ignores: "true"   # apply your repo's .agent-latch-ignore (a pull request can edit it)

Run it, pre-commit: add this to .pre-commit-config.yaml, then run pre-commit install:

repos:
  - repo: https://github.com/AgentLatch/agent-latch
    rev: v0.5.0
    hooks:
      - id: agent-latch

See the result:

  • Actions: open the run's log and its job summary (a findings table), or the repository's Security → Code scanning tab and the pull request's checks. The job exposes the outputs sarif-file, finding-count and exit-code.

  • pre-commit: the commit is blocked on a high or critical finding. Check the whole repo at any time with:

pre-commit run agent-latch --all-files

Upgrading from v0.1.0: the project's own .agent-latch-ignore, pyproject.toml excludes, and inline ignore comments are no longer applied by default. If your repository relies on them, add project-ignores: "true" to the Action or --project-ignores on the command line. See the v0.2.0 release notes.

Go deeper: pre-commit and CI (all inputs and outputs, other CI systems, choosing a threshold)

3. Runtime monitor for MCP (preview)

What it does: agent-latch-runtime sits between an AI agent and an MCP server and records what the agent asks its tools to do and what comes back. It is a preview and monitor only: it never blocks a call. It runs ALR04, which reports a finding when a tool definition contains instruction-like content. Secrets are masked in every file.

Runtime monitor: the agent talks to the MCP server through the agent-latch-runtime proxy, which passes every message through unchanged and writes masked logs. import-logs joins them into events and findings, and agent-latch --runtime-result prints the report.

Run it: try it with a bundled synthetic server, no setup:

agent-latch-runtime demo

demo starts the synthetic server behind the real proxy, makes a few tool calls (one returns a fake credential, one fails), then imports the logs. This is real output:

Output of agent-latch-runtime demo: ten MCP events, from tools/list to prompts/get, each joined with its payload

Watch a real agent. Put the proxy in front of any MCP server, then follow its logs from a second terminal:

# Terminal 1: the agent's MCP traffic goes through the proxy.
agent-latch-runtime proxy --trace runtime-logs/trace.jsonl --payloads runtime-logs/payloads.jsonl \
  -- npx -y @modelcontextprotocol/server-github
# Terminal 2: one line per message, plus events.csv and gate-results.csv in runtime-logs/.
agent-latch-runtime import-logs

Run both from the same folder, in the environment where AgentLatch is installed. mcp-server/.venv does not provide agent-latch-runtime. To also keep a queryable local copy, add --database runtime-logs/runtime.db to import-logs (SQLite, nothing is uploaded).

See the result:

agent-latch . --runtime-result runtime-logs/gate-results.csv

This prints the gate findings in the same table as a scan, with the local tool's file and line when the project defines it (add --plain for text). Real output, shortened:

Runtime findings · 3

HIGH     ALR04-003  mcp-server/tools/alr04_fixture_tools.py:14
  concealment
  Tool definition contains above-threshold injection indicators; no exploit confirmed.
  Evidence: instruction_to_conceal_from_user @ $/description
  OWASP: ASI01 Agent Goal Hijack; ASI02 Tool Misuse and Exploitation; ...

The report lists findings only. Nothing was blocked. Add --fail-on high to exit 1 on a high finding, and --min-severity to hide lower ones.

Go deeper: Runtime proxy guide (limits, SQLite store, HTTP mode) · Live run with a CrewAI agent, plus 20 test scenarios

What the proxy records

MCP message

Trace (always)

Full payload (--payloads)

tools/list: tool names, descriptions, schemas

✅

✅

tools/call: request, response and error

✅

✅ (a failed call is logged with its error type)

prompts/get: request and response

✅

✅

prompts/list

✅

names only

The trace keeps argument names, sizes, SHA-256 hashes and a short secret-masked excerpt, never raw values. The opt-in payloads file keeps full argument values and tool output, secret-masked and cut to --payload-max-chars. import-logs joins the two into one event per message.

Not recorded yet: resources/list and resources/read, initialize, sampling/createMessage, notifications (including tools/list_changed), image, audio and embedded-resource content in tool results, and a failed prompts/get. These pass through the proxy unchanged with no record. The proxy also never sees the user's chat with the model, an app's built-in tools, or servers not routed through it. Details: docs/runtime.md.

4. Tamper-evident ledger (preview)

What it does: a log the agent can rewrite is not evidence. --ledger FILE seals every trace record into a local hash chain, and one short digest per batch (an anchor) is published somewhere the agent cannot write. An edit, a deletion or a full rebuild then shows up when you verify. It is off unless you ask for it, uses only the standard library, makes no network call, and is never in the request path.

Tamper-evident ledger: each trace line is sealed into a numbered block that holds its hash and the previous block's digest, the newest digest is published as an anchor the agent cannot write, and verify returns intact, unanchored, tampered, deleted, rewritten or missing.

Run it:

# 1. Record with a ledger (the ledger needs a trace file beside it)
agent-latch-runtime proxy --trace runtime-logs/trace.jsonl \
  --ledger runtime-logs/trace.ledger.jsonl -- npx -y @modelcontextprotocol/server-github
# 2. Publish an anchor to a place the agent cannot write (a mounted drive, another host, ...)
agent-latch-runtime anchor --ledger runtime-logs/trace.ledger.jsonl --to /mnt/audit/anchors.jsonl
# 3. Verify, any time
agent-latch-runtime verify runtime-logs/trace.ledger.jsonl                       # finds trace.jsonl beside it
agent-latch-runtime verify runtime-logs/trace.ledger.jsonl --anchor /mnt/audit/anchors.jsonl
agent-latch-runtime verify runtime-logs                                          # every ledger in a folder
agent-latch-runtime verify runtime-logs --all                                    # ... and its subfolders, archives included

See the result: verify prints one verdict (intact, unanchored, tampered, deleted, rewritten or missing) and exits 1 when the trail cannot be trusted. For the full picture, put the ledger in the runtime report:

agent-latch . --runtime-result runtime-logs/gate-results.csv \
  --ledger runtime-logs/trace.ledger.jsonl --anchor /mnt/audit/anchors.jsonl

The verdict leads the report, followed by a table with one row per record. Problem records are always listed, and --ledger-rows N sets how many intact ones to show (0 for all). Real output for a ledger with one edited record, one gap and one out-of-order block (shortened):

AUDIT TRAIL TAMPERED — a record was altered; the log cannot be trusted.
  #5: the block's digest does not match its content
  #11: 2 records are missing here
  #13: this block does not follow the block before it

#   TIME                      METHOD      STAGE    DIGEST        STATE
5   2026-10-31T15:52:51.881Z  tools/list  request  b1c5e3ae7973  EDITED
11  -                         -           -        -             DELETED
13  2026-10-31T15:52:51.882Z  tools/call  request  65cbcbd329ef  REORDERED
30  2026-10-31T15:52:51.883Z  tools/call  request  97adbec2a3bd  ok

Export it as SARIF for a viewer or code scanning. The file gets the SARIF and the terminal still shows the report above:

agent-latch . --runtime-result runtime-logs/gate-results.csv \
  --ledger runtime-logs/trace.ledger.jsonl --anchor /mnt/audit/anchors.jsonl \
  --format sarif --output audit.sarif

A failed trail exits 1 even with --fail-on none, because log integrity is not a severity threshold.

What to expect: without an anchor the best verdict is unanchored: the chain is consistent, but nothing outside the machine proves the file was not rebuilt. The ledger makes tampering visible; it does not prevent it, and it cannot show a change made before a record was sealed. Check live sessions with verify runtime-logs (the folder, without --all) and use --all to audit archived sessions on purpose. What an agent with write access can still do, and how to narrow it: the ledger operations guide.

Go deeper: Audit ledger overview · Setup · Reference · Operations and incident runbook

5. Connect Claude, ChatGPT or Cursor

What it does: your app starts the proxy instead of the MCP server, and the proxy starts the real server. Nothing else about the app changes.

Run it: in the app's MCP settings, replace the server's command with the proxy and move the old command after --. Use full paths: desktop apps often start servers with a different PATH and working directory.

{
  "mcpServers": {
    "github": {
      "command": "/full/path/to/.venv/bin/agent-latch-runtime",
      "args": [
        "proxy", "--name", "github", "--trace", "/full/path/to/runtime-logs/trace.jsonl", "--",
        "npx", "-y", "@modelcontextprotocol/server-github"
      ]
    }
  }
}

Restart the app afterwards. Add "--ledger", "/full/path/to/runtime-logs/trace.ledger.jsonl" before the -- to also seal the log (section 4).

App

Settings file

Claude Code

.mcp.json in the project

Claude Desktop

Settings → Developer → Edit Config

Cursor

~/.cursor/mcp.json

GitHub Copilot in VS Code

.vscode/mcp.json (top-level key is servers, not mcpServers)

ChatGPT (web)

cannot start a local program: it reaches the proxy through OpenAI's Secure MCP Tunnel, see the ChatGPT guide

See the result: use the app as usual, then follow the traffic with agent-latch-runtime import-logs and read it with the commands from sections 3 and 4.

Go deeper: Connect an app (exact paths per OS, remote servers over HTTP, the supported-clients table) · ChatGPT through the tunnel · Claude Desktop on Windows with the MCP server in WSL

How it works

AgentLatch looks at an agent at two different times. The scanner reads the project's files before anything runs. The runtime proxy watches the agent's MCP tool traffic while it runs. Both stay on your machine.

flowchart LR
    subgraph before["Before you run: static scanner"]
        code["Python agent code<br/>prompts, YAML, manifests"] --> scan["agent-latch scan"]
        scan --> report["Findings<br/>terminal · JSON · SARIF<br/>mapped to OWASP ASI01–ASI10"]
    end
    subgraph during["While it runs: runtime proxy (preview)"]
        agent["AI agent<br/>CrewAI · Claude Desktop · Cursor · ..."] --> proxy["agent-latch-runtime proxy"]
        proxy --> server["MCP server"]
        proxy --> logs["Masked logs<br/>trace.jsonl · payloads.jsonl"]
        logs --> importer["agent-latch-runtime import-logs"]
        importer --> events["One event per message<br/>events.csv · normalized.jsonl<br/>optional --database (local SQLite)"]
    end

The scanner never imports or runs the code it checks. The proxy passes every MCP message through unchanged and never blocks anything.

For one tool call, the runtime path looks like this:

sequenceDiagram
    participant A as AI agent
    participant P as agent-latch-runtime proxy
    participant S as MCP server
    participant I as import-logs
    A->>P: tools/call (arguments)
    P->>S: forwarded unchanged
    S-->>P: result
    P-->>A: returned unchanged
    P->>P: write masked trace + payload records
    I->>P: tail the log files (read-only)
    I->>I: join request, payload and response into one event

What the scanner checks today

Rule

Gate

Detection

OWASP Agentic mapping

PY001

ALR06

Direct Python eval() and exec() calls

ASI05 Unexpected Code Execution (RCE); ASI02 Tool Misuse and Exploitation

PY002

ALR06

subprocess.*(..., shell=True) calls

ASI05 Unexpected Code Execution (RCE); ASI02 Tool Misuse and Exploitation

PY003

ALR12

Calls with a literal verify=False argument

ASI02 Tool Misuse and Exploitation

AG001

ALR07

CrewAI Agent(..., allow_delegation=True) review hint

ASI02 Tool Misuse and Exploitation; ASI03 Identity and Privilege Abuse

AG002

ALR06

LangChain create_pandas_dataframe_agent(...) code-execution capability

ASI05 Unexpected Code Execution (RCE); ASI02 Tool Misuse and Exploitation

AG003

ALR05

Web-search, web-loader, or HTTP output flowing unfenced into an LLM message (indirect prompt injection)

ASI01 Agent Goal Hijack

AG004

ALR09

Function exposed to the model as a tool that runs commands, writes files, sends email, or writes data, with no human-approval gate

ASI02 Tool Misuse and Exploitation; ASI05 / ASI03; ASI09

AG005

ALR07

Agent given an unrestricted built-in tool (shell, Python REPL, unscoped file access)

ASI02 Tool Misuse and Exploitation; ASI05 / ASI03

AG006

ALR09

Human approval turned off for agent actions (human_input_mode="NEVER" with code execution, auto_approve=True, permission_mode="bypassPermissions")

ASI09 Human-Agent Trust Exploitation; ASI05 / ASI02

AG007

ALR08

Agent loop with no effective limit (max_iterations=None, very high limits, while True around an agent call)

ASI08 Cascading Failures

SEC001

ALR10

Credential-like quoted assignments; matched value is redacted

ASI03 Identity and Privilege Abuse; ASI04 Agentic Supply Chain Vulnerabilities

DEP001

ALR11

Known advisory for a package in an audited requirements file

ASI04 Agentic Supply Chain Vulnerabilities

MAN001

ALR09

Manifest tool with a high-risk capability and no human-approval gate

ASI02 Tool Misuse and Exploitation; ASI05 / ASI03; ASI09

MAN002

ALR07

Manifest tool with wildcard permissions

ASI02 Tool Misuse and Exploitation; ASI03 Identity and Privilege Abuse

MAN003

ALR03

Manifest tool calling a remote endpoint without authentication

ASI03 Identity and Privilege Abuse; ASI02 Tool Misuse and Exploitation

PRM001

ALR01

Prompt-injection signatures in prompts in code, YAML, prompt template files, and manifests

ASI01 Agent Goal Hijack

PRM002

ALR01

User-input placeholder interpolated into a system prompt

ASI01 Agent Goal Hijack

ALR01-S01

ALR01

Invisible, bidi, or zero-width characters in a prompt

ASI01 Agent Goal Hijack

ALR03-S01

ALR03

Agent or MCP server bound to every interface (host="0.0.0.0")

ASI03 Identity and Privilege Abuse; ASI07

ALR06-S01

ALR06

Unsafe deserialization (yaml.load without a safe loader, pickle, torch.load without weights_only)

ASI05 Unexpected Code Execution (RCE)

ALR06-S02

ALR06

Model-written code runs without a sandbox (use_docker=False, code_execution_mode="unsafe", local executor)

ASI05 Unexpected Code Execution (RCE); ASI02

ALR08-S01

ALR08

Outbound HTTP call without a timeout

ASI08 Cascading Failures

ALR08-S02

ALR08

Unbounded retry (@retry without stop, Retry(total=None), max_retries=None)

ASI08 Cascading Failures

ALR11-S01

ALR11

Model or dataset loaded with trust_remote_code=True

ASI04 Agentic Supply Chain Vulnerabilities

ALR12-S01

ALR12

Agent, tool, or model endpoint on plaintext http:// or ws://

ASI02 Tool Misuse and Exploitation; ASI07

ALR13-S01

ALR13

Web or tool output written to agent memory or a vector store without validation

ASI06 Memory & Context Poisoning

ALR13-S02

ALR13

Memory or vector store created once at module level, shared by every session

ASI06 Memory & Context Poisoning

ALR14-S01

ALR14

Agent writes to its own prompts, instructions, or settings

ASI10 Rogue Agents

ALR14-S02

ALR14

Agent installs persistence (cron, systemd, launchd, shell profile, SSH keys)

ASI10 Rogue Agents

ALR14-S03

ALR14

Agent installs packages at runtime

ASI10 Rogue Agents

Rule behavior and known blind spots are documented in docs/RULES.md.

Every rule belongs to one gate: the security outcome it checks, such as ALR09 Human approval for sensitive actions. Reports show a rule with its gate, for example AG006 (ALR09). SARIF and JSON keep the full rule ID (AGENTLATCH-AG006), and suppressions accept either form. docs/GATES.md lists every gate, its detectors (static rules and runtime checks such as ALR04), and how it maps to OWASP and the EU AI Act. These mappings are informational, not a compliance claim.

OWASP Agentic Top 10 coverage

How the scanner's rules map to the OWASP Top 10 for Agentic Applications 2026. This table is the static scanner. The runtime gate ALR04 also cites ASI01, ASI02, and ASI04 on a finding. That does not add a scanner check.

ID

Category

Coverage

Rules

ASI01

Agent Goal Hijack

✅ checks

AG003, PRM001, PRM002, ALR01-S01

ASI02

Tool Misuse and Exploitation

✅ checks

PY001–PY003, AG001, AG002, AG004–AG006, MAN001–MAN003, ALR06-S02, ALR12-S01

ASI03

Identity and Privilege Abuse

✅ checks

AG001, AG004, AG005, SEC001, MAN001–MAN003, ALR03-S01

ASI04

Agentic Supply Chain Vulnerabilities

✅ checks

SEC001, DEP001, ALR11-S01

ASI05

Unexpected Code Execution (RCE)

✅ checks

PY001, PY002, AG002, AG004–AG006, MAN001, ALR06-S01, ALR06-S02

ASI06

Memory & Context Poisoning

🟨 partial

ALR13-S01, ALR13-S02

ASI07

Insecure Inter-Agent Communication

🟨 partial

ALR03-S01, ALR12-S01

ASI08

Cascading Failures

🟨 partial

AG007, ALR08-S01, ALR08-S02

ASI09

Human-Agent Trust Exploitation

🟨 partial

AG004, AG006, MAN001

ASI10

Rogue Agents

🟨 partial

ALR14-S01, ALR14-S02, ALR14-S03

Every scan report ends with the same ASI01–ASI10 summary and marks the uncovered categories as no checks yet, so they aren't mistaken for clean results. A ✅ means some checks exist, not that the category is fully covered. The mapping is informational, not an OWASP endorsement or certification.

Documentation

Guide

Covers

Getting started

Install on Linux, macOS, WSL, and Windows; scanning; options; ignoring false positives with .agent-latch-ignore; output formats; exit codes; dependency audit; troubleshooting

Agent manifests

Declaring agents, tools, permissions, and prompts in agent-manifest.yaml, and what is checked

pre-commit and CI

pre-commit hook, GitHub Action inputs and outputs, other CI systems, choosing a threshold

Detection rules

What every rule detects, its OWASP mapping, and its known blind spots

Gates

The security outcomes AgentLatch checks, which rules and runtime checks belong to each, and their OWASP and EU AI Act references

Audit ledger

Making the runtime log tamper-evident: the hash chain, anchors, the six verdicts, and what it cannot catch. Then setup, reference and operations

Vulnerable example

A demo project and the findings it should produce

Runtime proxy for MCP (preview)

Install, connecting an app, what is recorded, import-logs and demo, limits. Optional local SQLite: Store events in SQLite

MCP gateway

A local MCP gateway for running agents against real tools, with step-by-step setup for Claude Code, Claude Desktop, Cursor, Codex CLI, and HTTP clients, and live runs through the runtime proxy

Why AgentLatch?

AI agents combine model-generated decisions with tools, credentials, code execution, and external data. Traditional code and dependency checks are useful, but they do not by themselves explain agent-specific risks. AgentLatch is a small starting point: run selected checks locally, inspect the exact file and evidence, see what an agent actually did with its tools, and map relevant findings to OWASP Agentic Top 10 categories.

The goal is to grow in layers:

  1. Now: local scanner. Focused checks of Python source, agent manifests, and prompt templates; optional Python dependency advisories; portable reports; and pre-commit and GitHub Action integrations.

  2. Now, preview: runtime recording for MCP. A proxy records live MCP tool traffic with secrets masked, and an importer turns it into reviewable events. --database FILE optionally keeps those events in a local SQLite file. It never blocks, and it does not upload them.

  3. Now, preview: one runtime gate. ALR04 reports a finding when a MCP tool definition (name, description, or schema) contains instruction-like content, and maps that finding to ASI01, ASI02, and ASI04. Calls are not blocked. The report lists findings only.

  4. Planned: enforcement and adapters. Blocking only when the operator turns it on in their own policy; framework adapters and broader evaluation checks after that.

These layers will remain clearly distinguished: detecting a risky pattern is not the same as testing agent behavior, and neither alone guarantees runtime enforcement.

Reports and data handling

  • Scans run locally. They do not call an LLM or upload your source code.

  • The one exception is the opt-in dependency audit (--dependencies), which sends package names and versions to an advisory service. See Dependency audit.

  • Detected secret values are redacted from evidence, but reports still include paths, line numbers, and code context. Review them before sharing.

  • Every folder and every text file under the target is scanned, and no manifest is required. Only .git, installed environments (a folder with pyvenv.cfg, or an installed node_modules), symlinks, binary files, and files over 1 MB are skipped.

  • The runtime proxy and importer write only to local files and send nothing anywhere. Their logs can hold tool arguments and output: secrets are masked by pattern, which can miss unusual formats, so keep runtime-logs/ local and private (files are created with mode 0600). --database adds another local file, SQLite, with the same rule: it can hold payloads, it is created with mode 0600 on macOS and Linux, and it is written only when you pass the flag.

Important limitations

  • Rules are static heuristics: aliases, wrappers, dynamic imports, generated code, non-Python languages, and runtime behavior can be missed.

  • Findings can be false positives. A code-pattern match is not proof that an attacker can exploit it.

  • No findings does not mean the agent is secure. Prompt checks cover prompts found in Python code, YAML, prompt template files, and agent manifests, plus web/tool content flowing into LLM messages in Python code. The scanner does not inspect model behavior, deployment configuration, or complete transitive dependency state.

  • Manifest checks read what the manifest declares; they do not verify that your code enforces it. Source checks always run, and a manifest can only add findings.

  • By default, nothing in the scanned project can hide a finding: its .agent-latch-ignore, pyproject.toml excludes, and inline ignore comments are not applied. Add --project-ignores for your own repositories.

  • OWASP category IDs help organize selected findings; the mapping is not a compliance assessment, OWASP affiliation, or certification.

  • The runtime proxy is a preview. It records only MCP traffic routed through it, does not record every MCP message type yet (see above), and never blocks or changes a call. ALR04 reports findings on tool definitions only.

FAQ

How do I scan an AI agent project for security vulnerabilities?

Install AgentLatch and run agent-latch scan /path/to/agent. It checks Python agent code, an agent-manifest.yaml describing the agent's tools and prompts, and the prompt templates it references, then reports each finding with file, line, evidence, and an OWASP Agentic Top 10 mapping. Add --dependencies to check pinned Python packages for known advisories.

How do I monitor the MCP tool calls my AI agent makes?

Put agent-latch-runtime proxy in front of the MCP server, either in your app's MCP config or as an HTTP proxy, and run agent-latch-runtime import-logs next to it from the same folder. Every tool list, tool call, result and prompt is recorded with secrets masked, and shown as one event per message. Add --database runtime-logs/runtime.db when you want those events in a local SQLite file as well. Run agent-latch-runtime demo to see the whole flow first. See Runtime monitor for MCP.

Can AgentLatch block a dangerous MCP tool call?

No. The runtime proxy is monitor only: it passes every message through unchanged. ALR04 records a finding when a tool definition looks hostile. Blocking is planned only as an opt-in the operator turns on in their own policy.

Can AgentLatch detect prompt injection?

It detects three static signals: instruction-override phrases such as "ignore all previous instructions" in prompt templates (PRM001), user input interpolated into system prompts (PRM002), and indirect prompt injection paths where web-search, web-page, or HTTP content flows into an LLM message without delimiters (AG003). It does not test model behavior at runtime, so it cannot prove an agent resists prompt injection.

Which AI agent frameworks does it support?

The source rules work on any Python code. Framework-specific checks cover CrewAI delegation, LangChain's dataframe agent and web/search tools (Tavily, DuckDuckGo, WebBaseLoader, and others), and data flowing through LangGraph state. Manifest and prompt checks are framework-agnostic. JavaScript and TypeScript agents are not scanned yet. The runtime proxy works with any agent or app that talks to MCP servers, whatever language it is written in.

How do I check AI agent security in CI or GitHub Actions?

Use the GitHub Action (uses: AgentLatch/agent-latch@v0.5.0) to scan every push and pull request and show findings in GitHub code scanning, or the pre-commit hook to block risky commits. Any other CI can run agent-latch scan --fail-on high, which exits with code 1 when high-severity findings exist.

Does AgentLatch upload my code or call an LLM?

No. Scanning runs locally and does not call any model, and the runtime proxy writes only local files. The only network use is the opt-in dependency audit, which sends package names and versions to an advisory service, and the GitHub Action's optional upload of the findings report to GitHub code scanning.

How does it map to the OWASP Top 10 for Agentic Applications?

Each finding lists the related categories, for example ASI01 Agent Goal Hijack for prompt injection, ASI02 Tool Misuse for over-privileged tools, and ASI05 Unexpected Code Execution for eval or shell=True. See the coverage table. The mapping is informational, not a compliance assessment or OWASP endorsement.

How do I handle false positives?

List accepted findings in a .agent-latch-ignore file, by path, rule, or exact line, or add an inline # agent-latch: ignore[RULE] comment, and scan with --project-ignores. These are off by default so a project you scan cannot hide its own findings. Every report states how many findings were suppressed.

Does a clean scan mean my agent is secure?

No. AgentLatch runs a focused set of static checks. A clean scan means only that those checks found nothing; it is not a security certification.

Development and tests

git clone https://github.com/AgentLatch/agent-latch.git && cd agent-latch
python3 -m venv .venv && source .venv/bin/activate
python -m pip install -e ".[dev,audit,runtime]"
python -m pytest
ruff check .

Tests use synthetic fixtures and mock the dependency-audit subprocess, so they make no network calls. Runtime tests that need FastMCP are skipped without the runtime extra. See CONTRIBUTING.md for writing new rules.

Roadmap

The longer-term direction is a layered AI-agent security toolkit. Each layer should have its own stated coverage and tests:

  • Scanner (current): expand well-scoped rules, language support, dependency manifest support, and SARIF quality.

  • Runtime checks (preview): recording and importing MCP tool traffic works today. Next come the missing MCP message types (resources, initialize, non-text content), then detection gates on the recorded events, mapped to OWASP categories. Monitor mode (findings only) stays the default; allow, deny, ask, or fence decisions apply only when the operator enables enforcement in their own policy. Checks cover only traffic routed through AgentLatch. Framework adapters and an HTTP sidecar come after that.

  • Evaluation (planned): reproducible test cases for selected agent security behaviors, with transparent methodology and no single opaque "safe" score.

  • Hosted scanning service (future, not implemented): require explicit consent, minimal repository access, retention/deletion policy, tenant isolation, and security review before accepting private source code.

The project will not claim to be an industry standard or a universal security guarantee. Interoperability, independent review, transparent tests, and community adoption must come before such claims.

Contributing and security reports

See CONTRIBUTING.md for development and rule authoring, and SECURITY.md for responsible vulnerability reporting. Please submit synthetic test fixtures rather than real secrets or confidential source code.

Questions, rule ideas, false-positive reports and setups are welcome in GitHub Discussions. Use SECURITY.md, not a public thread, for a vulnerability in AgentLatch itself.

Name and standards references

AgentLatch is an independent open-source project. It references selected categories from the OWASP Top 10 for Agentic Applications 2026 where useful. OWASP is not affiliated with or endorsing AgentLatch.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Security proxy that wraps any MCP server with bidirectional scanning for credential leaks, prompt injection, and tool description poisoning. Also provides an HTTP fetch proxy with a 9-layer scanner pipeline for capability-separated agent deployments.
    976
    Apache 2.0
  • A
    license
    Not graded
    quality
    A
    maintenance
    Open-source MCP proxy that enforces security policies, content scanning, and audit logging between AI agents and tool servers
    25
    AGPL 3.0
  • A
    license
    C
    quality
    D
    maintenance
    Security scanner and MCP server that catches dangerous patterns in MCP servers and AI agent projects, such as leaked secrets, shell execution, and prompt-injection text. Runs as both a CLI and MCP server with CI-friendly severity gates.
    2
    1
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Security scanner and runtime proxy for MCP servers. Catches tool poisoning, prompt injection, and rug-pull attacks (silent tool description changes) before they reach your AI agent. Includes a static scanner and a runtime stdio proxy.
    59 npm
    MIT