Metadata-Version: 2.4
Name: shrike-scanner
Version: 1.0.0
Summary: Payment security engine for Stripe and Razorpay workflows
License-Expression: BUSL-1.1
Project-URL: Homepage, https://shrike.pro
Project-URL: Repository, https://github.com/NANIEXISTS/shrike
Project-URL: Bug Tracker, https://github.com/NANIEXISTS/shrike/issues
Keywords: stripe,razorpay,paypal,security,sast,payment,scanner,pci-dss
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Environment :: Console
Classifier: Operating System :: OS Independent
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: click>=8.1
Requires-Dist: Jinja2>=3.1
Requires-Dist: PyYAML>=6.0
Requires-Dist: rich>=13.0
Requires-Dist: PyNaCl>=1.5
Provides-Extra: ai
Requires-Dist: litellm>=1.0; extra == "ai"
Provides-Extra: pdf
Requires-Dist: weasyprint>=60.0; extra == "pdf"
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0; extra == "dev"
Requires-Dist: black; extra == "dev"
Requires-Dist: ruff; extra == "dev"
Requires-Dist: mypy; extra == "dev"
Provides-Extra: ast
Requires-Dist: tree-sitter; extra == "ast"
Requires-Dist: tree-sitter-javascript; extra == "ast"
Requires-Dist: tree-sitter-typescript; extra == "ast"
Provides-Extra: server
Requires-Dist: aiosqlite>=0.20; extra == "server"
Requires-Dist: asyncpg>=0.29; extra == "server"
Requires-Dist: boto3>=1.34; extra == "server"
Requires-Dist: fastapi>=0.115; extra == "server"
Requires-Dist: python-multipart>=0.0.9; extra == "server"
Requires-Dist: slowapi>=0.1.9; extra == "server"
Requires-Dist: sqlalchemy>=2.0; extra == "server"
Requires-Dist: uvicorn>=0.30; extra == "server"
Dynamic: license-file

<p align="center">
  <img src="https://shrike.pro/logo.svg" alt="Shrike" width="120" />
</p>

<h1 align="center">Shrike — Payment Security Scanner</h1>

<p align="center">
  <strong>593 rules. Stripe, Razorpay, PayPal. One command.</strong><br/>
  Find idempotency bugs, webhook signature bypasses, float currency errors, leaked keys, and hundreds of other payment-specific vulnerabilities before they cost you money.
</p>

<p align="center">
  <a href="https://github.com/NANIEXISTS/shrike/actions/workflows/ci.yml"><img src="https://github.com/NANIEXISTS/shrike/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
  <a href="https://pypi.org/project/shrike-scanner/"><img src="https://img.shields.io/pypi/v/shrike-scanner?color=blue" alt="PyPI"></a>
  <a href="https://pypi.org/project/shrike-scanner/"><img src="https://img.shields.io/pypi/pyversions/shrike-scanner" alt="Python"></a>
  <a href="https://github.com/NANIEXISTS/shrike/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-BSL--1.1-blue" alt="License"></a>
</p>

---

## Why Shrike?

Generic SAST tools know nothing about payment APIs. They miss the bugs that actually cost money:

| What they miss | What Shrike catches |
|---|---|
| `amount: 19.99` passed as float | **CUR001** — Float currency causes rounding chargebacks |
| No idempotency key on PaymentIntent.create | **IDP001** — Duplicate charges on network retry |
| `constructEvent()` without raw body | **WHK003** — Webhook signature always fails |
| `sk_live_` in client-side bundle | **SEC001** — Secret key exposed to browsers |
| Redirect-only checkout with no webhook | **CHK002** — Fulfillment never fires on bank delays |

Shrike has **593 rules** across **39 categories** covering Stripe, Razorpay, PayPal, PCI-DSS compliance, and cross-provider architecture patterns. Each finding includes a risk score, financial exposure estimate, and a concrete fix.

## Install

```bash
pip install shrike-scanner
```

Requires Python 3.10+. No external services needed — all scanning is local.

## Quick Start

```bash
# Activate your license
shrike activate <YOUR_LICENSE_KEY>

# Scan a project
shrike audit .

# Scan with financial exposure estimates
shrike audit . --mrr 50000

# Output SARIF for GitHub Security tab
shrike audit . --format sarif --output results.sarif

# Scan a public GitHub repo directly
shrike github https://github.com/stripe-samples/accept-a-payment
```

## Example Output

```
  ╔═╗╦ ╦╦═╗╦╦╔═╔═╗  vMAX
  ╚═╗╠═╣╠╦╝║╠╩╗║╣   593 Rules · Payment Security Scanner
  ╚═╝╩ ╩╩╚═╩╩ ╩╚═╝  shrike.pro/cli

Scanning: ./src  Rules: 593

[✗] SEC001 · CRITICAL  [CERTAIN]  Stripe Secret Key Exposed
  Location:  src/api/stripe.ts:14
  Category:  Secrets         CWE-798
  Snippet:   const stripe = new Stripe("sk_live_51H...")
  Risk:      Live secret key in source — full account access if leaked
  Exposure:  UNLIMITED — account compromise possible
  Fix:       Move to environment variable: process.env.STRIPE_SECRET_KEY

[!] IDP001 · HIGH  [LIKELY]  Missing Idempotency Key
  Location:  src/api/checkout.ts:47
  Category:  Idempotency     CWE-834
  Snippet:   await stripe.paymentIntents.create({ amount, currency })
  Risk:      Network retries can create duplicate charges
  Exposure:  $500–$10,000 / month
  Fix:       Add idempotencyKey: `pi_${orderId}` to the create() call

╭──────────────────────────────────╮
│          AUDIT SUMMARY           │
├────────────────────────┬─────────┤
│ Target                 │   ./src │
│ Files Scanned          │      47 │
│ Duration               │   340ms │
│ ──────────────────────── ──────── │
│ CRITICAL               │       1 │
│ HIGH                   │       3 │
│ MEDIUM                 │       5 │
│ LOW                    │       2 │
│ ──────────────────────── ──────── │
│ TOTAL                  │      11 │
│ Risk Score             │  58/100 │
│ Est. Monthly Exposure  │ ~$4,200 │
╰────────────────────────┴─────────╯
```

## GitHub Action

Add Shrike to your CI pipeline — findings appear in the **GitHub Security tab** via SARIF.

```yaml
# .github/workflows/shrike.yml
name: Payment Security
on: [push, pull_request]

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: NANIEXISTS/shrike@v1
        with:
          shrike_token: ${{ secrets.SHRIKE_TOKEN }}
          fail_on: HIGH        # block merges on HIGH+ findings
          engine: 5            # max depth (1=fast, 5=thorough)
```

### Action Inputs

| Input | Default | Description |
|---|---|---|
| `shrike_token` | *(required)* | License key — set as repository secret |
| `target` | `.` | Directory or file to scan |
| `fail_on` | `HIGH` | Minimum severity to fail the build (`CRITICAL`, `HIGH`, `MEDIUM`, `LOW`, `NONE`) |
| `engine` | `5` | Scan depth (1 = fast regex, 5 = full taint analysis) |
| `upload_sarif` | `true` | Upload results to GitHub Security tab |
| `mrr` | — | Monthly revenue (USD) for exposure estimates |

### Action Outputs

| Output | Description |
|---|---|
| `sarif_path` | Path to generated SARIF file |
| `findings_json` | Path to full JSON findings |
| `risk_score` | Numeric risk score (0–100) |

## CLI Reference

```
shrike audit <TARGET>       Scan a codebase for payment vulnerabilities
shrike github <URL>         Clone + scan a public GitHub repo
shrike analyze <FILE>       Forensic analysis of a webhook payload
shrike watch <LOG>          Live-monitor webhook logs
shrike rules                List all detection rules
shrike activate <KEY>       Activate license
shrike license status       Check license status
shrike license deactivate   Free a device seat
shrike config set <K> <V>   Set AI/config options
shrike config show          Show current configuration
```

### Key Flags

```
--format   terminal | json | html | pdf | sarif | all
--output   Output file stem (or "-" to pipe JSON/SARIF to stdout)
--mrr      Monthly revenue for exposure calculation
--fail-on  Exit code 1 if findings at this severity or above
--engine   Scan depth: 1 (regex) → 3 (taint) → 5 (cross-file + LLM)
--workers  Parallel scan workers (default: all CPUs)
--baseline Path to baseline JSON — report only new findings
```

## Docker

```bash
docker run --rm -v $(pwd):/src ghcr.io/naniexists/shrike:latest audit /src
```

## Output Formats

| Format | Use Case |
|---|---|
| `terminal` | Human-readable CLI output |
| `json` | Machine-readable, CI integration, baseline diffing |
| `sarif` | GitHub Security tab, VS Code SARIF Viewer |
| `html` | Shareable report with risk scores |
| `pdf` | Stakeholder/compliance reporting (requires `pip install shrike-scanner[pdf]`) |

## Rule Categories

| Provider | Categories |
|---|---|
| **Stripe** | Secrets, Idempotency, Webhooks, Payments, Subscriptions, Connect, Currency, Checkout, Refunds, Customers, SCA |
| **Razorpay** | Secrets, Webhooks, Payments, Subscriptions, UPI, RazorpayX |
| **PayPal** | Secrets, Webhooks, Payments, Config, Subscriptions |
| **Compliance** | PCI-DSS, RBI, EU PSD2 |
| **Cross-Provider** | Architecture, Logging, Race Conditions, Frontend, Infrastructure, Error Handling |
| **Frameworks** | Next.js, Express, Django, Flask, Rails, Laravel, Go, Slim |

## AI-Powered Fixes

With an API key, Shrike generates context-aware patches for critical findings:

```bash
shrike config set openai_api_key sk-...
shrike audit . --ai-patches
```

Supports OpenAI, Anthropic, and Google Gemini. Code snippets are sent to the LLM — you'll be prompted for consent.

## Architecture

```
shrike audit .
    │
    ├── File Discovery ──→ language detection, .shrikeignore, size limits
    ├── Relevance Filter ──→ payment-signal matching (skip non-payment files)
    ├── L1: Regex Rules ──→ 593 pattern rules with context windows
    ├── L3: Taint Analysis ──→ AST-based data flow (tree-sitter)
    ├── L4: LLM Filtering ──→ false-positive suppression via AI
    ├── Deduplication ──→ two-tier: exact + LOW/INFO rollup
    ├── Cross-File Suppression ──→ e.g., CHK002 if webhook handler exists
    └── Report Generation ──→ terminal, JSON, HTML, PDF, SARIF
```

## License

[Business Source License 1.1](LICENSE) — free for non-production use and education. Commercial/production use requires a license from [shrike.pro](https://shrike.pro).

Changes to Apache 2.0 four years after each release.
