AgentFort
Static security scanner for AI agent codebases. Analyzes repositories and MCP config files against a CVE-style advisory database — no live agent interaction required.
What it does
- Scans Python repos for dangerous patterns:
eval(),exec(),shell=True, hardcoded API keys - Parses MCP config files (
claude_desktop_config.json,.mcp.json) for shell execution tools, overly broad filesystem access, and unverifiednpx/uvxpackages - Detects agent framework imports (LangChain, CrewAI, AutoGen, OpenAI, Anthropic, etc.) and cross-references against known vulnerabilities
- Queries OSV.dev live for real CVEs against every detected package — findings stay current without any database updates
- Produces risk scores, terminal reports, Markdown, and JSON output
- Exits with code 1 on critical findings — CI pipeline friendly
Install
# From repo root (inside a virtualenv)
pip install agentfort
# Or dev install from repo root
pip install -e .
Usage
# Scan a repo
agentfort scan --repo /path/to/your/agent-project
# Scan just an MCP config file
agentfort scan --mcp-config ~/.config/claude/claude_desktop_config.json
# JSON output (clean stdout, progress on stderr)
agentfort scan --repo . --format json
# Markdown report to file
agentfort scan --repo . --format md --output report.md
# Only show high and above
agentfort scan --repo . --min-severity high
# Disable CI exit code
agentfort scan --repo . --no-fail-on-critical
# Skip OSV live lookup (air-gapped / CI without outbound)
agentfort scan --repo . --offline
# Browse advisories
agentfort advisories list
agentfort advisories list --severity critical
agentfort advisories show AGSA-001
Pro tier — Alerts and Digest
Scan notifications
Post findings to Slack or email when a scan completes:
# Slack alert on critical findings
agentfort scan --repo . --notify-slack https://hooks.slack.com/services/...
# Email alert (requires SMTP env vars)
export AGENTFORT_SMTP_HOST=smtp.example.com
export AGENTFORT_SMTP_USER=alerts@example.com
export AGENTFORT_SMTP_PASS=secret
export AGENTFORT_SMTP_FROM=alerts@example.com
agentfort scan --repo . --notify-email team@example.com
# Env var shorthand (useful in CI secrets)
export AGENTFORT_SLACK_WEBHOOK=https://hooks.slack.com/services/...
agentfort scan --repo .
Weekly advisory digest
Send a digest of new advisories on a schedule:
# Show all advisories
agentfort digest
# Show only advisories added in the last 7 days
agentfort digest --since 7
# Post to Slack
agentfort digest --since 7 --slack $SLACK_WEBHOOK
# Email the digest
agentfort digest --since 7 --email team@example.com
Run the digest weekly via GitHub Actions scheduled workflow:
on:
schedule:
- cron: '0 9 * * 1' # every Monday at 9am UTC
jobs:
digest:
runs-on: ubuntu-latest
steps:
- run: pip install agentfort
- run: agentfort digest --since 7 --slack ${{ secrets.SLACK_WEBHOOK }}
GitHub Actions Pro inputs
- name: AgentFort Security Scan
uses: ./.github/actions/agentfort
with:
repo-path: '.'
fail-on-critical: 'true'
offline: 'true'
slack-webhook: ${{ secrets.SLACK_WEBHOOK }} # optional
notify-email: 'team@example.com' # optional
GitHub Actions
Add AgentFort to any CI pipeline with one step. The action installs agentfort from PyPI and runs a full scan — failing the build on critical findings by default.
- name: AgentFort Security Scan
uses: NeuronKnight/agentfort-action@v1
with:
repo-path: '.' # directory to scan (default: .)
min-severity: 'low' # critical | high | medium | low (default: low)
fail-on-critical: 'true' # fail build on critical findings (default: true)
offline: 'false' # skip OSV.dev live CVE lookup (default: false)
Full workflow example:
name: Security Scan
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: NeuronKnight/agentfort-action@v1
with:
min-severity: high
fail-on-critical: 'true'
Note:
NeuronKnight/agentfort-actionis the planned standalone Action repo. Until it's published, use the local action from this repo:uses: ./.github/actions/agentfort.
Live CVE lookup (OSV.dev)
Every scan queries OSV.dev in parallel for known CVEs against every package detected in the repo. No database to update — findings reflect OSV's current state on each run.
- Results are capped at 5 CVEs per package (highest severity first) to avoid noise from very old pinned versions
- Uses GHSA severity labels (
database_specific.severity) for accurate critical/high/medium/low mapping - Falls back silently if the network is unreachable — use
--offlineto skip the lookup entirely
# Scan with live CVEs (default)
agentfort scan --repo .
# Air-gapped / no outbound network
agentfort scan --repo . --offline
Ignoring paths
Create .agentfortignore in your repo root to exclude directories or files from scanning. Uses gitignore-style glob patterns:
# .agentfortignore
# Ignore generated code
generated/
# Ignore vendor directory
vendor/
# Ignore specific file pattern
*.pb.py
The scanner skips any file whose path matches a pattern. Useful for:
- Vendored code you don't control
- Test fixtures that intentionally contain vulnerable patterns
- Generated files with no manual security surface
Advisory database
14 static advisories covering structural/behavioral risks from the OWASP Agentic Top 10. Package CVEs are handled live by OSV.dev (see above).
| ID | Severity | Risk |
|---|---|---|
| AGSA-001 | Critical | LangChain ShellTool unrestricted shell execution |
| AGSA-002 | Critical | MCP server exposes shell execution tool |
| AGSA-003 | Critical | eval()/exec() in agent tool handler |
| AGSA-005 | Critical | AutoGen/CrewAI code execution without confirmation |
| AGSA-004 | High | Hardcoded API key or secret in MCP config |
| AGSA-006 | High | MCP filesystem server with overly broad path (/, ~) |
| AGSA-007 | High | subprocess with shell=True or os.system() |
| AGSA-008 | High | Agent tool writes to arbitrary file paths |
| AGSA-010 | High | Prompt injection via unvalidated tool output |
| AGSA-013 | High | OpenAI Assistants file_search/code_interpreter without scope restriction |
| AGSA-009 | Medium | MCP server loaded via unverified npx/uvx package |
| AGSA-012 | Medium | Secrets exposed via os.environ in tool scope |
| AGSA-014 | Medium | Non-PyPI/non-npm dependency as framework component |
| AGSA-015 | Medium | System prompt in user-accessible config location |
Risk score
0–100. Each finding adds: critical=40, high=15, medium=5, low=1. Capped at 100.
Output formats
Terminal (default) — Rich panels with color-coded severity table and detail panels for critical/high findings.
JSON — Machine-readable. Progress messages go to stderr so stdout is clean for piping:
agentfort scan --repo . --format json 2>/dev/null | jq '.findings[] | select(.severity=="critical")'
Markdown — Full report with summary table and per-finding sections, suitable for GitHub issues or PR comments.
Project structure
agentfort/ # project root
├── agentfort/ # Python package
│ ├── cli.py # Click CLI entry point
│ ├── models.py # Finding, ScanResult dataclasses
│ ├── db/
│ │ ├── advisory.py # Advisory loader and index
│ │ └── data/ # AGSA-001.yaml … AGSA-015.yaml
│ ├── scanner/
│ │ ├── frameworks.py # requirements.txt / pyproject.toml / package.json
│ │ ├── mcp.py # MCP config file scanner
│ │ ├── osv.py # Live CVE lookup via OSV.dev API
│ │ ├── patterns.py # Python source pattern scanner
│ │ └── secrets.py # Hardcoded credential scanner
│ └── report/
│ └── formatter.py # Terminal, Markdown, JSON renderers
└── pyproject.toml
Metadata
Release files for agentfort 0.1.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| agentfort-0.1.5.tar.gz | 33.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| agentfort-0.1.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 73.2 kB
Release files / agentfort-0.1.5.tar.gz
| Download URL | agentfort-0.1.5.tar.gz |
|---|---|
| Size | 33.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e196110ed982352a19c1e569cd3d25f68eb05439120ec7816894b13112a0a1e5
|
|
BLAKE2b-256 checksum How to use checksums |
8e28ddfb166b395c0845d40a30a8b7c82a5c3add8ffdd9e565cb3ebc3396b3bf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|
Release files / agentfort-0.1.5-py3-none-any.whl
| Download URL | agentfort-0.1.5-py3-none-any.whl |
|---|---|
| Size | 39.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b780b3dca561dcada048a0f0a8d5473006025c94e66853b376eff194fd6c2922
|
|
BLAKE2b-256 checksum How to use checksums |
a54703f58ca409e3a41ea07f9de7ed39052cc512fd657ac27fd628c8564d21c9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|