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);
});