One scriptable CLI for web security testing: scanner, proxy, fuzzer, authorization testing, WAF analysis, link-hijack detection and recon.
Free where the equivalents are paid - by Pennacle Security.
We use Burp and ZAP every day. We also kept wanting three things they are not: a scanner we can script against in CI, findings that tell us how sure they are, and a codebase small enough to read in one sitting. Summit is that tool - v0.6, MIT, a single pip install summit-scanner away, built in the open.
Full documentation: pennacle-security.github.io/summit
Contents
- At a glance
- Quick start
- Proof, not promises
- Commands
- Feature notes
- Anti false positives and false negatives
- Check catalog
- How summit compares
- Roadmap
- Community and contributors
- Contributing and security
- Legal and license
At a glance
Capabilities that usually sit behind paid tooling, plus the scanning core:
| Capability | Summit | The usual route |
|---|---|---|
| Broken access control testing (BOLA/IDOR) | summit authorize |
Autorize-style add-on / paid workflows |
| Hidden parameter discovery | summit mine |
Param Miner-style add-on |
| OpenAPI-driven scanning | summit scan --openapi |
add-ons |
| WAF fingerprinting + bypass probing | built in | partial / add-ons |
| Broken-link hijack detection | built in | paid extension |
| SQLi, XSS, redirect, traversal, takeover, host header, CORS | built in | core scanners (free) |
| Recon chain: subfinder -> httpx -> nmap | summit recon |
manual gluing |
| Rate limiting, retries, JWT/encoder toolkit | built in | add-ons / paid |
| CI-ready, confidence-labelled findings | the whole point | paid automation |
Every finding carries a confidence label: confirmed (an observed fact) or potential (a heuristic). That distinction runs through the entire tool.
Quick start
pip install summit-scanner # from PyPI
# or from a git checkout:
git clone https://github.com/pennacle-security/summit.git
cd summit
pip install -e .
Python 3.10+. Then watch it work against a deliberately vulnerable local target:
python examples/vuln_app.py # terminal 1 - the target (127.0.0.1 only)
summit scan http://127.0.0.1:8765 # terminal 2 - the scan
A fuller pass on a real engagement looks like this:
summit recon target.com --json recon.json # subdomains -> hosts -> ports
summit scan https://target.com --depth 2 --rate 10 # crawl + all checks
summit scan --openapi api-spec.json # API: scan what the spec admits to
summit authorize https://target.com/admin?user=1 \
--role 'admin=Cookie: session=abc' \
--role 'user=Cookie: session=xyz' # BOLA/IDOR testing
Proof, not promises
Every claim on this page is reproduced by examples/evidence.py - it runs the demo target live, measures each feature, and prints PASS/FAIL with the real numbers. CI executes it on every push; a claim that stops holding fails the build.
Latest measured run (python examples/evidence.py)
[PASS] full scan: 16 seeded check families detected, zero false positives
53 findings in 22.9s (344 requests), missing=none, control link flagged=no, 19 finding(s) carry confidence=confirmed
[PASS] resource takeover fingerprint detected on the target's own 404
Possible AWS S3 resource takeover | AWS S3: 'nosuchbucket'
[PASS] host header injection: marker domain echoed back by the app
Host: summit-host-probe.example -> reflected (reset-link poisoning surface)
[PASS] CORS reflects an arbitrary origin with credentials allowed
ACAO: https://summit-cors-probe.example; ACAC: true
[PASS] WAF bypass: naive filter blocks, tampered payload lands decoded
raw payload -> HTTP 403 (blocked); URL-encoded once -> HTTP 200, payload reflected decoded: True
[PASS] CAPTCHA challenge detected (reported, not solved)
/login -> reCAPTCHA via marker 'recaptcha/api.js'
[PASS] rate limiting: --rate 5 paces 12 requests to ~2.2s; unlimited runs free
12 requests at rate 5 -> 2.20s (theoretical floor: 2.2s); 12 requests unlimited -> 0.02s
[PASS] concurrency on a latency-bearing target: 8 workers vs serial
40 requests x 25ms latency: serial 1.33s -> parallel 0.18s (7.3x speedup)
[PASS] smart prioritizer ranks known-injectable parameters first
probing starts with: [('query', 'search?query=laptop'), ('id', 'user?id=1'), ('url', 'example.com')]
[PASS] toolkit decodes JWT header/payload and states the signature is unverified
signature NOT verified - decoding only
[PASS] update check compares versions numerically (0.3 < 0.10)
is_outdated('0.3.0', '0.10.0') -> True; is_outdated('1.0.0', '0.9.9') -> False
[PASS] broken access control: admin panel served identically to a low-privilege role
verdict=broken; finding=Broken access control (BOLA/IDOR candidate)
[PASS] hidden parameter mining finds the undocumented debug parameter, zero noise
1 finding(s): ['debug'] (all confirmed reflections)
[PASS] openapi-driven scan: spec alone leads the engine to seeded SQLi and XSS
2 spec target(s) scanned -> 10 findings, sqli-error=yes, xss-reflection=yes
[PASS] OS command injection: marker executed and echoed by the server
semicolon: exec marker x2, control marker x1 | CWE-78
[PASS] server-side template injection: {{7*7}} came back as 49
Jinja2/Twig: {{7*7}} -> 49 | CWE-1336
[PASS] CRLF injection: X-Summit-CRLF header materialized in the response
X-Summit-CRLF: injected | CWE-113
[PASS] sensitive file exposure: /.env confirmed by content signature
content signature: 'APP_KEY=' | CWE-538
[PASS] CVE detection: Apache/2.4.49 banner maps to known CVEs
detect_cves('Apache/2.4.49') -> ['CVE-2021-41773', 'CVE-2021-42013']
evidence summary: 19/19 claims verified
A visual of a real scan against the demo target:
Reproduce everything yourself:
python examples/vuln_app.py # terminal 1 - the target
summit scan http://127.0.0.1:8765
python examples/evidence.py # re-verify every claim above
The demo seeds a healthy outbound link (https://example.com) as a negative control - it must never be reported, and CI asserts that alongside the seeded detections. Found something wrong anyway? Report it.
Commands
| Command | What it does |
|---|---|
summit scan <url> |
crawl, then passive + active checks, link health, WAF analysis. --openapi scans a spec instead of crawling. --json / --html reports. |
summit authorize <url...> |
BOLA/IDOR testing: compare responses between two roles. |
summit mine <url> |
hidden parameter discovery (~70 candidates, marker-based). |
summit fuzz <url> |
directory brute force with wildcard-baseline filtering. |
summit recon <domain> |
chain subfinder -> httpx -> nmap into one report. |
summit tls <host> |
certificate expiry / self-signed / legacy TLS version audit. |
summit proxy |
intercepting HTTP proxy with a SQLite site map. |
summit repeater <file> |
send a raw request file (Burp-style). |
summit encode / summit decode |
base64, URL, hex, JWT (decode-only, honestly unverified). |
summit --check-update / --auto-update / --install-tools |
versioning and recon tool installer. |
Shared flags on scanning commands: --workers, --rate (requests/second ceiling), --retries (with Retry-After support), --timeout, --delay.
Feature notes
Authorization testing. Requests each URL as a privileged and a low-privilege role, then compares. Verdicts: enforced (roles differ), broken (identical response for the low-privilege role - critical, confirmed), partial (same status, different body - potential). Measured on the demo: the admin panel serves salaries to both roles, caught as confirmed.
Hidden parameter mining. Servers read parameters the HTML never mentions - debug switches, feature flags, internal overrides. ~70 candidate names are probed with unique markers; reflection findings are confirmed, status/size shifts are potential. Measured: the demo's undocumented debug switch found as confirmed, the other candidates silent - zero noise.
OpenAPI-driven scanning. Every documented endpoint becomes a target, with path params filled from examples and defaults - no crawling, no guessing. Measured: the spec alone leads the engine to the seeded SQLi and XSS. JSON and YAML specs are read natively.
WAF detection and bypass. Tight vendor signatures for Cloudflare, AWS WAF, Akamai, Imperva, ModSecurity, Sucuri, F5 and Wordfence. When a filter blocks standard payloads, tamper variants (single/double URL-encoding, comment splitting, case alternation) are tried - and a bypass is reported only when the original payload lands decoded in the response. Measured: raw payload -> HTTP 403; encoded once -> HTTP 200, decoded.
OS command injection, SSTI, CRLF, sensitive files. New in v0.6, each with a hard confirmation rule: OS command injection uses an exec marker plus a control probe (a server that merely reflects input shows both markers; a server that executes shows the exec marker more often - measured x2 vs x1), SSTI requires {{7*7}} to come back as 49, CRLF requires our injected header to materialize, and sensitive files (.env, .git/config, backups) require a content signature - never just a 200. Every finding is tagged with its CWE automatically (CWE-78, CWE-1336, CWE-113, CWE-538), and version banners are matched against an offline CVE database (spoofable banners stay potential).
CAPTCHA: detect, do not solve. reCAPTCHA, hCaptcha, Cloudflare Turnstile and challenge pages are detected and reported. Solving them automatically is out of scope by design - that line does not move.
Broken-link hijacking. Every outbound link is health-checked: dead domains (DNS verified twice), parked domains (tight fingerprints), broken links (404/410), unreachable hosts, and private-target links - recorded but never fetched, so a hostile page cannot weaponize your scanner as an SSRF probe.
Resource takeover fingerprints. A 404 answered with a provider's unclaimed-resource page (AWS S3, GitHub Pages, Heroku, Azure, Shopify, Fastly, Pantheon, Tumblr, Surge, Bitbucket) is a takeover setup. Fingerprint-only: no DNS tricks, no active claiming, ever.
Recon orchestration. subfinder -> httpx -> nmap, whichever are installed, with defensive parsing: passive-DNS noise capped, per-tool timeouts degrade into notes, and a crashed nmap is reported as failed - never as "no open ports".
Rate limiting and prioritization. --rate is a thread-safe requests/second ceiling (measured: 12 requests paced to 2.20s at rate 5; 0.02s unlimited). A transparent scoring model orders high-signal parameters first - deterministic and auditable, deliberately not a "neural network" claim.
Toolkit and updates. JWT decode with an honest "signature NOT verified" note, base64/URL/hex both directions, numeric version comparison against GitHub releases (0.3 < 0.10), self-update from a git checkout.
Anti false positives and false negatives
False positives waste your triage time. False negatives get clients breached. Summit engineers against both, and the evidence runner proves it:
| Mechanism | What it kills |
|---|---|
| Two-stage XSS check - a unique canary goes first; payloads only fire on parameters that actually reflect | payload noise on parameters that never reflect |
| Baseline diffing - every probe compared against the same request untouched | error strings already sitting in the page |
Divergence + baseline match (boolean SQLi) - AND 1=1 must match the baseline, AND 1=2 must differ |
pages that simply vary per request |
| Wildcard baseline (fuzzer) - a random nonexistent path is measured first | "everything returns 200" servers flooding the report |
| DNS double-check (linkcheck) - a host must fail to resolve twice | transient resolver hiccups becoming fake hijack reports |
| SSRF guard - private/link-local/metadata ranges recorded, never fetched | your scanner weaponized against internal networks |
| Tamper honesty (WAF bypass) - requires the payload decoded in the response | bypass reports that would not survive a browser |
Tracker/opaque param filter - utm_*, fbclid, 40+ char tokens never probed |
wasted requests and padded reports |
| Negative control in CI - a healthy link that must stay unreported, asserted every push | silent regressions into false-positive territory |
| Scope lock - the spider never leaves the target host | crawling half the internet, and legal exposure |
| Confidence labels - fact vs heuristic, on every finding | one flat "everything is critical" triage queue |
Unbreakable probe hosts - .example cannot resolve |
third-party callbacks and accidental DoS |
Check catalog
| Check | Type | Severity | Confirmation basis |
|---|---|---|---|
| Missing security headers | passive | low | header absence |
| Cookie flags (Secure / HttpOnly / SameSite) | passive | low-medium | header parse |
| SQL error / stack-trace disclosure | passive | medium | baseline-diffed signatures |
| Server and tech version disclosure | passive | info | header parse |
| CORS wildcard with credentials | passive | low | header parse |
| Email exposure | passive | info | regex |
| WAF fingerprint | passive | info | tight vendor signatures |
| CAPTCHA / anti-bot challenge | passive | info | challenge markers, reported not solved |
| Resource takeover signature | passive | high | provider unclaimed-resource page on 404 -> confirmed |
| SQL injection, error-based | active | critical | fresh DB error vs baseline -> confirmed |
| SQL injection, boolean-based | active | critical | response divergence -> potential |
| SQL injection, time-based blind | active | critical | calibrated delay reproduced on every probe -> potential |
| GraphQL introspection enabled | passive-origin | low | real __schema payload -> confirmed |
| Reflected XSS | active | high | canary + raw payload reflection -> confirmed |
| WAF filter bypass | active | high | tampered payload lands decoded -> confirmed |
| Host header injection | active | high | marker domain echoed vs baseline -> confirmed |
| CORS origin reflection | active | high | arbitrary origin reflected + credentials -> confirmed |
| OS command injection | active | critical | exec marker outruns control marker -> confirmed, CWE-78 |
| Server-side template injection (RCE) | active | critical | {{7*7}} evaluates to 49 -> confirmed, CWE-1336 |
| CRLF injection / response splitting | active | high | injected header materializes -> confirmed, CWE-113 |
| Sensitive file exposure (.env, .git) | passive-origin | high | content signature, not just a 200 -> confirmed, CWE-538 |
| Known CVE in version banner | passive | high | offline CVE database match -> potential (banners spoof) |
| Open redirect | active | medium | 3xx Location to probe host -> confirmed |
| Path traversal | active | high | OS file indicators -> confirmed |
| Broken access control (BOLA/IDOR) | authorize | critical | identical response for low-privilege role -> confirmed |
| Hidden parameter (reflected) | mine | medium | unique marker reflected -> confirmed |
| Hidden parameter (behavior) | mine | low | status/size shift -> potential |
| Link to dead domain (hijack) | linkcheck | high | DNS failure, verified twice -> confirmed |
| Link to parked domain (hijack) | linkcheck | high | tight parking fingerprints -> confirmed |
| Broken outbound link | linkcheck | medium | HTTP 404/410 -> confirmed |
| Unreachable outbound link | linkcheck | low | fails after retry -> potential |
| Outbound link to private IP | linkcheck | info | DNS resolution -> confirmed, never fetched |
| TLS certificate expired / self-signed | tls | high-medium | certificate dates and issuer -> confirmed |
| Legacy TLS versions accepted | tls | medium | handshake completed with TLSv1.0/1.1 -> confirmed |
| Directory fuzz | fuzz | info | status + wildcard baseline |
How summit compares
| summit | ZAP | Burp Suite | |
|---|---|---|---|
| Price | free, MIT | free | paid core |
| UI | CLI + HTML/JSON reports | full GUI | full GUI |
| Scriptable in CI | yes, that is the point | add-ons | paid automation |
| Confidence-labelled findings | yes | partial | partial |
| Authorization testing (Autorize-style) | built in, scriptable | add-on | paid workflows |
| Hidden parameter mining (Param Miner-style) | built in | add-on | add-on |
| OpenAPI-driven scanning | built in | add-on | add-on |
| WAF detection + bypass probing | built in | partial | partial |
| Broken-link hijacking | built in | add-on | paid extension |
| Rate limiting | built in, thread-safe | add-on | paid |
| JWT/encoder toolkit | built in | add-on | built in |
| Takeover fingerprints, host header, CORS | built in | add-ons | add-ons |
| Codebase you can audit in an afternoon | ~3.6k lines | large | closed source |
| TLS-intercepting proxy | on the roadmap | yes | yes |
We are not trying to replace either of them. Summit is the small tool you drop into a pipeline or onto a VPS box, and the codebase you can actually read line by line.
Roadmap
- TLS interception in the proxy (generated CA)
- POST form and JSON body injection points
- Authenticated scanning (cookies, headers)
- CNAME-level subdomain takeover (DNS resolution + service verification)
- Plugin API for custom checks
- Request interception UI
Community and contributors
A repository that helps people back grows through word-of-mouth:
- Questions -> Q&A discussion - beginner questions welcome, answered gladly
- Ideas & roadmap votes -> Ideas
- Show what you scanned -> Show and tell
- Your first contribution -> good first issues come with step-by-step instructions
- First issues and PRs get a personal review and a spot below; the welcome bot says hello too
If summit saved you time on an engagement, a star helps the next person find it.
SakarPaisen 💻 |
mrvi0 💻 |
Contributing and security
PRs welcome - the contributing guide covers the process, and adding a scan check is roughly thirty lines if you follow the pattern. examples/vuln_app.py gives you a live target to test against.
Security issues go through private disclosure only. Details in the security policy.
Legal and license
Summit is built for authorized security testing: your own systems, or systems you have written permission to test. We are not responsible for misuse. Licensed under MIT.
Metadata
Release files for summit-scanner 0.7.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| summit_scanner-0.7.1.tar.gz | 84.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| summit_scanner-0.7.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 170.0 kB
Release files / summit_scanner-0.7.1.tar.gz
| Download URL | summit_scanner-0.7.1.tar.gz |
|---|---|
| Size | 84.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
52435e0a2b14f89c95a927a4e8b832608919eed74e6b4bdc4a477ed7503669bc
|
|
BLAKE2b-256 checksum How to use checksums |
1fbc46ee05036df27892d79c57643a4abe7c3917e8f87bb22f5c856d24e0d5be
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.
Transparency logRelease files / summit_scanner-0.7.1-py3-none-any.whl
| Download URL | summit_scanner-0.7.1-py3-none-any.whl |
|---|---|
| Size | 85.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4a2fd560a66b25ffeecf9c569859be46cb7800fee78745474e8436a549ea7f29
|
|
BLAKE2b-256 checksum How to use checksums |
c05396922d09d788aeca3e8da4b4308c22d21bfd8685c27dd9158e4eb5af4c89
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.
Transparency log