Back to Technical Mode
Client-Side Price Tampering
When a server trusts a price or amount field submitted by the client instead of re-deriving it from the product catalog server-side, changing one number in the request changes what gets charged.
Any value that determines money changing hands must be looked up server-side from a source of truth, never trusted from client input
Client-side price display is a UX convenience — it carries no authority over what the payment processor actually charges
Signed, short-lived server-issued price tokens (or re-fetching the cart total at charge time) close this gap without slowing down checkout
The same class of bug applies to quantity, discount codes, and shipping cost — anywhere a number flows from client to charge
Want this flow explained in detail as it plays?
POST/api/checkout
Headers
Host:app.flowground.dev
Content-Type:application/json
Body
Loading...
Quick-Insert Payloads
Defense in depth
- Re-derive the charge amount from the product catalog by itemId on the server — never accept an amount field from the client at all
- If a client-computed total must be shown for UX, verify it server-side against the catalog before creating the charge, and reject on mismatch
- Enforce a sane bounds check (amount > 0, amount matches an expected range) as defense-in-depth even after removing client trust
Vulnerable vs. Fixed
app.post("/api/checkout", async (req, res) => {
const { itemId, amount } = req.body;
const charge = await stripe.charges.create({ amount, currency: "usd" }); // trusts client-supplied amount
res.json(charge);
});