Hookwarden is a CLI tool designed to detect signature-verification bugs in webhook handler code, ensuring robust security for applications by identifying vulnerabilities efficiently.
Key Features:
Open-source: Transparent and community-driven development.
Local Operation: Functions without sending data off-machine, enhancing privacy and security.
Multi-language Support: Works with JavaScript/TypeScript and Python, catering to a wide range of projects.
Deterministic Results: Provides consistent findings across different environments.
CI/CD Integration: Seamlessly integrates into existing workflows for automated security checks.
Audience & Benefit:
Ideal for developers and security teams focused on maintaining secure applications. Hookwarden allows early detection of vulnerabilities, reducing risks in the development lifecycle. It ensures compliance with security standards without external dependencies.
Available via winget for easy installation, Hookwarden is a reliable tool for enhancing application security through proactive vulnerability management.
README
The only scanner laser-focused on webhook signature verification.
Local. Deterministic. Zero-network. JS/TS + Python + PHP + Go. Five minutes from npx to fix.
npx hookwarden scan ./your-app
No traffic leaves your machine. No telemetry. No SaaS sign-up required.
Every Sunday at 22:00 UTC, this repo's CI runs hookwarden against 45 popular open-source projects โ currently cal.com, documenso, formbricks, twenty, plane, unkey, typebot, papermark (full target list, combined โ 190k+) โ to prove the scanner works on real production code.
These are bugs in the webhook handlers that receive provider events โ flaws in the integrating projects' integration code, not in the providers' own SDKs or services.
Coverage note: the engine couldn't parse 238 files across the corpus (broken syntax or language features the parser doesn't model). Those are scan-coverage diagnostics โ not handler bugs โ and are excluded from the table above.
Hookwarden checks 11 rule classes across 21 providers โ most of the corpus handles webhooks correctly, hence the short list. The full rule catalog lives in the docs.
Per-target findings are never published before responsible disclosure โ see methodology. To run the same scan against your own code:
npx hookwarden scan ./your-app
Why
Every dollar of fraud that flows through a webhook starts with a verification bug โ and verification bugs hide in plain sight.
A handler that accepts an unsigned payload, compares HMACs with ==, or skips the signature check on a ?test=true path silently routes attacker traffic into your business logic. The bug is one line in a 50K-line app, and it looks plausible โ not the shape general-purpose SAST tools are tuned to flag. They were built for SQL injection and prototype pollution; webhook verification falls between their default rule packs.
hookwarden does one thing. It walks your repo, parses every webhook handler across 11 frameworks, and labels each one verified, not-verified, or manual-review โ with the exact file, line, and a fix quoted from provider docs. The catalog (21 named providers โ Stripe, GitHub, Shopify, Slack, Twilio, Square, Sentry, Zendesk, DocuSign, PagerDuty, Notion, Auth0, HubSpot, Intercom, Linear, Zoom, Calendly, Bitbucket, Mailchimp, Postmark, plus Standard Webhooks conformant providers like Clerk, Resend, Mux) encodes signature quirks no generic scanner has the surface area to know: Stripe's 5-minute timestamp tolerance, Slack's v0:${ts}:${body} scheme, Twilio's SHA-1 outlier.
The three-state verdict is not a hedge.manual-review is what you get when hookwarden can't prove safety or unsafety from the source alone โ a handler inside a middleware chain the analyzer couldn't unroll, say. It's how the false-positive rate stays honest (<5%, measured against a 200-repo OSS corpus). A tool that reports every gray area as a bug isn't a security tool; it's noise. โ How the verdict works
Install
npx hookwarden scan . # works everywhere, no install
> hookwarden is a CLI, not a library โ run it with npx hookwarden scan . or install globally with npm i -g hookwarden. (The plain npm i hookwarden that npm auto-suggests on the package page installs it as a local dependency, which isn't what you want for a command-line tool.)
Or install natively:
OS
Recommended
Alternates
Linux
brew install Hookwarden/tap/hookwarden
npm i -g hookwarden ยท pip install hookwarden ยท direct binary
Node 22+ is required for the npm/npx/macOS-brew paths; the standalone binaries (Linux x64/arm64, Windows x64) bundle the runtime. Direct binary downloads are intentionally unsigned (Gatekeeper / SmartScreen will warn) โ prefer brew / scoop / npm / pip, which verify by SHA-256. โ Install guide
Update
hookwarden --version # check what you have
Channel
Command
brew (macOS/Linux)
brew upgrade hookwarden
scoop (Windows)
scoop update hookwarden
npm (global)
npm i -g hookwarden@latest
pip
pip install -U hookwarden
npx (no install)
npx hookwarden@latest scan . โ @latest bypasses the npx cache
Rule pack versions move with the CLI (engine, rules, and CLI ship as a fixed group โ 0.7.5 everywhere). Pin in CI with npx hookwarden@0.7.5 scan . if you want byte-stable verdicts across runs.
Quickstart
# Scan โ no install required
npx hookwarden scan ./your-app
# Fail CI on high+ findings, machine-readable output
npx hookwarden scan ./your-app --fail-on high --format json
# Exit codes: 0 clean ยท 1 findings at threshold ยท 2 engine error ยท 3 config error ยท 4 parse coverage below floor
# Adopt on a non-greenfield repo โ accept existing findings, gate only NEW ones
npx hookwarden scan ./your-app --baseline write
npx hookwarden scan ./your-app --fail-on high
# List every detected webhook handler (no rules run) โ useful for audits
npx hookwarden inventory ./your-app
--diff-only, --provider stripe,github (phased rollout), --include/--exclude globs, --strict-suppressions, repo-level hookwarden.config.yaml, and more: npx hookwarden --help and the CLI docs.
Git history scan (--history)
By default scan only looks at your working tree. --history also walks the
git history โ including files that were committed then deleted before HEAD โ
so a secret that was force-pushed away is still found. It's off by default and
bounded to the last 1000 commits; narrow it with --since :
npx hookwarden scan --history # last 1000 commits
npx hookwarden scan --history --since v1.0.0 # since a tag/ref
npx hookwarden scan --history --since 2026-01-01
--history is fully open-source and never requires a token.
Live verification (--verify-secrets)
--verify-secrets checks whether a leaked API-key-class credential is still
alive by making a single read-only call to the secret's own provider
(Stripe / GitHub) directly from your machine โ hookwarden never sees the secret.
A live leak is escalated to critical; a dead (rotated/revoked) one is
downgraded to info. It's paid (team tier), off by default, and explicit
opt-in only.
# Mint a token from the dashboard (Settings โ CLI tokens) on a team workspace:
HOOKWARDEN_TOKEN=hw_โฆ npx hookwarden scan --verify-secrets
The credential is held in-memory only and redacted in all output.
The entitlement check transmits only your token โ never the secret.
A webhook signing secret (whsec_, GitHub webhook secret) is always
reported unverified โ no provider can confirm a signing secret's liveness.
Without a valid HOOKWARDEN_TOKEN, findings are reported unverified and no
provider call is made.
Auto-fix
hookwarden doesn't just name the fix โ it applies it. The fix subcommand mechanically rewrites the safety: safe subset across JS/TS, Python, PHP, and Go (covering timing-unsafe comparisons โ crypto.timingSafeEqual / hmac.compare_digest / hash_equals, and raw-body misuse). The other 188 rules are architectural and emit per-finding fix prose instead.
npx hookwarden fix ./your-app # dry-run โ prints a unified diff, writes nothing
npx hookwarden fix ./your-app --write # atomic staging, re-scan, then rename into place
Every rewrite lands in a staging dir and is re-scanned before replacing the original; the fixer never edits inside strings or comments. โ hookwarden fix ยท Safety levels
Real output
Captured verbatim โ each line is what you'll see in your terminal, not a mockup. One Express middleware bug produces three findings, because that single mistake violates three distinct invariants; fixing one (re-ordering the middleware) clears all three:
$ hookwarden scan ./your-app
ร critical server.js:10:1 stripe/express-middleware-ordering not-verified
Express webhook handler for Stripe has `express.json()` registered before the webhook route. JSON
middleware consumes the request body; by the time the Stripe handler runs, the raw bytes used for
HMAC are gone and `stripe.webhooks.constructEvent` cannot reproduce the signature.
fix โบ register `express.json()` AFTER the webhook route, OR mount `express.raw(...)` on the path only.
docs โบ https://docs.stripe.com/webhooks#verify-events
refs โบ https://expressjs.com/en/guide/using-middleware.html
https://www.svix.com/blog/common-failure-modes-for-webhook-signatures/
ร critical server.js:10:1 stripe/missing-signature-verification not-verified
Stripe webhook handler does not appear to verify the signature header before processing the event โฆ
ร critical server.js:10:1 stripe/raw-body-misuse not-verified
Stripe webhook handler reads the signature header but does not appear to receive the body as raw bytes โฆ
โโโโโโโโโโโโ
Found 3 critical ยท 0 high ยท 0 medium ยท 0 low ยท 0 info ยท 0 manual-review โ 1 webhook handler across 1 file
Scanned in 3 ms ยท 1 / 1 candidates parsed (100.0% coverage)
Glyph
Severity
SARIF level
Counts toward --fail-on?
ร
critical
error
yes
!
high
error
yes
โฒ
medium
warning
yes
ยท
low
note
yes
i
info
note
no โ informational (e.g. library-verified)
The state column is the three-state verdict. Output is also available as byte-stable JSON and SARIF 2.1.0 (round-trips through GitHub Code Scanning, dedupes via partialFingerprints). โ Output formats & JSON schema
Languages, frameworks & providers
4 languages ยท 15 frameworks ยท 21 providers ยท 230 rules ยท 100% cited. Every rule carries โฅ1 external citation (CWE / RFC / Svix / Stripe spec) alongside the provider's own docs โ auditors and reviewers can follow any finding back to a stable external source. JS/TS parse with Babel; Python, PHP, and Go with tree-sitter (WASM).
Language
Frameworks
JavaScript / TypeScript
Express ยท Hono ยท Fastify ยท Next.js
Python
Flask ยท FastAPI ยท Django
PHP
Laravel ยท Symfony ยท Slim ยท vanilla single-file
Go
net/http ยท chi ยท gin ยท echo
Every rule carries fix guidance quoted from the provider's canonical security docs. Full per-rule reference and coverage matrix: docs.hookwarden.dev/rules.
Finds hardcoded secrets; doesn't audit whether verification is correct
Datadog Static Analysis
Broad SAST; good cloud signal
No webhook specialization; low-signal for this bug class
hookwarden
Webhook verification logic only
230 rules (100% cited), 21 providers, three-state verdicts, <5% FP on a 200-repo corpus
hookwarden is not a general-purpose SAST or DAST scanner โ it won't find XSS, SQL injection, or memory-safety bugs, and it isn't trying to. Keep semgrep, CodeQL, or your DAST for those. Already running one? hookwarden is additive โ it finds the one class of bug they weren't built to catch.
AI agents (Claude Code, Cursor, Continue)
@hookwarden/mcp is a Model Context Protocol server that gives AI coding agents the scan_handler tool. Paste in any webhook handler, get back the same 3-state verdict (verified / not-verified / manual-review) the CLI would emit โ fully local, deterministic, no traffic leaves the agent's machine.
npx @hookwarden/mcp init # auto-detects Claude Desktop / Cursor / Continue and writes the config
The rule pack is bundled inline, content-hashed, and version-pinned to the engine โ scan_handler cross-checks both on every call and fails loudly on drift. โ @hookwarden/mcp on npm
Architecture
A pnpm monorepo with a strict, CI-enforced dependency boundary: the engine is pure-functional (no I/O, no filesystem, no network), so the same engine runs in the CLI, in CI, in the MCP server, and โ eventually โ in a browser playground without modification.
โ v0.4 โ PHP support (Laravel, Symfony, Slim, vanilla) + --provider filter for phased rollout.
Contributing
Rule-pack PRs are the highest-value contribution โ adding a provider is a catalog edit plus N rule YAMLs, no new TypeScript in most cases. See the existing 21 in packages/rules/rules/ as worked examples, and CONTRIBUTING.md.
pnpm install && pnpm -r build && pnpm -r test
Apache 2.0 โ see LICENSE. The CLI, engine, and rule packs are open source and will stay that way. A separate closed-source SaaS tier handles continuous monitoring, secret-leak scanning, automated rotation, and SOC 2 evidence export โ hookwarden.dev.