Skip to content

khldLabs/webhookcheck

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

webhookcheck

A small command-line tool that reads Java code and flags webhook handlers that act on a message before checking it's actually real.

What the bug actually is

A webhook is just a message one company's server sends to yours — like Stripe pinging your app to say "that payment went through, ship the order."

The catch: that URL is public, so anyone on the internet can send your app that message. The only thing proving it's really from Stripe is a signature — think of it like a wax seal on a letter. So the rule is simple: check the seal before you do anything.

This tool catches the case where the code does the important thing first and checks the seal after:

capture(payment);                            // marks the order paid...
if (!verifySignature(payload, signature)) {  // ...then checks the seal, too late
    throw new SecurityException("bad signature");
}

A faker can send a "payment worked!" message with a garbage seal:

curl -X POST https://shop.example.com/webhook/payment \
  -H "Stripe-Signature: totally-fake" \
  -d '{"type":"payment_succeeded","amount":100}'

The app charges ahead and marks the order paid before it ever looks at the seal. The check is right there in the code — it just runs one line too late to help.

See it in action

gradlew.bat build
java -jar build\libs\webhookcheck.jar .\examples

⚠  NoVerificationController.java:18  orderHook — no signature verification found
⚠  ResultIgnoredController.java:17   handleWebhook — signature checked but result is ignored
⚠  TooLateController.java:18         handleWebhook — payload processed before signature check
✓  6 handlers checked, 3 issues

(If the ⚠ shows as a box on Windows, run chcp 65001 first.)

What it catches

A handler is safe only when the seal check runs — and stops everything on failure — before any important action. Three ways that breaks:

  • No check at all — the message is trusted blindly.
  • Check too late — the check is there, but something important already ran.
  • Check ignored — the seal is checked, but the code doesn't stop on a bad one.

Where it falls short (on purpose)

I threw tricky code at my own tool to see where it breaks — better to know the gaps than pretend they aren't there:

  • Check throws its own error instead of using an if → false alarm.
  • Check done by hand (comparing the codes directly) → missed, because nothing is literally named "verify."
  • Checking handed off to a helper function → missed; the tool reads one function at a time.
  • A skipped check where the action uses a word I didn't list → stays quiet.

The first three are false alarms; the last is a real miss. Fixing all four is the plan for v2.

How it works

  1. Walk the folder and read every .java file into a tree the tool can inspect (using JavaParser — this is what lets it reason about the order of the code, which plain text search can't).
  2. Find the webhook handlers.
  3. For each one, check that a seal check runs and stops on failure before any important action.
  4. Print what's wrong.

Running the tests

gradlew.bat test

The tests point the tool at a set of example handlers — three broken, three safe — and check it flags exactly the broken ones and stays quiet on the safe ones.

Requirements

Java 17 or newer. No need to install Gradle — the included gradlew.bat handles it.

About

Command-line tool that flags Java webhook handlers that act on a message before verifying its signature

Topics

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Contributors

Languages