Metadata-Version: 2.4
Name: vigil-review
Version: 0.1.0
Summary: AI security review for every pull request — powered by Claude. Flags injection, secrets, authz bugs & more inline on the PR.
Project-URL: Homepage, https://github.com/nadirzhon/vigil
Project-URL: Repository, https://github.com/nadirzhon/vigil
Author: nadirzhon
License: MIT
License-File: LICENSE
Keywords: ai,anthropic,appsec,claude,code-review,devsecops,github-action,llm,pull-request,sast,security
Requires-Python: >=3.10
Requires-Dist: anthropic>=0.109
Requires-Dist: httpx>=0.27
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Description-Content-Type: text/markdown

<div align="center">

# 🛡️ Vigil

**AI security review for every pull request — powered by Claude.**

Vigil reads each PR's diff and flags injection, hard-coded secrets, broken authorization,
unsafe crypto, SSRF, XSS and more — as a report right on the pull request. Drop it into any
repo with one workflow file.

![CI](https://github.com/nadirzhon/vigil/actions/workflows/ci.yml/badge.svg)
![GitHub Action](https://img.shields.io/badge/GitHub-Action-2088FF?logo=githubactions&logoColor=white)
![Claude](https://img.shields.io/badge/Claude-Opus%205-8A63D2)
![License](https://img.shields.io/badge/License-MIT-green)

</div>

---

## Why

Human review catches design issues; it misses the boring, dangerous stuff — a secret pasted
into a config, a query built with string concatenation, a missing auth check. Vigil reads
**only the diff** on every PR and reports security-relevant defects before they merge, with a
severity, a confidence level, and a concrete fix. Two layers:

- **Deterministic secret scan** — fast regex pass over added lines (AWS/GCP/Stripe/GitHub
  keys, private keys, JWTs, generic `secret = "..."`), with placeholder filtering.
- **AI review** — Claude analyzes each changed file's diff for the OWASP-style weakness
  classes and returns structured findings.

## Quick start

Add `.github/workflows/security-review.yml` to your repo:

```yaml
name: Security review
on: pull_request

permissions:
  contents: read
  pull-requests: write   # so Vigil can post its report

jobs:
  vigil:
    runs-on: ubuntu-latest
    steps:
      - uses: nadirzhon/vigil@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
```

Add your key once at **Settings → Secrets and variables → Actions → `ANTHROPIC_API_KEY`**.
That's it — open a PR and Vigil comments with its findings.

## What a report looks like

> ## 🛡️ Vigil — security review
> Found **2** issue(s): 🟥 1 critical · 🟧 1 high
> > ❌ Blocking: at least one issue is **high** or higher.
>
> ### 🟥 Possible GitHub token committed — CRITICAL
> 🔑 `config/settings.py:14` · _hardcoded-secret_ · confidence: high
> A value matching a GitHub token pattern was added to `config/settings.py`.
> **Fix:** Remove the secret, rotate it immediately, and load it from an environment variable.
>
> ### 🟧 SQL injection via string formatting — HIGH
> 🤖 `api/users.py:42` · _injection_ · confidence: high
> The query interpolates `user_id` directly into SQL, allowing injection.
> **Fix:** Use a parameterized query instead of f-string interpolation.

## Inputs

| Input | Default | Description |
|-------|---------|-------------|
| `anthropic_api_key` | — (required) | Your Anthropic API key, from a repository secret |
| `github_token` | `${{ github.token }}` | Token to read the diff and post the report |
| `model` | `claude-opus-5` | Claude model id |
| `fail_on_severity` | `high` | Fail the check at this severity or higher: `none`/`low`/`medium`/`high`/`critical` |
| `max_files` | `50` | Max changed files to review |
| `comment_mode` | `summary` | `summary` (one PR comment) or `none` |
| `exclude` | `""` | Comma-separated globs to skip, e.g. `test/**,*.lock` |

**Output:** `findings_count` — total number of findings.

### Make it advisory (don't block merges)

```yaml
      - uses: nadirzhon/vigil@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          fail_on_severity: none
```

## How it works

1. Reads the `pull_request` event and fetches changed files (with patches) via the GitHub API.
2. Skips binaries, removed files, huge diffs, and non-code paths (and your `exclude` globs).
3. Runs the deterministic secret scan, then an AI review per file (structured JSON output,
   Claude's safety refusals handled gracefully).
4. Posts a single report comment (updated in place on new pushes) and writes the job summary.
5. Exits non-zero when a finding meets `fail_on_severity`.

Vigil never sends your whole repo anywhere — only the **diffs of changed files** are sent to
the Claude API for analysis.

## Development

```bash
uv pip install -e ".[dev]"
pytest          # 16 tests: secret scan, gating, report rendering, review parsing (mocked)
ruff check .
```

## Part of an AI × Security toolkit

- [offsec-mcp](https://github.com/nadirzhon/offsec-mcp) — MCP server giving AI agents offensive-security tools (recon, CVE, JS analysis)
- [specter](https://github.com/nadirzhon/specter) — autonomous AI recon agent that drives those tools end-to-end
- **vigil** — AI security review for every pull request · *(this repo)*
- [mcpscan](https://github.com/nadirzhon/mcpscan) — security scanner for MCP servers (tool poisoning, injection surfaces)
- [State of MCP Security](https://github.com/nadirzhon/state-of-mcp-security) — research: 87% of scanned MCP servers expose a medium+ hardening issue

## License

MIT — see [LICENSE](LICENSE). Findings are AI-assisted and may be imperfect; treat Vigil as a
fast first pass, not a replacement for human review.
