A payment webhook handler
+app.post(+ "/webhooks/payments",+ express.raw({ type: "application/json" }),+ async (req, res) => {+ const signature = Buffer.from(req.headers["x-signature"] ?? "", "hex");+ const expected = crypto+ .createHmac("sha256", process.env.WEBHOOK_SECRET)+ .update(req.body) // raw bytes, not re-serialized JSON+ .digest();·+ if (+ signature.length !== expected.length ||+ !crypto.timingSafeEqual(signature, expected)+ ) {+ return res.sendStatus(401);+ }+ await fulfillOrder(JSON.parse(req.body).data);+ res.sendStatus(200);· }+);
What our engineer caught
The AI verified the signature against re-serialized JSON (which breaks when key order changes) and compared it with ===, which leaks timing information. It also answered 200 even when verification failed.
Why it matters
A forged webhook could confirm orders that were never paid. Raw-body verification and a timing-safe comparison are the difference between an integration and a fraud vector.