Guide · VibeScan

AI-Built Webhooks: 7 Security Tests Before You Trust an Incoming Event

Webhooks are small endpoints with outsized power. If an AI coding tool generated yours, test the trust boundary before a forged or repeated event can trigger real work.

2026-09-06
9 min read
Abhilash — MakeLabs
A signed webhook event passing through seven security checks
A webhook is not trusted because it came from a familiar URL. It is trusted only after the request, event, and side effects are checked.

AI coding tools make it easy to add a Stripe checkout, GitHub integration, email provider, background job, or deployment hook in an afternoon. The generated endpoint may be short, readable, and apparently functional.

That is exactly why webhooks deserve their own review. An incoming webhook is an internet-facing POST request that can create records, change account state, issue refunds, trigger emails, or start a deployment. A route that “works” in a happy-path test can still accept forged requests, process the same event twice, or trust fields it should have ignored.

This is a different problem from the broader pre-launch security checklist for AI-built apps. Here the question is narrower: what must be true before your app treats an external event as an instruction?

Start with the trust boundary

Write down four things before reading the handler:

OWASP’s API Security Top 10 is a useful map for this review. Webhook handlers can run into broken authentication, unrestricted resource consumption, security misconfiguration, unsafe consumption of APIs, and authorization flaws—not because webhooks are special, but because they combine an API boundary with automated side effects.

1. Verify the signature on the raw request body

The first test is simple: send a request with a missing, malformed, or incorrect signature and confirm that no side effect occurs. Then change one byte in an otherwise valid payload and confirm that it is rejected.

Signature verification usually depends on the exact bytes received. Do not parse JSON, reserialize it, and then verify the reconstructed string unless the provider explicitly documents that behavior. Keep the signing secret server-side, use the provider’s official verification library when one exists, and compare signatures using the library’s safe verification function.

Stripe’s webhook guidance says to verify the payload with the Stripe-Signature header and the endpoint secret. GitHub’s guidance likewise recommends a high-entropy webhook secret and validation against the original request body. These are provider-specific implementations of the same boundary: an unverified webhook is just an anonymous POST request.

Test it: replay a known-good payload after changing a harmless-looking field. If the handler still processes it, the signature check is happening too late—or not at all.

2. Make replay protection explicit

A valid signature proves that the provider signed the request. It does not automatically prove that this delivery is new. An attacker who captures a valid request may be able to send it again, and providers may retry deliveries when your endpoint times out.

Store a provider delivery ID or event ID with a uniqueness constraint, and decide how long to retain it based on the provider’s retry window and the impact of the action. For providers that supply a timestamp, enforce the documented tolerance through the official library. GitHub specifically documents the X-GitHub-Delivery identifier as a way to detect repeated deliveries.

Test the same signed request twice. The first request may create the record or enqueue the job; the second should be a safe no-op or a clearly recorded duplicate, not a second charge, email, or account mutation.

3. Separate “accepted” from “completed”

Webhook providers expect a quick HTTP response. If your handler performs a long database transaction, calls several APIs, or generates a report before returning, the provider may retry the delivery while the first attempt is still working.

A safer shape is: verify the request, validate the event, record the delivery, enqueue idempotent work, and return a success response. The worker can then perform the expensive side effect. GitHub’s documentation recommends responding within 10 seconds and suggests asynchronous processing when work would take longer.

This is not a license to acknowledge every request. Invalid signatures and unsupported events should be rejected. The point is to keep verified, accepted work small and repeatable.

4. Allowlist event types and actions

Many providers send multiple event types through one endpoint. An AI-generated handler may switch on a convenient field without checking whether the event type, action, account, or object state is one you actually support.

Build an explicit allowlist. Reject unknown event types. For known events, validate required fields, expected state transitions, and the provider account or environment when the payload contains those identifiers. GitHub recommends checking both the event type and action before processing a payload; the same discipline applies to other providers.

5. Make the side effect idempotent

Idempotency is not only a webhook concern. It is the property that lets a retried operation reach the same final state without multiplying the effect.

Choose a stable idempotency key—often the provider event ID—and enforce it in the database rather than relying only on an in-memory flag. Put the uniqueness check close to the side effect. If an event creates a subscription, for example, the subscription write and the “already processed” record need a transaction or an equivalent concurrency-safe design.

Then test concurrent delivery: send two copies at nearly the same time. A sequential duplicate test can pass while a race still creates two records.

6. Bound inputs, privileges, and outbound work

Signature verification does not make every field trustworthy. A signed payload can still be unexpectedly large, contain an unsupported value, or request work that is expensive for your system.

These checks line up with OWASP API risks such as unrestricted resource consumption, SSRF, security misconfiguration, and unsafe consumption of APIs. They also make failures easier to diagnose when a provider changes its payload shape.

7. Log enough to investigate, not enough to leak

Record the delivery ID, event type, verification result, processing status, latency, and a correlation ID. Avoid logging signing secrets, authorization headers, full payment or customer objects, raw tokens, or entire payloads by default.

Keep logs useful for a replay investigation: when was the delivery seen, was it accepted, was it a duplicate, what worker handled it, and what side effect was committed? If you need a payload for debugging, redact it deliberately and apply a retention period.

A review sequence for an AI-generated handler

  1. Read the provider’s signature-verification documentation before reading the generated code.
  2. Trace the raw request body from the web framework to the verification call.
  3. Find the delivery ID, uniqueness constraint, and duplicate path.
  4. List accepted event types and reject everything else.
  5. Trace every side effect and identify its idempotency boundary.
  6. Check body limits, timeouts, outbound destinations, and worker privileges.
  7. Run invalid, modified, duplicate, concurrent, oversized, and unsupported-event tests.

OWASP’s AI-Assisted Secure Coding guidance recommends independent human review and automated security testing for AI-generated code, with elevated review for security-critical files. A webhook handler belongs in that category when it controls money, identity, permissions, deployments, or user data.

Have a small AI-built app with an integration endpoint?

Run a first-pass security check with VibeScan →

VibeScan is positioned as a first-pass check for security mistakes in AI-generated code and live apps, such as exposed secrets, open database rules, and missing auth checks. It is useful for finding obvious problems earlier, but it is not a guarantee, a complete webhook review, or a replacement for a professional security assessment. Read the VibeScan documentation for the current scope before relying on any result.

Further reading

For the broader launch sequence, read How to Secure an AI-Built Web App Before Launch. For the human side of shipping focused products, read more about building apps solo.

← Back to blog
All posts
Related post →
How to Secure an AI-Built Web App Before Launch