Skip to main content

Security scanner for MCP servers — finds hardcoded secrets, unsafe exec, missing auth

Project description

MCP Security Scan

GitHub Marketplace License: MIT

Security scanner for Model Context Protocol (MCP) servers. Finds hardcoded secrets, unsafe execution patterns, data exfiltration risks, filesystem access issues, code obfuscation, and missing authentication.

Available as a GitHub Action and a CLI tool.


Why?

We statically scanned 7,029 public MCP servers (part of a 35,689-endpoint agent-ecosystem corpus):

  • 9% — nearly 1 in 11 — ship at least one high or critical issue detectable by static analysis alone
  • Most common: hardcoded secrets, unsafe shell/exec with user-controllable input, credential-exfiltration paths, filesystem access far broader than advertised

Full prevalence data + methodology: Agent Tool Supply-Chain Security: Prevalence from 35,689 Scans.

MCP servers run on your machine with access to your files, shell, and API keys — and increasingly get called in a loop by autonomous agents with nobody watching. Recent incidents like GitLost (GitHub's AI agent tricked into leaking private repos) and MCPoison / CVE-2025-54136 (the Cursor mcp.json rug-pull) live on this exact attack surface. Most MCP servers have no security review process.

What it detects

Twelve finding categories, all open source:

Category Examples
secret Hardcoded API keys, tokens, credentials
unsafe_exec shell=True with user input, eval/exec on external data
exfiltration Env vars / secrets piped into network calls
fs_access "Read a file" servers that can walk the entire home directory
obfuscation Base64-packed or dynamically-assembled code
dynamic_remote_load Rug-pulls: fetch-then-exec, curl|sh, unpinned npx/uvx, manifest-exec (the MCPoison / CVE-2025-54136 class)
hidden_unicode Invisible Unicode Tags, bidi controls (Trojan Source), zero-width chars smuggling instructions past review
prompt_injection Instruction-override / hide-from-user / exfil directives in tool descriptions, mcp.json, SKILL.md
insecure_deserialization pickle.loads, unsafe yaml.load, torch.load on untrusted data
install_hook npm preinstall/postinstall scripts that fetch, eval, or pipe to shell
toxic_flow The lethal trifecta (the GitLost class): private-data read + untrusted input + outbound send composing in one tool
Missing auth Tool endpoints with no authentication boundary

The hosted scanner at agentgraph.co/check adds what a local one-shot scan structurally can't: every verdict signed as an offline-verifiable attestation (Ed25519/JWS), tool-definition pinning with drift detection across re-scans (a tool that changes after you vetted it fails verification), and vulnerable-dependency intelligence from a 35,689-endpoint scan corpus.


Quick Start

GitHub Action (recommended)

Add this to .github/workflows/mcp-security.yml:

name: MCP Security Scan
on: [push, pull_request]

jobs:
  security-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: agentgraph-co/mcp-security-scan@v1
        with:
          fail-on: critical

That's it. The action will:

  • Scan your repository for security issues
  • Post a detailed comment on pull requests
  • Fail the check if critical findings are detected

CLI

pip install git+https://github.com/agentgraph-co/mcp-security-scan.git

# Scan any MCP server repo on GitHub
mcp-security-scan owner/repo

# Scan the current repo (auto-detects from git remote)
mcp-security-scan

# JSON output for programmatic use
mcp-security-scan owner/repo --format json

# Fail CI on critical findings
mcp-security-scan owner/repo --fail-on critical

Advanced Usage

Action Inputs

Input Description Default
repo GitHub repo to scan (owner/repo). Defaults to the current repository. Current repo
token GitHub token for API access ${{ github.token }}
fail-on Fail the check if findings at or above this severity: critical, high, or medium critical
format Output format: text, json, github github

Action Outputs

Output Description
trust-score Trust score from 0-100
findings-count Total number of security findings
critical-count Number of critical-severity findings
report Full scan report as JSON

Using Outputs in Your Workflow

jobs:
  security-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: agentgraph-co/mcp-security-scan@v1
        id: scan
        with:
          fail-on: high

      - name: Check trust score
        if: steps.scan.outputs.trust-score < 50
        run: echo "Trust score is below 50 — review findings"

Scanning a Different Repository

- uses: agentgraph-co/mcp-security-scan@v1
  with:
    repo: some-org/their-mcp-server
    token: ${{ secrets.GITHUB_TOKEN }}

CLI Flags

Flag Description Default
repo GitHub repo (owner/repo) Auto-detect from git remote
--token GitHub API token $GITHUB_TOKEN env var
--format Output format: text, json, github text
--output, -o Write JSON report to file --
--fail-on Exit code 1 if findings at this severity or above: critical, high, medium --

What It Scans

The scanner checks for 6 categories of security issues:

:key: Hardcoded Secrets (critical/high)

  • AWS access keys and secret keys
  • OpenAI, Anthropic, Google API keys
  • GitHub tokens, Slack tokens, Stripe keys
  • Private key blocks (RSA, etc.)
  • Generic API key and password assignments

:warning: Unsafe Execution (critical/high)

  • subprocess.run(), os.system(), os.popen() (Python)
  • shell=True in subprocess calls (Python -- critical)
  • eval(), exec() (Python/JS)
  • child_process, execSync (Node.js)
  • Command::new (Rust), exec.Command (Go)

:file_folder: Filesystem Access (medium/high)

  • Unrestricted file read/write operations
  • Path traversal patterns (../)
  • Recursive delete (shutil.rmtree, rimraf)

:satellite: Data Exfiltration (high/critical)

  • Outbound HTTP requests with sensitive data
  • Encoded data transmission patterns
  • Suspicious network calls in unexpected contexts

:detective: Code Obfuscation (high)

  • Base64-encoded code execution
  • Dynamic code generation patterns
  • Obfuscated variable names and control flow

:white_check_mark: Positive Security Signals (reduce risk)

  • Authentication and authorization checks
  • Input validation (Zod, Pydantic, JSON Schema)
  • Rate limiting
  • CORS configuration
  • Security headers (Helmet, CSP)

Example PR Comment

When the action runs on a pull request, it posts a comment like this:

MCP Security Scan Results

:white_check_mark: Trust Score: 85/100 (Good)

  • :white_check_mark: Credential Theft -- Clear
  • :white_check_mark: Data Exfiltration -- Clear
  • :warning: Unsafe Execution -- 2 findings
  • :white_check_mark: Filesystem Access -- Clear
  • :white_check_mark: Code Obfuscation -- Clear
Metric Value
Files scanned 45
Language Python
Positive signals Input validation, Rate limiting
Findings (2)
Severity Category Name File Line
high unsafe_exec subprocess.run src/tools.py 42
medium unsafe_exec os.popen src/utils.py 18

Trust Score

Each scanned repo receives a score from 0 to 100:

Factor Impact
Base score 70
Critical finding -15 each
High finding -8 each
Medium finding -3 each
Positive security signal +5 each
Has README +5
Has LICENSE +5
Has tests +5

Contributing

Found a false positive? Missing a detection pattern? PRs welcome.

Good first issues:

  • Add detection for more secret patterns (Twilio, SendGrid, etc.)
  • Reduce false positives on path traversal in test files
  • Add support for local directory scanning (not just GitHub repos)
  • Add SARIF output format for GitHub Code Scanning integration

License

MIT -- see LICENSE.


Built by AgentGraph -- trust infrastructure for AI agents.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mcp_security_scan-1.1.0.tar.gz (25.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mcp_security_scan-1.1.0-py3-none-any.whl (22.7 kB view details)

Uploaded Python 3

File details

Details for the file mcp_security_scan-1.1.0.tar.gz.

File metadata

  • Download URL: mcp_security_scan-1.1.0.tar.gz
  • Upload date:
  • Size: 25.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for mcp_security_scan-1.1.0.tar.gz
Algorithm Hash digest
SHA256 233c85299f675afbb188c7ca32cdb2a7863e101c0240fdf6ac589660692dca62
MD5 0d247cff329448cd288db60c988d31d2
BLAKE2b-256 5ffe4df5547db8148eb707e6fce9f42ae5fc33c4a0c9fed65668e71720f73e6f

See more details on using hashes here.

File details

Details for the file mcp_security_scan-1.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for mcp_security_scan-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a1ed471cf4c295dcffdd256a6a79cdda8f79d2f8b625f846fb30153d93b1157b
MD5 ef97c96838af66f49c94aef82728527c
BLAKE2b-256 c557ae8f29dd77898881ce9d9fdf0ddd95d57d4c854103f5f55af73336ce51f6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page