Install
$ agentstack add mcp-mkarvan-agentshield ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ● Filesystem access Used
- ● Shell / process execution Used
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
AgentShield
Security layer for AI agent frameworks. AgentShield intercepts package installation requests made by AI agents, checks them against CVE databases and static analysis tools, enforces configurable response policies, and generates security posture reports — all locally, with no telemetry.
[](#installation) [](LICENSE) [](#)
> AI agent? Skip straight to the [Agent Setup Guide](AGENT_SETUP.md) — it has everything your agent needs to integrate AgentShield in one self-contained document.
Why this exists
AI agents can now install arbitrary packages on behalf of users. This creates a novel attack surface that existing security tooling doesn't address:
- An agent can be prompt-injected — a malicious web page or tool result instructs the agent to install a backdoored package
- Agents may typosquat — suggest
requetsinstead ofrequests, orpandainstead ofpandas - Agents don't inherently check CVEs or audit dependency trees before installing
- Compromised packages can exfiltrate context windows, API keys, tool credentials, or local files before the user notices anything
AgentShield sits between the agent's intent ("install X") and the system executing that intent, providing a security checkpoint the agent cannot bypass. It works with any framework through native plugins (Hermes, OpenClaw) or the MCP protocol.
Table of Contents
- [Architecture](#architecture)
- [Threat model](#threat-model)
- [Installation](#installation)
- [Quick start](#quick-start)
- [Configuration](#configuration)
- [CLI reference](#cli-reference)
- [agentshield scan](#agentshield-scan)
- [agentshield scan-file](#agentshield-scan-file)
- [agentshield scan-mcp](#agentshield-scan-mcp)
- [agentshield sbom](#agentshield-sbom)
- [agentshield posture](#agentshield-posture)
- [agentshield cache](#agentshield-cache)
- [agentshield serve](#agentshield-serve)
- [agentshield proxy](#agentshield-proxy)
- [agentshield doctor / init](#agentshield-doctor--init)
- [Framework integrations](#framework-integrations)
- [Posture reports](#posture-reports)
- [Python API](#python-api)
- [Static analysis (--deep)](#static-analysis---deep)
- [Transitive dependency scanning](#transitive-dependency-scanning)
- [SBOM generation](#sbom-generation)
- [License compliance scanning](#license-compliance-scanning)
- [pre-commit hook](#pre-commit-hook)
- [GitHub Action](#github-action)
- [Drift detection](#drift-detection)
- [Rate limits](#rate-limits)
- [Diff scan mode](#diff-scan-mode)
- [Trust score / reputation system](#trust-score--reputation-system)
- [Container / Docker scanning](#container--docker-scanning)
- [HTTP daemon mode](#http-daemon-mode)
- [agentshield guard](#agentshield-guard)
- [Offline mode](#offline-mode)
- [Caching](#caching)
- [Audit log](#audit-log)
- [Provenance / attestations](#provenance--attestations)
- [SARIF output](#sarif-output)
- [Waivers](#waivers)
- [Notifications](#notifications)
- [Testing](#testing)
- [Contributing](#contributing)
- [License](#license)
Architecture
┌───────────────────────────────── Entry points ─────────────────────────────────┐
│ │
│ Agent plugins (in-process) Agent hooks Servers / CLI │
│ ┌───────────────────────┐ ┌────────────────────┐ ┌─────────────────────────┐ │
│ │ Hermes pre_tool_call │ │ Claude Code, Codex │ │ MCP (stdio) · HTTP :8765│ │
│ │ OpenClaw │ │ PreToolUse │ │ IPC socket · CLI / CI │ │
│ │ before_tool_call │ │ (agentshield hook) │ │ GitHub Action·pre-commit│ │
│ └───────────┬───────────┘ └─────────┬──────────┘ └────────────┬────────────┘ │
└──────────────┼────────────────────────┼──────────────────────────┼──────────────┘
│ │ │
┌──────────────┴────────────────────────┴──────────────────────────┴──────────────┐
│ Enforcement layers (all fail CLOSED) │
│ guard shell wrapper · PATH shim · execve interceptor (LD_PRELOAD/dyld) │
│ index proxy :8799 — PIP_INDEX_URL / npm registry / GOPROXY │
└──────────────────────────────────────┬──────────────────────────────────────────┘
│ ScanRequest
┌──────────▼──────────┐
│ Core Engine │
│ denylist → allowlist│
│ → cache → rate limit│
└──────────┬──────────┘
│ cache miss
┌─────────────────────────────┼─────────────────────────────┐
│ │ │
┌────────▼─────────┐ ┌───────────▼───────────┐ ┌──────────▼──────────┐
│ Enrichment │ │ Local heuristics │ │ Static analysis │
│ (parallel, fails │ │ (offline-capable) │ │ (--deep only) │
│ open) │ │ │ │ │
│ • OSV │ │ • typosquat (T1.2) │ │ • semgrep │
│ • NVD (CPE- │ │ • malicious DB (T1.1) │ │ • bandit │
│ version-aware) │ │ • prompt-inj. (T4.1) │ │ • AST inspector │
│ • GitHub Advisory│ │ • drift (D1.1) │ │ (PyPI wheels/ │
│ • license (L1.1) │ │ • lockfile hashes │ │ sdists) (T3.x) │
│ • provenance │ │ (H1.x) │ └─────────────────────┘
│ (T6.x) │ │ • syspkg CVEs (SP1.x) │
│ • trust score │ └───────────────────────┘
│ (T5.1) │
└──────────────────┘
│
┌────────▼────────────────────────────────────────────────┐
│ Response Engine │
│ severity policy → per-ecosystem → per-rule-ID → waivers │
│ ⇒ ALLOW · BLOCK · NEEDS_CONFIRMATION · LOG_ASYNC │
└────────┬────────────────────────────────────────────────┘
│ every decision
┌────────▼─────────────────────────┐ ┌──────────────────────────────────┐
│ Audit log — hash-chained JSONL │ │ Local SQLite │
│ + SQLite query index │ │ scan cache · CVE mirror · │
│ + HTTP/syslog forwarding │ │ malicious DB · scan history · │
│ Webhook notifications (Slack) │ │ provenance history · rate limits │
└──────────────────────────────────┘ └──────────────────────────────────┘
Data flow
Agent: "pip install numpy==1.24.0"
│
▼
[Entry point] plugin hook / PreToolUse / guard / shim / execve / proxy / CLI
└─→ ScanRequest(package="numpy", version="1.24.0", ecosystem="pypi")
│
▼
[Core Engine]
├── denylist → BLOCK immediately (never scanned)
├── allowlist → ALLOW immediately (never scanned)
├── cache HIT → return cached ScanResult ( **Note:** PyPI publishing is planned for a future release.
### Optional extras
```bash
# Static analysis (semgrep + bandit) — needed for --deep flag
pip install "agentshield[static-analysis] @ git+https://github.com/mkarvan/AgentShield.git"
# Hermes Agent integration
pip install "agentshield[hermes] @ git+https://github.com/mkarvan/AgentShield.git"
# OpenClaw integration is a Node plugin (OpenClaw is TypeScript), installed in
# the OpenClaw box — not a Python extra:
# openclaw plugins install @agentshield/openclaw-plugin
# (it shells out to the `agentshield` CLI, so install that too: pipx install agentshield)
# Hermes + static analysis (the [all] bundle)
pip install "agentshield[all] @ git+https://github.com/mkarvan/AgentShield.git"
Quick start
# 1. Scan a package (online — hits OSV + NVD + GitHub Advisory)
agentshield scan requests==2.28.0 --ecosystem pypi
# 2. Deep scan — download wheel and run static analysis
agentshield scan some-new-package --ecosystem pypi --deep
# Scan package + its transitive dependencies
agentshield scan flask --transitive
# Scan an entire requirements.txt at once
agentshield scan-file requirements.txt
# Generate a CycloneDX SBOM from a manifest
agentshield sbom requirements.txt
# 3. Populate local database for offline use (~2–5 min first run)
agentshield cache warm
# 4. Generate a security posture report
agentshield posture
# 5. Start the MCP server (any MCP-compatible agent connects to this)
agentshield serve --mcp
Exit codes for agentshield scan: 0 = ALLOW/WARN/LOG_ASYNC, 1 = BLOCK.
API keys (optional but recommended)
Set these to raise NVD rate limits and enable the GitHub Advisory Database:
export NVD_API_KEY=your-key-here # 5 → 50 req/30s; get one at nvd.nist.gov/developers
export GITHUB_TOKEN=ghp_... # enables GitHub Advisory lookups; any classic PAT works
You can also set them in ~/.config/agentshield/config.toml under [api].
Configuration
AgentShield looks for config at ~/.config/agentshield/config.toml. Create it to override defaults.
> [!IMPORTANT] > System-package CVE scanning is OFF by default (since v0.9.0). > AgentShield still detects system installs (apt/yum/apk/brew/snap/…) and prints an SP1.1 warning, but it does not run a live CVE scan of them unless you opt in. This is deliberate: distro packages ship with many low/medium CVEs, so scanning every apt-get install curl or yum install httpd would block or nag on routine installs (and slow paths like snap install could time out). > > To turn it on, add three lines to your config: > > ``toml > [syspkg] > cve_scan = true # default: false > ` > > See [System package scanning ([syspkg]`)](#system-package-scanning-syspkg) for the severity floor, findings cap, and recommended policy.
Full config reference
# ── Response defaults (by severity) ──────────────────────────────────────────
[defaults]
critical = "block" # ALLOW | BLOCK | WARN_CONFIRM | ASYNC_REPORT
high = "warn_confirm"
medium = "async_report"
low = "ignore"
info = "ignore"
# ── Per-ecosystem overrides ───────────────────────────────────────────────────
[ecosystems.pypi]
high = "block" # Stricter than default for pip installs
[ecosystems.npm]
high = "warn_confirm"
critical = "block"
[ecosystems.cargo]
critical = "block"
high = "warn_confirm"
# ── Per-rule-ID overrides (highest priority) ──────────────────────────────────
[rules]
[rules."T1.1"] # Known-malicious: always block, regardless of severity
mode = "block"
[rules."T1.2"] # Typosquatting: always block
mode = "block"
[rules."T2.3"] # Transitive CVEs: only log, don't block
mode = "async_report"
[rules."T3.1"] # Shell execution at install time
mode = "warn_confirm"
[rules."T3.5"] # Credential harvesting: block
mode = "block"
[rules."T4.1"] # Prompt injection heuristic: confirm before allowing
mode = "warn_confirm"
# ── Allowlist / denylist ─────────────────────────────────────────────────────
[allowlist]
# Packages that bypass all checks (trusted internal packages, etc.)
packages = ["numpy", "requests", "pytest", "boto3"]
[denylist]
# Packages that are always blocked regardless of findings
packages = ["malicious-pkg-example", "colouredlogs"]
# ── API keys ─────────────────────────────────────────────────────────────────
[api]
# Also accepted via environment variables NVD_API_KEY and GITHUB_TOKEN
nvd_api_key = "" # Increases NVD rate limit from 5→50 req/30s
github_token = "" # Required for GitHub Advisory Database (GraphQL)
# ── Cache settings ────────────────────────────────────────────────────────────
[cache]
db_path = "~/.agentshield/agentshield.db"
ttl_hours = 24
# Entries are evicted (oldest first) once this many are cached, and each is
# re-fetched after ttl_hours. Never-expiring BLOCK entries are exempt from
# eviction. Entries are small JSON blobs, so the default 50,000-entry cap
# corresponds to roughly tens of MB of disk and working memory.
max_entries = 50000
# Warm-data freshness: offline scans and `cache stats` warn when the OSV
# mirror (populated by `agentshield cache warm`) is older than this.
warm_max_age_days = 7
# Opt-in: long-running `agentshield serve` daemons re-warm stale ecosystems
# in the background, checking every auto_warm_interval_hours.
auto_warm = false
auto_warm_interval_hours = 24
# ── System packages (apt/yum/apk/brew/snap/…) ─────────────────────────────────
[syspkg]
enabled = true # Detect system installs + emit SP1.1 warning (never blocks)
cve_scan = false # OPT-IN live CVE scan of system packages (off by default)
severity_floor = "HIGH" # When cve_scan is on, ignore findings below this severity
max_findings = 50 # Cap findings shown; overflow summarised as "+N more"
# Only applies when cve_scan = true.
[syspkg.severity_policy]
critical = "block"
high = "warn_confirm"
medium = "async_report"
low = "ignore"
info = "ignore"
# ── Release-age quarantine (A1.1) ─────────────────────────────────────────────
[release_age]
min_days = 0 # quarantine versions younger than N days; 0 = disabled
# (HIGH → warn_confirm under the default policy)
# ── Dependency-confusion protection (DC1.1) ───────────────────────────────────
[namespaces]
internal = [] # e.g. ["mycorp-*", "@mycorp/*"] — internal names that
# must NEVER resolve from a public registry (hard BLOCK,
# checked before the allowlist)
# ── Reporting ─────────────────────────────────────────────────────────────────
[reporting]
report_dir = "~/.agentshield/reports/"
auto_report_on_exit = true
# ── License policy (opt-in) ───────────────────────────────────────────────────
[license_policy]
mode = "disabled" # disabled | denylist | allowlist | permissive-only
denied = ["GPL-2.0-only", "GPL-2.0-or-later", "GPL-3.0-only", "GPL-3.0-or-later",
"AGPL-3.0-only", "AGPL-3.0-or-later", "SSPL-1.0", "EUPL-1.1", "OSL-3.0"]
# allowed = ["MIT", "Apache-2.0", "BSD-2-Clause", "BSD-3-Clause", "ISC"]
Response modes
| Mode | CLI identifier | Behaviour | |------|---------------|-----------| | Block | block | Refuse install. Returns error to agent. Agent cannot proceed. | | Warn & confirm | warn_confirm | Present findings to user. Require explicit approval before allowing. Agent pauses. | | Async report | async_report | Allow install unconditionally. Record findings for the next posture report. | | Ignore | ignore | Skip this check entirely. No scan overhead. |
Priority resolution
When a finding arrives, AgentShield looks up the response mode in this order (first match wins):
1. rule-level override [rules."T1.2"] mode = "block"
2. ecosystem-level override [ecosystems.pypi] high = "block"
3. global severity default [defaults] high = "warn_confirm"
│
(denylist check: always BLOCK regardless of above)
(namespace check: internal names always BLOCK — even if allowlisted)
(allowlist check: always ALLOW, skips the scan entirely)
API keys
| Key | Where | Effect | |-----|-------|--------| | NVD_API_KEY | env var or [api] | NVD rate limit: 5 req/30s → 50 req/30s. Get one at nvd.nist.gov/developers | | GITHUB_TOKEN | env var or [api] | Enables GitHub Advisory Database. Any classic PAT with no scopes works. github.com/settings/tokens |
AgentShield works without either key — OSV has no rate limit and covers most PyPI/npm/Rust packages.
System package scanning ([syspkg])
AgentShield also notices when an agent shells out to a system package manager (apt/apt-get, yum/dnf, apk, brew, snap, pacman, zypper, flatpak, …). This is controlled by the [syspkg] section:
| Key | Default | Eff
…
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: mkarvan
- Source: mkarvan/AgentShield
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.