Tools
Agent Guard
Scan AI agent skills, plugins, and MCP servers for malicious code before installation - one scan, every agent (Claude Code, Codex, Gemini, Hermes, OpenClaw). Powered by cisco-ai-skill-scanner.
README
# agent-guard
[](https://skills.sh/elliottwaves-20/agent-guard)
**Scan any AI agent skill, plugin, or MCP server for malicious code โ before it ever runs on your machine.**
Skills and MCP servers are third-party code executed with your user account's permissions. A malicious one can read your SSH keys, grab `.env` files and browser sessions, exfiltrate data โ or hijack your AI agent through a poisoned SKILL.md (prompt injection). This skill makes **scan first, install after** the default workflow, powered by Cisco's [skill-scanner](https://github.com/cisco-ai-defense/skill-scanner) (for skills) and [mcp-scanner](https://github.com/cisco-ai-defense/mcp-scanner) (for MCP servers).
## What you get
- **Commit-pinned ZIP scanning** โ repos are fetched as a ZIP snapshot of one exact commit; `git clone` never touches your machine before a verdict, and the commit that was scanned is the commit that gets installed. No scan/install gap an attacker could slip a push into.
- **Skills *and* MCP servers** โ an MCP server is code that must run to be inspected, so naive scanning would execute it. `scan_mcp.py` scans the package **source** first (fetched from the registry, nothing executed), with an optional **Docker-sandboxed** live scan โ untrusted MCP code never runs unconfined on your machine.
- **Three analysis layers** โ static signatures, behavioral dataflow analysis, and optional LLM-powered semantic analysis with automatic false-positive filtering.
- **Bring your own LLM** โ Anthropic, OpenAI, local Ollama (free, no API key), or any OpenAI-compatible endpoint (OpenRouter, Groq, Azure, vLLM, LM Studio) via bundled LiteLLM.
- **Fail-closed workflow** โ scanner errors are never silently treated as "no findings".
- **Prompt-injection aware** โ content of scanned repos is treated as data, never as instructions to the reviewing agent.
- **Clear verdicts** โ โ
SAFE / โ REVIEW / ๐ซ DO NOT INSTALL, with file and line for every finding.
- **Universal installer included** โ after a SAFE verdict, one command installs the skill or MCP server to every agent detected on the machine (Claude Code, Claude Desktop, Codex, Antigravity/Gemini, Hermes, OpenClaw), or a subset via `--tools`.
## One scan, every agent
Skills are not a Claude-only concept: they follow the open [SKILL.md standard (agentskills.io)](https://agentskills.io), and [MCP](https://modelcontextprotocol.io) is an open protocol. The same skill or server runs in Claude Code, Codex, Gemini/Antigravity, [Hermes](https://hermes-agent.nousresearch.com), [OpenClaw](https://docs.openclaw.ai), and friends โ and the Cisco scanner doesn't care which agent the code is destined for.
Many people now work across several agents in parallel, not least because of per-provider rate limits. That normally means installing โ and *trusting* โ the same third-party code once per agent. agent-guard collapses this into **scan once, verdict once, install everywhere**: one command links the audited commit into every detected agent, so all your agents run exactly the same reviewed code. Use `--tools` to target only specific agents.
## Supported tools (auto-detected)
| Tool | Skills | MCP servers |
|------|--------|-------------|
| Claude Code | `~/.claude/skills/` | `claude mcp add -s user` โ `~/.claude.json` |
| Claude Desktop | `~/.claude/skills/` *(shared with Claude Code)* | `%APPDATA%/Claude/claude_desktop_config.json` |
| Codex | `~/.codex/skills/` | `~/.codex/config.toml` |
| Antigravity / Gemini | `~/.gemini/config/skills/` | `~/.gemini/config/mcp_config.json` |
| Hermes (Nous Research) | `~/.hermes/skills/` | manual โ `mcp_servers:` block in Hermes `config.yaml` |
| OpenClaw | `~/.openclaw/skills/` | manual โ OpenClaw's own MCP tooling |
Detection is automatic โ only tools whose configs exist are touched. Claude Desktop reads skills from the same `~/.claude/skills/` as Claude Code, so that shared path is linked once and serves both. JSON configs are backed up (`.bak`) before every write. Hermes and OpenClaw use their own MCP config formats (YAML / CLI), so the installer prints instructions for those instead of modifying configs blindly.
## Prerequisites
- [uv](https://docs.astral.sh/uv/) โ installs the scanners in isolated environments (uv ships its own Python)
- Python 3.10+ โ for running `scripts/install_skill.py` and `scripts/scan_mcp.py`
- An LLM provider of your choice โ optional, enables LLM-powered analysis (see [LLM provider support](#llm-provider-support)); without one, skill scans run with `--use-behavioral` only
- [Docker](https://docs.docker.com/get-docker/) โ **optional**, only for the MCP sandbox (`scan_mcp.py ... --sandbox`, Stage 2). Skill scans and the default Stage 1 MCP source scan do **not** need Docker.
## Quick start
**Option A โ via [skills.sh](https://skills.sh) (any of 70+ agents):**
```bash
# Installs the skill into every agent the CLI detects (Claude Code, Codex,
# Hermes, OpenClaw, Cursor, ...). Works without git.
npx skills add elliottwaves-20/agent-guard
```
This installs the skill files. The skill drives the [cisco-ai-skill-scanner](https://github.com/cisco-ai-defense/skill-scanner) binary, so run the one-time setup afterwards to install it:
```bash
cd ~/.claude/skills/agent-guard # or wherever the CLI placed it
./setup.sh # Windows PowerShell: .\setup.ps1
cp .env.example .env # optional: pick an LLM provider
```
**Option B โ clone and install manually:**
```bash
git clone https://github.com/elliottwaves-20/agent-guard
cd agent-guard
./setup.sh # Windows PowerShell: .\setup.ps1
cp .env.example .env # optional: pick an LLM provider for deeper analysis
# Register agent-guard itself into every detected agent (auto-detects your tools):
python scripts/install_skill.py skill .
```
## Usage
### Scan a GitHub repo before installing
```bash
# Load LLM provider config (optional, enables --use-llm)
set -a && source .env && set +a
REPO="user/repo-name"
WORKDIR=$(mktemp -d)
# Pin the current commit of the default branch (works for main, master, anything)
SHA=$(curl -fsSL "https://api.github.com/repos/${REPO}/commits/HEAD" \
| grep -m1 '"sha"' | cut -d'"' -f4)
# Download exactly that commit as ZIP โ no git hooks, no git attack surface
curl -fsSL "https://github.com/${REPO}/archive/${SHA}.zip" -o "$WORKDIR/scan.zip"
unzip -q "$WORKDIR/scan.zip" -d "$WORKDIR/src"
# Scan the extracted skill directory (the ZIP unpacks into <repo>-<sha>/)
# Provider and model come from .env โ no provider flag needed
skill-scanner scan "$WORKDIR/src"/* --use-behavioral --use-llm \
--enable-meta --format table
# Cleanup (keep $SHA for installation)
rm -rf "$WORKDIR"
```
Scanner errors or empty output mean **no verdict** โ never treat a failed scan as safe.
### Scan an MCP server before installing
MCP servers need different handling than skills. A skill is Markdown that only gets *read*; an MCP server is code that must *run* to expose its tools โ so "just start it and scan" would already execute untrusted code. `scan_mcp.py` enforces a safe order:
**Stage 1 (default โ nothing from the package runs):** fetch the source straight from the registry and scan it.
```bash
# PyPI MCP server:
python scripts/scan_mcp.py pypi mcp-server-name
# npm MCP server:
python scripts/scan_mcp.py npm @scope/mcp-server-name
# source already on disk / a hosted remote MCP:
python scripts/scan_mcp.py local ./path/to/mcp-source
python scripts/scan_mcp.py remote https://example.com/mcp
```
**Stage 2 (optional โ live runtime check):** start the server inside a throwaway **Docker container with no access to your filesystem**, then scan its live tools and prompts.
```bash
python scripts/scan_mcp.py pypi mcp-server-name --sandbox -- uvx mcp-server-name
```
The scan reuses `SKILL_SCANNER_LLM_API_KEY` from `.env` (the behavioral source analysis is LLM-based). A clean Stage 1 scan does **not** prove runtime safety โ reach for `--sandbox` when a server is unfamiliar. Install only after a SAFE verdict.
### Install after a SAFE verdict
Install the same commit that was scanned:
```bash
git clone https://github.com/user/repo-name ~/path/to/workspace/repo-name
git -C ~/path/to/workspace/repo-name -c advice.detachedHead=false checkout "$SHA"
# All detected agents at once:
python scripts/install_skill.py skill ~/path/to/workspace/repo-name
# Or only specific agents:
python scripts/install_skill.py skill ~/path/to/workspace/repo-name --tools claude-code hermes
```
**MCP server (PyPI, isolated via uvx) โ only after `scan_mcp.py` returned SAFE:**
```bash
python scripts/install_skill.py mcp \
--name "my-server" \
--command "uvx" \
--args "package-name" \
--env "API_KEY=your-key"
```
**Dry run first** to preview every change:
```bash
python scripts/install_skill.py mcp --name foo --command uvx --args bar --dry-run
python scripts/install_skill.py skill <path> --dry-run
```
### Audit all installed skills
```bash
skill-scanner scan-all ~/.claude/skills --use-behavioral --format table
```
## LLM provider support
The LLM analyzer (`--use-llm`) works with any provider โ configure it once in `.env`, the scan commands stay the same:
| Provider | `.env` settings | Notes |
|----------|----------------|-------|
| **Anthropic** (default) | `PROVIDER=anthropic`, `API_KEY`, `MODEL=claude-haiku-4-5-20251001` | fast + cheap for scanning |
| **OpenAI** | `PROVIDER=openai`, `API_KEY`, `MODEL=gpt-4o-mini` | |
| **Ollama** (local) | `MODEL=ollama/<model>` | free, no API key, fully offline |
| **OpenAI-compatible** | `PROVIDER=openai-compatible`, `API_KEY`, `MODEL`, `BASE_URL` | OpenRouter, Groq, Azure OpenAI, vLLM, LM Studio, ... |
All variables use the `SKILL_SCANNER_LLM_` prefix (see `.env.example`). LiteLLM is bundled โ no extra install. A separate model for the meta analyzer can be set via `SKILL_SCANNER_META_LLM_*`.
**Verdict quality depends on model quality.** This tool makes
... (truncated)
tools
Comments
Sign in to leave a comment