BugForge - Daily - Cheesy Does It
Daily - Cheesy Does It
Vulnerabilities Covered
Summary
The Cheesy Does It application advertises a FOUNDERS20 promo code that grants 20% off your first order and is explicitly marked one per customer. The checkout flow enforces this limit correctly, rejecting a second use with You have already used this coupon. The Reorder feature, however, re-implements coupon handling on POST /api/orders/<id>/reorder without the same guard. The endpoint silently accepts a coupon_code value in the request body, a parameter the front-end never sends, and re-applies the discount without re-checking the per-customer redemption limit or requiring any payment. Redeeming FOUNDERS20 once at checkout and then replaying it through the reorder endpoint flips coupon_reused to true and discloses the flag, confirming the one-time-use constraint is not enforced on this path.
Reference
Application Analysis
Begin by exploring the Cheesy Does It application on first load. The menu page greets new customers with a Founders Circle banner offering 20% off your first order with the code FOUNDERS20, to be applied at checkout.

Placing the First Order with the Coupon
Add a pizza to the cart and proceed to checkout. In the Discounts & Rewards section, enter FOUNDERS20 in the promo code field. The helper text reinforces the rule, “First order? Use FOUNDERS20 for 20% off (one per customer).”, and the coupon applies cleanly, taking -$2.20 off the $10.99 subtotal for a total of $8.79.

Complete the payment and place the order. This is the single, legitimate redemption of FOUNDERS20, the coupon is now consumed against our account. Attempting to use it a second time through the normal checkout is rejected with You have already used this coupon, confirming the limit is enforced on the primary order flow.
Discovering the Reorder Feature
Navigate to the Orders page to view the order history. Each past order exposes a Reorder button alongside View Details, a convenience feature that re-places a previous order in a single click.

Investigating the Reorder Request
Click Reorder and capture the request in Caido. The front-end issues a POST to /api/orders/<id>/reorder with an empty body (Content-Length: 0). Despite sending no coupon data, the JSON response contains a full set of coupon fields:
{
"id": 2,
"order_number": "CDI-1783946285456-7CN0YRWG7",
"message": "Reorder placed successfully",
"status": "received",
"subtotal": 10.99,
"coupon_code": null,
"coupon_discount": 0,
"coupon_reused": false,
"points_earned": 10,
"total": 10.99
}

Two things stand out. First, the endpoint clearly has coupon logic, it reports coupon_code, coupon_discount, and a telling coupon_reused flag, yet the browser never sends a coupon. Second, the reorder is placed at full price ($10.99) with no payment step at all. The presence of coupon_reused strongly hints that the intended bug is coupon reuse, and the fact that the server returns coupon fields for an input it “never received” suggests the handler is reading a coupon_code body parameter that the front-end simply leaves out.
Injecting the Coupon and Retrieving the Flag
Send the reorder request to Caido Replay and modify it in two ways:
- Add a
Content-Type: application/jsonheader, without it the server’s body parser ignores the payload andcoupon_codeis never read. - Add the JSON body
{"coupon_code":"FOUNDERS20"}, re-supplying the coupon that was already consumed at checkout.
POST /api/orders/2/reorder HTTP/1.1
Content-Type: application/json
{
"coupon_code": "FOUNDERS20"
}
The server accepts the already-used coupon, re-applies the -$2.20 discount, and returns "coupon_reused": true with the message Reorder placed successfully — promo applied. The flag is disclosed inline:

The reorder endpoint honoured FOUNDERS20 a second time even though the account had already redeemed it, proving the application does not correctly enforce the coupon’s one-per-customer constraint on this path.
Why the Content-Type Header Matters
The back-end parses request bodies with a JSON body parser (Express express.json()), which by default only runs when the request’s Content-Type is application/json. Two byte-identical reorder requests behave completely differently depending on this header:
- With
Content-Type: application/json, the body is parsed,coupon_codeis read, the discount is re-applied,coupon_reusedbecomestrue, and the flag is returned. - Without it, the parser skips the body,
coupon_codeisundefined, and the server places a plain full-price reorder withcoupon_reused: falseand no flag.
This is a common gotcha for parameter-injection findings, an injected field is silently ignored until the Content-Type matches what the server’s body parser expects.
Impact
- Unlimited reuse of a coupon that is meant to be redeemed only once per customer
- Repeated discounts applied through the reorder endpoint, resulting in direct financial loss
- Orders placed with no payment validation, the reorder path skips the checkout
validate→process→payment_tokenpipeline entirely - Loyalty points earned on every reordered order, allowing point farming on top of the discount abuse
- The flaw is exploitable against the attacker’s own account with a single crafted request, requiring no elevated privileges
Vulnerability Classification
- OWASP Top 10: A04:2021 - Insecure Design (business-logic abuse of a sensitive flow)
- OWASP API Security Top 10: API6:2023 - Unrestricted Access to Sensitive Business Flows
- Vulnerability Type: Business Logic Flaw - single-use coupon reuse via an alternate endpoint that omits the redemption check and accepts a client-supplied
coupon_code - Attack Surface:
POST /api/orders/<id>/reorder - CWE: CWE-837 - Improper Enforcement of a Single, Unique Action, CWE-841 - Improper Enforcement of Behavioral Workflow, CWE-915 - Improperly Controlled Modification of Dynamically-Determined Object Attributes
Root Cause
The reorder handler duplicates the checkout’s coupon-application logic but drops its guards. Where POST /api/orders validates the coupon, checks the per-user redemption record, records the redemption, and requires a valid payment token, the reorder endpoint trusts a coupon_code value passed in the request body and applies the discount without re-verifying that the coupon has not already been redeemed by that customer and without requiring payment. The server even computes a coupon_reused flag that correctly identifies the reuse, but grants the discount anyway rather than rejecting it. Because the single-use constraint is enforced only on the primary checkout path and not on this secondary flow, the “one per customer” rule can be bypassed indefinitely.
Remediation
- Enforce coupon validation centrally so every code path that applies a discount, including reorder, runs the same redemption checks
- Reject any coupon whose per-customer or global redemption limit has already been reached, and treat
coupon_reused: trueas a hard failure rather than an informational flag - Record coupon redemptions atomically at the point the order is created to prevent race conditions and replay
- Do not accept a client-supplied
coupon_codeon the reorder endpoint; derive pricing server-side from the referenced order and re-validate it - Require the full payment authorisation flow for reorders instead of allowing orders to be placed with no payment token
- Ignore or strip body parameters that the endpoint is not designed to accept, and validate the request
Content-Typeexplicitly - Add server-side monitoring for repeated use of single-use codes and anomalous reorder volumes