Metadata-Version: 2.4
Name: cipher-mcp-scan
Version: 0.4.0
Summary: Local security scan CLI for Cipher checks
Author: Cipher
License: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: requests<3.0.0,>=2.31.0
Provides-Extra: test
Requires-Dist: pytest<9,>=8.2; extra == "test"
Requires-Dist: pytest-asyncio<1,>=0.24; extra == "test"

# CIPHER MCP Scan

Version 0.4 adds industrial finding metadata, richer CLI output, precision fixes, and a gating GitHub Actions workflow 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.

```bash
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](https://github.com/novasecuritynz/remote-mcp-scanner), copyright Nova Security, licensed under the MIT License. The reference project is not imported as a runtime dependency.

## Prior art / related tools

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

## Install

```bash
pip install cipher-mcp-scan
```

## Use CIPHER directly in the CLI

1. Install:
   ```bash
   pip install cipher-mcp-scan
   ```
2. Check it works:
   ```bash
   cipher-scan --help
   ```
3. Scan the current directory:
   ```bash
   cipher-scan . --fail-on high
   ```
4. Scan a specific project path:
   ```bash
   cipher-scan path/to/project --fail-on high
   ```
5. Report only without failing CI:
   ```bash
   cipher-scan . --fail-on none
   ```
6. Write a JSON report:
   ```bash
   cipher-scan . --fail-on high --format json --output cipher-report.json
   ```
7. Exit codes:
   - `0` = scan completed and policy is satisfied
   - `1` = findings are at or above the selected threshold
   - `2` = tool error, invalid path, or optional CVE hard-fail
8. `--fail-on` values:
   - `critical`
   - `high`
   - `medium`
   - `none`

## Use CIPHER in GitHub Actions

The repository includes [.github/workflows/cipher-scan.yml](.github/workflows/cipher-scan.yml).
It installs CIPHER locally, runs the human gate at `--fail-on high`, writes a JSON report,
and uploads that report as an artifact. The default job is gating: exit code `1` blocks the
workflow. No secrets are required for the static scan.

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](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.

```yaml
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](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
- `--json` emits machine-readable JSON only
- `--verbose` prints full evidence and detection metadata
- `--by-check` groups human findings by check
- `--no-color` disables ANSI color
- `--cve-fail-on-error` makes OSV infrastructure failures return exit code `2`
- `--output REPORT.json` saves the machine-readable report

The scanner is static evidence for human review, not proof of exploitability. It can produce
false positives or miss runtime behavior. CVE results depend on OSV availability. Review
findings before acting on them, and do not send private source code to an untrusted third-party
host without reviewing the deployment and data-handling risks.

For the optional pytest suite, install the pinned-compatible test tools with
`pip install -e ".[test]"`. The repository's `unittest` self-tests do not require pytest.

## Modular API quick check

```bash
curl -sS https://<your-render-host>/health
curl -sS -X POST https://<your-render-host>/modularscan \
  -H "Content-Type: application/json" \
  -d '{"repo_url":"https://github.com/<owner>/<repo>"}'
```

The default API request runs the five static checks in fixed order. `remote_url` is optional
and enables the remote OAuth probe only when explicitly supplied. The API is intended for
authorized deployments; review network exposure and authentication before using it with private
code.

## 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](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:

```bash
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.
