Code & Engineering

Stripe Webhook Review

Reviews ONE Stripe webhook handler (the route code, in any language or framework) for the five mistakes that let a forged or repeated event move money, grant access or ship goods, and lists only those, one line each with a fixed code, the place, why it is dangerous and the fix - or exactly No findings. It catches a body parsed or re-serialized before the signature is checked, a handler that never checks the signature, a recency tolerance switched off or set huge, no record of event ids so a retry repeats the side effect, and slow work done before the 2xx answer. It leaves out the safe look-alikes, such as a raw body kept on the webhook route while the other routes parse JSON, and the default tolerance. Use to review a webhook route before going live, to audit one that someone else wrote, or to find out why signature checks fail or orders are fulfilled twice.

Stripe Webhook Review is a tested SKILL.md that reviews ONE Stripe webhook handler (the route code, in any language or framework) for the five mistakes that let a forged or repeated event move money, grant access or ship goods, and lists only those, one line each with a fixed code, the place, why it is dangerous and the fix - or exactly No findings; an agent buys it once for $0.01 over x402.

Tested 2026-10-19No code, no hidden instructionsv1.0.0 · 8.0 KB · perpetual license

Not for

Payment amounts, refunds, API keys, IP allowlists, rolling the signing secret, thin events, Connect and any helper function whose body is missing from the paste. It reads one pasted handler and judges only what is written in it.

Tested, honestly

Tested 2026-10-19 with a strong and a weak model.

SonnetStrong model, claude-sonnet-5-5
Right on all 3 cases, read by hand. On the Express app it named the body rebuilt with JSON.stringify after the app-wide JSON parser, and left out the default tolerance. On the Flask route it gave two lines, the tolerance set to 0 and the credit update with no event id, and left out the raw body next to a JSON route. On the clean Next.js route it answered exactly No findings.
HaikuWeak model, claude-haiku-5-5
Right on all 3 cases, read by hand. It gave the same single line for the rebuilt body and the same two lines for the Flask route, and answered exactly No findings on the clean route. On the Flask route it indented its two lines by four spaces, which the format check allows.

Full test summary

Example

Our own test text, before and after the skill ran. Excerpts only.

English · claude-sonnet-5-5

Before

# app.py import os import stripe from flask import Flask, request from db import db app = Flask(__name__) WEBHOOK_SECRET = os.environ["STRIPE_WEBHOOK_SECRET"] @app.post("/api/profile") def update_profile(): data = request.get_json() db.execute("UPDATE users SET name = %s WHERE id = %s", (data["name"], data["id"])) db.commit() return {"ok": True} @app.post("/stripe/webhook")…

After

TOLERANCE-OFF — `stripe_webhook`, `tolerance=0` passed to `stripe.Webhook.construct_event` — a tolerance of 0 switches the recency check off, so anyone who captures one validly signed request can replay it later — remove the argument to use the default 5 minutes…

What is in the file

  • The answer
  • What Stripe says (public webhook documentation, read on 19 October 2026)
  • The codes
  • How to read the handler
  • Rules
  • Work in this order
  • Short example

Languages

English. Tried in: English.

License

Perpetual, non-exclusive; use and modify for yourself incl. paid work; no resale or republishing. Holder: Georgi Kalchev, aiskills402.com. Full terms.

Versions

Current version 1.0.0, updated 2026-10-19. Whoever bought an earlier version gets new ones free through the same re-download token.

  1. v1.0.0 · 2026-10-19

    First release, written in the light-test batch of 19 October 2026 (three cases, price $0.01). The idea is ours; no foreign skill was opened, facts come from public pages (see notes/ideas.md). Output: one line per finding with a fixed code, or exactly `No findings.`

    Test: three cases written by hand (an Express app that rebuilds the body, a Flask route with tolerance 0 and no event-id record, and a clean Next.js route), one run on Claude Sonnet and one on Claude Haiku, no run without the skill, no iteration on the skill text after the runs. `test/control.mjs` shows that the checks pass on the ideal answers and fail on realistic wrong ones. See `test-summary.json` for the verdicts read by hand.

FAQ

Should a raw body next to JSON routes be reported?

No. Stripe needs the raw bytes of the request for the signature check, so a webhook route that keeps them is the safe form, whatever the neighbouring routes of the app do with JSON. The skill reports a body that was parsed and written out again before the check.

Does leaving out the tolerance argument count as a defect?

No. The official libraries accept five minutes unless told otherwise, and a handler that passes no tolerance is left alone. A tolerance of 0, which switches the recency check off, is reported, and so is a value of an hour or more, which is the policy of this skill because the documentation gives no figure for huge.

Which handlers went into the test?

An Express app that serialises the body again, a Flask route with the tolerance at 0 and no record of event ids, and a clean Next.js route. Claude Sonnet and Claude Haiku answered each once, and by hand both were right every time.

What does a handler without problems get?

The sentence No findings. on its own line, which makes it usable as a merge gate. A defect is a line holding a code, the place, the risk it creates and the correction.

Share

Read this page as Markdown: /skills/stripe-webhook-review.md.

More in Code & Engineering

  • GitHub Actions Security Review

    Code & Engineering

    SKILL.md · v1.0.0 · 8.3 KB

    Reviews ONE GitHub Actions workflow file (YAML) for the five mistakes that let an outsider run code or read secrets in your pipeline, and lists only those, one line each with a fixed code, the place, why it is dangerous and the fix - or exactly No findings. It catches text from an issue, pull request, comment or branch name pasted straight into a shell step, a pull_request_target or workflow_run job that checks out and runs the code of the pull request, a third-party action pinned to a tag or branch instead of a full commit hash, a missing or too wide permissions block, and a secret that is printed or handed to code you do not control. It leaves out the safe look-alikes, such as untrusted text passed through an env variable and quoted, or first-party actions pinned to a version tag. Use to review a workflow before merging it, to audit the pipelines of a repository, or to gate a pull request that edits a workflow file.

    $0.01once

    • x402
    • USDC
    • Base
    Get skill

    Tested with Sonnet and Haiku, 19 Oct 2026

  • API Breaking Change Check for OpenAPI

    Code & Engineering

    SKILL.md · v1.0.1 · 10.7 KB

    Compares two versions of one API description (OpenAPI 3.0 or 3.1 in YAML or JSON, or two JSON Schemas of one request or response) and lists ONLY the changes that break clients written against the old version, one line each with a fixed code, the place, old and new, and who breaks - or exactly No breaking changes. The skill judges by direction - a request may widen safely and breaks when it narrows, a response may narrow safely and breaks when it widens - and it follows each $ref and allOf to the operations that use it, so a change made only in a shared schema is still found, while a renamed path variable, a new optional field, a reformatted file and a field moved between allOf branches are left out. Use to check an API change before release, review a pull request that edits an OpenAPI file, or gate a pipeline on breaking changes.

    $0.03once

    • x402
    • USDC
    • Base
    Get skill

    Tested with Sonnet and Haiku, 18 Oct 2026

  • GDPR Cookie Consent Review: Banner, Consent Mode

    Code & Engineering

    SKILL.md · v1.0.0 · 17.9 KB

    Reviews a pasted snapshot of a website's cookie and consent setup (scripts in the head, the banner with each toggle's default, the Consent Mode or tag-manager setup, what a fresh browser stored and contacted before any click, the cookie table, the owner's note) against published EU law, court rulings, EDPB guidance, national regulators and vendor documents. It is a technical review, not legal advice. It flags trackers and embeds that store or read before a choice, a Consent Mode default that is late or granted, pre-ticked and implied consent, analytics filed as strictly necessary, legitimate interest used for cookies, a reject option that is missing or disguised, bundled purposes, missing cookie information, no easy withdrawal, a refusal that is not kept, missing Consent Mode v2 signals, personalised Google ads without a certified CMP, cookie walls, and cookieless pings or Google font links treated as exempt. Each finding has a fixed code, the place, the named source with its weight and a fix, then one verdict. Where sources disagree, the line says so and never picks a side. Use to review cookie consent banner setups, run a GDPR cookie banner check or do a Consent Mode setup review before a regulator or a customer asks.

    $0.01once

    • x402
    • USDC
    • Base
    Get skill

    Tested with Sonnet and Haiku, 16 Oct 2026

  • Recommended

    OpenNext R2 Cache Cleanup for Next.js on Cloudflare

    Code & Engineering

    SKILL.md · v1.0.1 · 11.9 KB

    Decides which old build folders of an OpenNext incremental cache on Cloudflare (R2, or Workers KV) can be deleted, from a pasted setup (wrangler config, open-next config, next.config, the public HTML build id, a listing of the cache folders), and never touches the live build. It reads the cache root and the real folder name (a custom prefix, a deploymentId, a constant deploymentId, a no-build-id folder), finds the live build from the public HTML, not from a local file, and handles a rollback, a deploy in progress, two Workers on one bucket, a bucket with other folders, KV billing, and a request to delete the live build or to skip the dry run. Answer in a fixed format: live build, KEEP and DELETE lines, steps with a dry run first, one verdict. Use to clean up an OpenNext R2 cache, find old build folders in R2, or free R2 space used by Next.js on Cloudflare before running any delete.

    $0.05once

    • x402
    • USDC
    • Base
    Get skill

    Tested with Sonnet and Haiku, 16 Oct 2026