See why a webhook was trusted before your application acts on it.
A local-first AppSec portfolio MVP by José Miguel Díaz.
HookShield is a visual inbox and policy boundary for incoming webhooks. It captures the original request bytes, verifies provider signatures, evaluates freshness and idempotency, records every security decision, and lets an operator inspect the evidence in one dense console.
It is intentionally described as a professional portfolio MVP, not a production gateway. The demo needs no Docker, cloud account, public tunnel, Redis, or PostgreSQL.
Requirements: Node.js 22+ and pnpm 11+.
git clone https://github.com/JMDcore/JMD-HookShield.git
cd JMD-HookShield
pnpm install
pnpm demoOpen http://localhost:3000. Demo authentication is automatic and limited to HOOKSHIELD_DEMO_MODE=true. Every run rebuilds a synthetic SQLite dataset; all included keys and webhook secrets are test-only.
From Simulate, generate a valid event, bad signature, tampered payload, stale timestamp, duplicate, replay attempt, oversized body, rate-limit rejection, or a valid event after secret rotation.
- GitHub
X-Hub-Signature-256verification over the untouched body andX-GitHub-Deliveryidempotency. - Stripe verification through the official SDK, including the signed timestamp and configurable tolerance.
- A documented Generic HMAC protocol that signs
timestamp.delivery-id.raw-bodywith HMAC-SHA256. - Constant-time equality, missing/malformed signature handling, payload caps, and endpoint rate limits.
- AES-256-GCM secret encryption with an environment-only master key.
- Versioned secret rotation with a bounded previous-version transition window.
- Append-only duplicate and replay evidence instead of silent discards.
- Owner-scoped dashboard access, expiring
HttpOnlysessions, strict cookies, origin-bound CSRF checks, CSP, and redacted headers. - Controlled internal processing, retry limits, JSON audit export, and configurable retention purge.
- A real operations UI with keyboard list navigation, responsive layout, loading/error/empty states, and automated WCAG checks.
Signatures are checked before JSON is trusted. A provider adapter then supplies the delivery ID, event type, and—where the protocol supports it—a signed timestamp. HookShield decides whether to admit, reject, expire, or deduplicate the delivery and persists the checks that led to that result.
GitHub's standard signature does not include a signed timestamp. HookShield therefore authenticates its raw body and deduplicates its delivery ID, while explicitly recording freshness as unavailable instead of inventing a guarantee.
apps/web Next.js operations console
apps/api Fastify ingress, auth, simulator, and decision engine
packages/ Contracts, consolidated security primitives, SQLite persistence
tests/e2e Browser-level product and accessibility tests
docs/ Threat model, protocols, guides, diagrams, and launch material
The MVP stays synchronous and single-node on purpose. See Architecture, Threat model, and Design system for the boundaries and trade-offs.
- GitHub CLI forwarding uses the official
cli/gh-webhookextension against a repository you own or are authorised to test. - Stripe CLI sandbox forwards sandbox events and uses its printed signing secret.
- Generic HMAC CLI runs entirely against localhost with the included sender.
The built-in simulator remains the recommended path because it is deterministic, offline from providers, and includes negative security cases.
pnpm typecheck
pnpm test
pnpm test:e2e
pnpm build
pnpm auditThe test suite covers valid, missing, incorrect, modified, stale, duplicated, rotated, oversized, rate-limited, cross-user, redaction, encryption, retention, retry, consistent-error, full simulator, and accessibility paths. See Testing.
The main threats are forged signatures, timing leakage, replay, duplicate processing, secret disclosure, cross-user access, unbounded input, log injection, session attacks, and excessive retention. Controls and residual risks are recorded in the threat model.
HookShield never forwards to arbitrary URLs in this MVP. That feature was rejected to avoid creating an SSRF surface before a proper egress policy and network sandbox exist.
Please report security issues using SECURITY.md, not a public issue.
Current limits are explicit:
- SQLite, in-memory rate windows, and process-local consumers are single-node controls.
- Delivery uniqueness is guaranteed by the single local decision engine, not a distributed database constraint.
- There is no KMS/HSM integration, SSO, multi-tenant billing, or arbitrary webhook forwarding.
- Payload inspection is JSON-focused and retention purge is invoked locally rather than by a durable scheduler.
The next credible steps are PostgreSQL uniqueness, Redis-backed distributed limits, a durable processing queue, envelope encryption via KMS, OIDC/SSO, scheduled retention, and carefully sandboxed destinations. See the roadmap.
- Demo and simulator
- Provider setup
- Generic HMAC protocol
- Architecture
- Threat model
- Testing guide
- Roadmap
- Contributing
MIT © 2026 José Miguel Díaz.



