Pry
Pry logo

v0.1.1 · public beta

Pry

Prove it. Don't guess it.

Pry proves an app you own is exposed by actually trying the exploit, then captures a signed, replayable request/response pair. No pattern-matching verdicts. No "secure" claim.

quickstart

# install from PyPI (or: pipx install pry-scanner)
uv tool install pry-scanner

# local repo in a disposable Docker sandbox
pry scan ./my-app --report

# verify a signed proof offline
pry verify-proof ~/.pry/runs/<id>/proofs/<bundle>.json

Docker is required for local intake. A live URL needs a P1 ownership token first.

01 Why

The exploit is the verdict.

Most scanners say an endpoint looks risky. Pry makes the request that should have been blocked, captures what came back, and signs it. A heuristic may prioritize; only a reproduced pair may produce EXPOSED.

Execute, don't infer

A real GET, POST, or fetch against a target you own. If it did not reproduce, the result is NOT_REPRODUCED, never "safe".

Proof, not a screenshot

Every EXPOSED finding gets an Ed25519-signed bundle with the redacted request/response pair, a target snapshot, and a fingerprint you can pin.

Ownership before requests

DNS TXT or a well-known file gates live scans. Local repos run in an isolated sandbox with no run-phase egress. Higher intensity needs explicit confirmation.

02 What it checks

A graduated set, declared by the owner.

No route discovery by guessing. You declare the protected paths, object pairs, and endpoints. Pry reproduces the check and reports only what it could capture.

  • Missing authA declared protected path returns 2xx JSON with no credentials.
  • Configured IDORTwo identities, two objects, both controls, and an A→B cross-request.
  • SSRFLocal callback sidecar or a live user-owned callback; only a hit is EXPOSED.
  • Rate limitsA bounded local/live observation. Never a verdict; stops on the first throttle.
  • HeadersOpt-in missing/present recommended headers. Unsigned, hardening-only.
  • Secrets and filesFixed secret paths and served SQLite/SQL dumps with a signature excerpt only.
  • Provider DB rulesFirebase RTDB and Supabase with a user-placed marker and one declared data path.
  • Level 2 writesOne declared write plus a marker verification read; live writes need an extra confirmation.
  • Proof and reportSigned bundles, offline verification, read-only replay, HTML report, JSONL corpus.

03 The verdicts

There is no safe verdict.

  • EXPOSED

    A real exploit was reproduced at or below the authorized intensity. The proof bundle is the evidence.

  • NOT_REPRODUCED

    The declared check did not reproduce. Absence of proof is not proof of absence.

  • UNVERIFIED

    Pry could not test: ownership unproven, target unreachable, or the intensity was too low.

04 In action

A real local run.

The vulnerable fixture produces four findings, writes signed proofs, and opens an HTML report. This is a real terminal capture, not a mockup.

Four EXPOSED findings, an HTML report, and a proof that verifies offline. Open the MP4 full size.

05 Status & limits

Public beta, honest scope.

In 0.1.1

Ownership gate, local sandbox, read-only floor, configured IDOR, local/live SSRF, rate-limit observations, headers, database files, provider DB rules, local/live Level 2 writes, signed proofs, replay, report, and corpus.

Not in 0.1.1

IDOR and endpoint discovery, hosted reports, and platform partnerships. Discovery by guessing is deliberately out of scope.

Safety model

Live targets need ownership proof. Read-only is the default. Level 1 and Level 2 need explicit confirmation. Credentials are 0600 and redacted. Live writes can alter real data and are not rolled back.

License

Apache-2.0. Self-hostable OSS; no upload or telemetry by default. The proof key stays local.

06 Install

One command, then scan.

install

# install from PyPI
uv tool install pry-scanner

# fallback: from the v0.1.1 tag
uv tool install "pry-scanner @ git+https://github.com/haqaliz/pry@v0.1.1"

# local repo, read-only floor
pry scan ./my-app --report

# live target: prove ownership first
pry verify-ownership https://your-app.example --method dns
pry scan https://your-app.example --token <token>

Read the README, architecture, roadmap, and ethics. For a vulnerability in Pry itself, use the private advisory.