npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

hookwarden

v0.4.0

Published

Webhook security audit CLI — finds signature-verification bugs in JavaScript, TypeScript, Python, and PHP codebases. Local, deterministic, zero-network. Ships rules for Stripe, GitHub, Shopify, Slack, Twilio, and Square; JSON / SARIF 2.1.0 output for CI a

Readme

npx hookwarden scan ./your-app

No traffic leaves your machine. No telemetry. No SaaS sign-up required.


Contents


Why

Every dollar of fraud loss 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 will silently route attacker traffic into your business logic. The bug is one line of code in a 50K-line app, and the code looks plausible — not the shape general-purpose SAST tools are tuned to flag. They were built to catch 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 Express, Hono, Fastify, Next.js, Flask, FastAPI, Django, Laravel, Symfony, Slim, and vanilla-PHP single-file handlers, and labels each one verified, not-verified, or manual-review — with the exact file, line, and a fix drawn verbatim from provider documentation. That focus is the entire point. The provider catalog (Stripe, GitHub, Shopify, Slack, Twilio, Square — and growing) encodes signature-format quirks no generic scanner has the surface area to know: that Stripe uses HMAC-SHA256 with a 5-minute timestamp tolerance, that Slack uses v0:${ts}:${body} not raw-body, that Twilio is the SHA1 outlier the rest of the catalog has to accommodate.

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 that the analyzer couldn't fully unroll, for example. It's how the false-positive rate stays honest. A tool that reports every gray area as a bug is not a security tool; it's noise.


🌐 Languages & frameworks

3 languages, 11 frameworks. PHP and Python use tree-sitter (WASM); JS/TS use Babel.

| Language | Frameworks | Parser | |---|---|---| | JavaScript / TypeScript | Express · Hono · Fastify · Next.js | @babel/parser | | Python | Flask · FastAPI · Django | tree-sitter-python | | PHP | Laravel · Symfony · Slim · vanilla-PHP single-file | tree-sitter-php |

PHP 8.0+ syntax floor. Python 3.10+ recommended.


🚀 Quickstart

First use — no install required:

npx hookwarden scan ./your-app

Make CI fail on high+ findings:

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

PR-scoped scan + CI gate:

npx hookwarden scan ./your-app --diff-only --diff-base origin/main --fail-on high

Upload to GitHub Code Scanning:

npx hookwarden scan ./your-app --format sarif > findings.sarif
gh api -X POST /repos/$REPO/code-scanning/sarifs \
  -F [email protected] -F ref=$GITHUB_REF

Non-greenfield adoption — accept existing findings, gate only NEW ones:

npx hookwarden scan ./your-app --baseline write
git add .hookwarden.baseline.json && git commit -m "chore: hookwarden baseline"
# Subsequent scans auto-read the baseline; only new findings are reported.
npx hookwarden scan ./your-app --fail-on high

List every detected handler (no rule evaluation):

npx hookwarden inventory ./your-app

Phased rollout — gate CI on one provider at a time:

npx hookwarden scan ./your-app --provider stripe --fail-on high
# Comma-separated for multiple: --provider stripe,github

Monorepo scoping — exclude / include paths from the command line:

npx hookwarden scan ./your-app --exclude 'packages/legacy/**,vendor/**'
npx hookwarden scan ./your-app --include 'packages/api/**'
# Both compose: --include narrows first, --exclude removes after.

Strict suppressions (compliance teams):

npx hookwarden scan ./your-app --strict-suppressions

Or install permanently:

npm install -g hookwarden          # global
npm install --save-dev hookwarden  # dev dependency (CI-pinnable)

Full flag reference: npx hookwarden --help.


Real output

Clean scan — exits 0:

hookwarden scan ./your-app

✓  Scanned 24 candidates · 24 parsed (100.0% coverage) · 0 findings

Scan with a bug — exits 1:

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.

    Fix: register `express.json()` AFTER the webhook route, OR mount
    `express.raw({ type: 'application/json' })` only on the webhook path.
    ↳ https://stripe.com/docs/webhooks/signatures

HIGH
────

  handlers/slack.ts:34:1
    slack/missing-timestamp-validation  [not-verified]
    Slack handler does not enforce the 5-minute replay window. The
    `X-Slack-Request-Timestamp` header is present but not compared against
    the current time before signature verification proceeds.

    Fix: reject requests where abs(Date.now()/1000 - ts) > 300 before
    computing the `v0:${ts}:${body}` signing string.
    ↳ https://api.slack.com/authentication/verifying-requests-from-slack

────────────
Found 1 critical · 1 high · 0 medium · 0 low · 0 info · 0 manual-review
Scanned in 0.3 s · 24 / 24 candidates parsed (100.0% coverage)

JSON envelope shape:

{
  "schema_version": "1.0",
  "engine": { "version": "0.2.0", "commit_sha": null },
  "rule_pack": { "version": "0.2.0", "content_hash": "51c219..." },
  "scan": {
    "counts": {
      "active":     { "critical": 1, "high": 1, "medium": 0, "low": 0, "info": 0 },
      "suppressed": { "critical": 0, "high": 0, "medium": 0, "low": 0, "info": 0 }
    },
    "findings": [
      {
        "rule_id": "stripe/express-middleware-ordering",
        "severity": "critical",
        "state": "not-verified",
        "provider": "stripe",
        "file_path": "server.js",
        "location": { "line": 10, "col": 1 },
        "finding_id": "stripe/express-middleware-ordering@d603a04...",
        "primary_location_line_hash": "d603a04...",
        "message": "Express webhook handler for Stripe has...",
        "redacted_snippet": "app.use(express.json())\napp.post('/webhook', ...",
        "suppressed": null
      }
    ],
    "scanned_at": "2026-05-05T18:31:33.653Z",
    "parsed_files_count": 1,
    "parse_candidates_count": 1
  },
  "suppressions": { "applied": [], "stale": [] }
}

Sorted keys, schema-versioned, byte-stable across runs (modulo scanned_at). SARIF output round-trips through GitHub Code Scanning and deduplicates via partialFingerprints on re-upload.


🔐 Provider coverage

45 rules across 6 providers as of v0.4. Every rule carries fix guidance quoted verbatim from the provider's canonical security documentation.

| Provider | Rules | Detection types | Custom predicate | |---|---|---|---| | Stripe | 9 | missing-sig-verif, timing-unsafe, raw-body, missing-timestamp, wrong-hmac, unreachable-verif, hardcoded-secret (whsec_), library-verified | — | | GitHub | 9 | missing-sig-verif, timing-unsafe, raw-body, missing-timestamp, wrong-hmac, unreachable-verif, hardcoded-secret (ghs_, github_pat_), library-verified | — | | Shopify | 7 | missing-sig-verif, timing-unsafe, raw-body, missing-timestamp (info), wrong-hmac, unreachable-verif, library-verified | — | | Slack | 7 | missing-sig-verif, timing-unsafe, raw-body, missing-timestamp (high), wrong-hmac, unreachable-verif, library-verified | Parameterized timestamp_dot_body recipe | | Twilio | 7 | missing-sig-verif, timing-unsafe, raw-body, missing-timestamp (info), wrong-hmac, unreachable-verif, library-verified | predicates/custom/twilio-signing.ts — URL+sorted-params canonical-string + HMAC-SHA1 | | Square | 6 | missing-sig-verif, timing-unsafe, raw-body, wrong-hmac, unreachable-verif, library-verified | Parameterized custom_field_tuple recipe |

Full per-rule applicability matrix: docs/rule-coverage.md.


CI integration

GitHub Action (recommended)

# .github/workflows/hookwarden.yml
name: hookwarden
on: [pull_request, push]
permissions:
  contents: read
  pull-requests: write
  security-events: write
jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 }
      - uses: Hookwarden/hookwarden-action@v1
        with:
          fail-on: high

Uploads SARIF to Code Scanning automatically. Findings appear as PR annotations.

Raw CLI + SARIF upload

- uses: actions/setup-node@v4
  with: { node-version: '22' }
- run: npx hookwarden scan . --format sarif > hookwarden.sarif
- uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: hookwarden.sarif

SARIF severity mapping: critical/higherror · mediumwarning · low/infonote.


Architecture

hookwarden is a pnpm monorepo with three load-bearing packages and a strict dependency boundary enforced in CI.

@hookwarden/rules  →  @hookwarden/engine  →  hookwarden CLI
(YAML data +          (pure-functional,       (binary, renders
 predicate factories)   I/O-free)               output)

| Package | Purpose | License | |---|---|---| | @hookwarden/engine | Webhook handler discovery, reachability analysis, evidence collection. Pure-functional, browser-safe — no I/O, no filesystem, no network. | Apache 2.0 | | @hookwarden/rules | Provider catalog, YAML rule packs, parameterized predicate factories. | Apache 2.0 | | hookwarden | CLI binary. Reads config, drives the engine, renders text/JSON/SARIF. | Apache 2.0 |

The engine's I/O boundary is the architectural load-bearing constraint. The same engine runs in the CLI, in CI, and — eventually — in a browser playground without modification. dependency-cruiser enforces the boundary in every PR.


vs. other tools

Hookwarden is specialized on purpose. Webhook signature verification is the only thing it does, and that's why it does it better than tools whose surface area covers everything. The general-purpose scanners below are excellent at what they do — they're just not in this fight.

| Tool | What it does well | Webhook verification coverage | |---|---|---| | semgrep | General-purpose SAST; flexible rule authoring | Low signal — generic pattern matching misses body-parsing ordering, timing-safe comparison paths, and SDK-specific verification flows | | snyk Code | Broad vulnerability detection in paid SaaS | No webhook-specific rules; doesn't model HMAC reachability | | GitGuardian | Secret leak detection in git history and CI | Finds hardcoded secrets; does not audit whether verification logic is correct | | TruffleHog | Secret scanning across sources | Same as GitGuardian — leak focus, not logic focus | | Datadog Static Analysis | Broad SAST; good AWS/cloud signal | No webhook verification specialization; high false-positive rate for this class of bug | | hookwarden | Webhook verification logic only | 45 rules, 6 providers, three-state verdicts, <5% FP target measured against a 200-repo OSS corpus |

If you're already running semgrep or snyk: hookwarden is additive, not a replacement. It finds the class of bug those tools were not built to find.


Advanced usage

Three suppression mechanisms, in order of preference:

Inline — best for one-off cases; the comment is grep-able evidence in code review:

// hookwarden-disable-next-line stripe/missing-signature-verification
app.post('/webhook', rawBodyHandler);

.hookwardenignore — gitignore syntax; best for path-scoped suppression:

__tests__/
fixtures/**/*.spec.ts
mocks/

Baseline — best for adopting on a non-greenfield codebase without failing CI on day one:

# Capture current state
hookwarden scan . --baseline write
# Subsequent runs suppress baselined findings; new findings still fail
hookwarden scan .

--format json reports each finding's suppression source (inline / ignorefile / baseline) so suppressions are auditable.

| Code | Meaning | |------|---------| | 0 | Clean — no findings at or above the configured --fail-on threshold | | 1 | Findings at or above threshold | | 2 | Engine error (parser crash, unreadable input) | | 3 | Config error (malformed hookwarden.config.yaml) | | 4 | Parse coverage below parse_coverage_min |

Precedence: 3 > 2 > 4 > 1 > 0. The highest applicable code wins; use this for branching logic in CI pipelines.

Drop a hookwarden.config.yaml at your project root (or any ancestor directory):

schema_version: '1.0'
fail_on: high                         # critical | high | medium | low | info
parse_coverage_min: 0.9               # fail if < 90% of candidates parsed
baseline:
  enabled: true
  path: .hookwarden.baseline.json

Precedence: CLI flag > hookwarden.config.yaml > built-in defaults.

Inventory mode (lists detected handlers without running rules):

hookwarden inventory ./your-app

| hookwarden severity | SARIF level | GitHub Code Scanning | |---|---|---| | critical | error | Blocks PR merge (if branch protection configured) | | high | error | Blocks PR merge | | medium | warning | Visible annotation, non-blocking | | low | note | Visible annotation | | info | note | Visible annotation |

Re-uploading the same scan deduplicates via SARIF partialFingerprints. Full mapping table: packages/cli/docs/sarif-severity-mapping.md.


Roadmap

v0.5 — Auto-remediation engine. hookwarden fix — mechanically rewrites safety: safe findings across JS/TS, Python, and PHP. Dry-run is the default; --write opts into atomic-staging writes with re-scan verification. Three-tier safety gate (safe / all / manual-only-explain). The largest extension of the correctness moat in v1 — hookwarden goes from "tells you the fix" to "applies it."

v0.6 — More providers. Adyen, Zendesk, Mailgun, SendGrid — each measured against the 200-repo OSS regression corpus before release, with a published false-positive rate.


Contributing

Rule-pack PRs are the highest-value contribution. Adding a new provider is a catalog edit plus N rule YAMLs — the factory architecture means most providers ship without any new TypeScript. See the existing six providers in packages/rules/rules/ as worked examples.

Bug reports and feature requests: open an issue.

Local development:

pnpm install
pnpm -r build
pnpm -r test

Documentation


License

Apache 2.0. The CLI, engine, and rule packs in this repo are open source and will remain so. A separate closed-source SaaS tier handles continuous monitoring, secret leak scanning, automated rotation, and SOC 2 evidence export — hookwarden.dev.