Security scanner for AI agent extensions — offline-first, multi-framework, SARIF output.
AgentShield scans MCP servers, OpenClaw skills, LangChain tools, CrewAI agents, and other AI agent extensions for security vulnerabilities before they reach production. Single Rust binary, zero data sharing, runs entirely on your machine.
AI agents are being given tools that can execute commands, read files, make HTTP requests, and install packages. A single malicious or poorly-written extension can:
- Exfiltrate credentials — read env vars and POST them to an external server
- Execute arbitrary commands — pass user input straight to
subprocess.run(shell=True) - Install backdoors at runtime —
pip installinside a tool handler - Serve as SSRF proxies — fetch attacker-controlled URLs from tool parameters
AgentShield catches these patterns with 12 built-in detectors and cross-file validation tracking that eliminates false positives, producing SARIF reports that integrate directly with GitHub Code Scanning.
| Feature | AgentShield | mcp-scan | Invariant Labs |
|---|---|---|---|
| Rust single binary | Yes | No (Python) | No (Cloud) |
| Offline / local-first | Yes | Partial | No |
| Multi-framework | MCP, OpenClaw, LangChain, CrewAI | MCP only | MCP only |
| Cross-file analysis | Yes | No | No |
| SARIF output | Yes | No | No |
| GitHub Action | Yes | No | No |
| Static analysis (AST) | tree-sitter | Regex | Runtime |
Add to .github/workflows/security.yml:
name: Agent Security
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: limaronaldo/agentshield@v1
with:
path: '.'
fail-on: 'high'
ignore-tests: true
upload-sarif: trueFindings appear as PR annotations and in the repository's Security > Code scanning tab.
# Install from crates.io
cargo install agent-shield
# Scan current directory
agentshield scan .
# Scan with specific format and threshold
agentshield scan ./my-mcp-server --format sarif --fail-on medium --output results.sarif
# Skip test files (test/, tests/, __tests__/, *.test.ts, *.spec.ts, etc.)
agentshield scan ./my-mcp-server --ignore-tests
# Generate HTML report
agentshield scan ./my-mcp-server --format html --output report.html
# List all rules
agentshield list-rules
# Create starter config
agentshield initDownload from the latest release — available for Linux (x86_64, aarch64), macOS (x86_64, aarch64), and Windows (x86_64).
git clone https://github.com/limaronaldo/agentshield.git
cd agentshield
cargo build --release
./target/release/agentshield scan /path/to/mcp-server| ID | Name | Severity | What it detects |
|---|---|---|---|
| SHIELD-001 | Command Injection | Critical | subprocess/os.system with non-literal args |
| SHIELD-002 | Credential Exfiltration | Critical | Reads secrets + makes HTTP requests in same file |
| SHIELD-003 | SSRF | High | Fetches URLs from tool parameters |
| SHIELD-004 | Arbitrary File Access | High | File read/write with parameter-derived paths |
| SHIELD-005 | Runtime Package Install | High | pip install/npm install at runtime |
| SHIELD-006 | Self-Modification | High | Writes to own source files |
| SHIELD-007 | Prompt Injection Surface | Medium | Returns unescaped external content to LLM |
| SHIELD-008 | Excessive Permissions | Medium | Declares more capabilities than used |
| SHIELD-009 | Unpinned Dependencies | Medium | No version pinning (>=, ~=, ^, *) |
| SHIELD-010 | Typosquat Detection | Medium | Package name similar to popular packages |
| SHIELD-011 | Dynamic Code Execution | Critical | eval/exec with non-literal args |
| SHIELD-012 | No Lockfile | Low | Dependencies declared without lockfile |
| Format | Flag | Use case |
|---|---|---|
| Console | --format console |
Local development (default) |
| JSON | --format json |
Programmatic consumption |
| SARIF | --format sarif |
GitHub Code Scanning, VS Code |
| HTML | --format html |
Shareable standalone reports |
4 finding(s) detected:
[CRITICAL] SHIELD-001 'subprocess.run' receives parameter 'command' as command argument
at server.py:13
fix: Validate and sanitize the input, or use an allowlist of permitted commands.
[HIGH] SHIELD-003 HTTP request to URL from parameter 'url'
at server.py:8
fix: Validate URLs against an allowlist of permitted domains.
Result: FAIL (threshold: high, highest: critical)
Create .agentshield.toml in your project root (or run agentshield init):
[policy]
# Minimum severity to fail the scan (info, low, medium, high, critical)
fail_on = "high"
# Rules to skip entirely
ignore_rules = ["SHIELD-008"]
# Downgrade specific rules
[policy.overrides]
"SHIELD-012" = "info"
[scan]
# Skip test files (test/, tests/, __tests__/, *.test.ts, *.spec.ts, etc.)
ignore_tests = true| Code | Meaning |
|---|---|
| 0 | Scan passed (no findings above threshold) |
| 1 | Scan failed (findings above threshold) |
| 2 | Scan error (invalid config, no adapter found, etc.) |
| Framework | Status | Adapter |
|---|---|---|
| MCP (Model Context Protocol) | Supported | Auto-detects package.json with MCP SDK + Python source |
| OpenClaw | Supported | Auto-detects SKILL.md files |
| CrewAI | Supported | Auto-detects pyproject.toml/requirements.txt with CrewAI deps or Python imports |
| LangChain / LangGraph | Supported | Auto-detects pyproject.toml/requirements.txt/langgraph.json with LangChain deps or Python imports |
| Language | Parser | Feature Flag |
|---|---|---|
| Python | tree-sitter AST | python (default) |
| TypeScript/TSX | tree-sitter AST | typescript (default) |
| JavaScript/JSX | tree-sitter AST | typescript (default) |
| Shell (bash/zsh) | Regex | always on |
| JSON Schema | MCP tool input parser | always on |
Both tree-sitter parsers are feature-gated. Build without them for a smaller binary:
cargo build --no-default-features # regex fallback for all languages
cargo build --features python # only Python AST
cargo build --features full # all parsersCLI / GitHub Action
│
┌──────▼──────┐
│ Scan Engine │ ── scan() → ScanReport
└──────┬──────┘
│
┌────┼────────────┐
▼ ▼ ▼
Adapters Parsers Supply Chain
MCP, Python, Analysis
OpenClaw, TypeScript,
CrewAI,
LangChain
Shell,
JSON Schema
└────┬────────────┘
▼
Cross-File Analysis
(sanitizer tracking)
▼
Unified IR (ScanTarget)
│
┌────▼────┐
│ Rules │ ── 12 detectors
│ Engine │
└────┬────┘
▼
Output
SARIF, JSON,
HTML, Console
Adapters translate framework-specific files into a unified intermediate representation (ScanTarget). Cross-file analysis eliminates false positives from helper functions that receive already-validated input. Detectors only read the IR, so adding a new framework never requires changing any detector.
# Run tests
cargo test
# Run with strict lints
cargo clippy -- -D warnings
# Check formatting
cargo fmt --check
# Build release binary
cargo build --releaseLicensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.