Skip to main content

CIPHER MCP Scan

Version 0.3 adds deterministic tool-metadata quality rules while preserving the five static checks and optional remote_oauth behavior.

CIPHER is a local static scan for MCP-oriented codebases. It inspects a checked-out project locally and runs five focused static checks: authentication, over-privilege, CVE lookup, typosquatting, and tool poisoning.

The tool_poisoning check examines MCP JSON tool metadata for instruction overrides, data-exfiltration requests, dangerous URI schemes, and hidden Unicode control characters. It is always included with the four static checks; remote_oauth remains separate and opt-in through --remote-url.

Findings include stable rule_id, detection_method, evidence, confidence, remediation, line ranges, and owasp_tags. The scanner remains static and deterministic by default; remote OAuth is the only opt-in active probe.

Modular API reports

The FastAPI service stores successful scan reports in reports/ beside modular_api.py by default. Set REPORTS_DIR to use a different directory. Existing reports from the legacy .cipher_reports/ location are not read automatically; move any files to reports/ once if they need to remain available.

On Render, set REPORTS_DIR to the mount path when using a persistent disk. Without a Render persistent disk, report files are ephemeral and do not survive redeploys. This API storage is separate from the CLI's local --output option.

Optional remote OAuth check

The fifth check is opt-in and runs only when an explicit remote URL is supplied. It probes OAuth well-known metadata, dynamic client registration, and a small set of redirect URI validation cases. It does not run during the normal cipher-scan . workflow or standard CI scans.

cipher-scan ./my-application --remote-url https://example.test/mcp --fail-on high

Remote connection failures are reported as low-severity transport results so static findings and the scan report are preserved. Only accepted dangerous redirect schemes produce high-severity remote findings. Use this check only against systems you are authorized to test; it is intended for lab and explicitly approved environments.

The remote OAuth probe is adapted from the concepts and minimal active probes in remote-mcp-scanner, copyright Nova Security, licensed under the MIT License. The reference project is not imported as a runtime dependency.

CIPHER's deterministic metadata rules were informed by invariantlabs-ai/mcp-scan, yatuk/mcpradar, sahiloj/MCPScan, alexandriashai/mcp-guardian, and bryand410/mcp-scrutiny. OAuth probe concepts were compared with novasecuritynz/remote-mcp-scanner. No vendor source is bundled or required.

Install

pip install cipher-mcp-scan

Use CIPHER directly in the CLI

  1. Install:
    pip install cipher-mcp-scan
    
  2. Check it works:
    cipher-scan --help
    
  3. Scan the current directory:
    cipher-scan . --fail-on high
    
  4. Scan a specific project path:
    cipher-scan path/to/project --fail-on high
    
  5. Report only without failing CI:
    cipher-scan . --fail-on none
    
  6. Write a JSON report:
    cipher-scan . --fail-on high --format json --output cipher-report.json
    
  7. Exit codes:
    • 0 = findings are below the selected threshold
    • 1 = findings are at or above the selected threshold
  8. --fail-on values:
    • critical
    • high
    • medium
    • none

Use CIPHER in GitHub Actions

Add a workflow in your project under .github/workflows/ and run the scanner after checkout. This works for public and private repos because the scan is local to the checked-out code.

Point to the demo file in this repo at examples/github-actions-cipher-scan.yml. You can copy that file into your repo as .github/workflows/cipher-scan.yml, or paste the workflow block below.

name: CIPHER MCP Scan

on:
  pull_request:
  push:
    branches:
      - main
      - master
  workflow_dispatch:

jobs:
  cipher-scan:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install CIPHER
        run: |
          python -m pip install --upgrade pip
          pip install cipher-mcp-scan

      - name: Run CIPHER scan
        env:
          GITHUB_STEP_SUMMARY: ${{ github.step_summary }}
        run: |
          cipher-scan . --fail-on high --summary github --output cipher-scan-report.json

      - name: Upload JSON report
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: cipher-scan-report
          path: cipher-scan-report.json
          if-no-files-found: ignore

To use it in another repo:

  1. Copy examples/github-actions-cipher-scan.yml to .github/workflows/cipher-scan.yml
  2. Or paste the block above into that file
  3. Open a PR or push to main/master to trigger the check

Optional flags

  • --summary github writes a markdown summary to the Actions job summary when available
  • --format text|json changes the output style
  • --output REPORT.json saves the machine-readable report

Short note

v0.1 is limited to the built-in CIPHER checks. Optional third-party compare engines are future work and are not required for this package.

Longer internal notes are preserved in README_ARCHIVE.md.

CLI UX

The command-line tool has a short banner on --help / -h and no noisy startup banner on successful scans. Example help output includes the package name, version, example commands, and a one-line fail-on explanation.

Local verification

Run these locally without uploading anything:

pip install -e .
cipher-scan --help
cipher-scan ./test/Cipher-demo-main --fail-on high

The demo path is useful for a quick smoke test because it includes intentionally vulnerable MCP sample code.

Production smoke test

After a Render deploy, run these three requests in order:

  1. curl -sS https://<your-render-host>/health and verify status is ok.
  2. curl -sS -X POST https://<your-render-host>/modularscan -H "Content-Type: application/json" -d '{"repo_url":"https://github.com/<owner>/<repo>"}' and verify the five static checks remain in checks_run, with grouped results and the additive normalized findings envelope.
  3. Repeat step 2 with ,"remote_url":"http://127.0.0.1:9" added to the JSON body. Verify the response remains status: "ok", includes remote_oauth, and records a low-severity transport finding without affecting static results.

Clients should poll /health before the first scan to accommodate Render cold starts.

Metadata

Release files for cipher-mcp-scan 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cipher-mcp-scan 0.3.0
File Size Uploaded Provenance Actions
cipher_mcp_scan-0.3.0.tar.gz 60.9 kB Without provenance Details for cipher_mcp_scan-0.3.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for cipher-mcp-scan 0.3.0
File Interpreter ABI Platform Actions
cipher_mcp_scan-0.3.0-py3-none-any.whl Python 3 none any Details for cipher_mcp_scan-0.3.0-py3-none-any.whl

Total release size: 122.7 kB

Release files / cipher_mcp_scan-0.3.0.tar.gz

Download URL cipher_mcp_scan-0.3.0.tar.gz
Size 60.9 kB
Tags Source
SHA-256 checksum
How to use checksums
65b65ef6ac56d9d8b40b1bef5ced2eb7dc137749efef4ec14f94824a4a6a1bb8
BLAKE2b-256 checksum
How to use checksums
ca53d78dc13897e25adff1a08c485968616eb236ab1f89454701392463153532
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.3

Release files / cipher_mcp_scan-0.3.0-py3-none-any.whl

Download URL cipher_mcp_scan-0.3.0-py3-none-any.whl
Size 61.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
cb600a4dcb6807b1106180621bc2283b748cec595df665b19b53d62262c65c20
BLAKE2b-256 checksum
How to use checksums
84a8f083e79dab931d7dbd5d36ae15b30b61818bcba8e330ca52004193bc1440
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.3

Security for cipher-mcp-scan 0.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page