Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.
Sources: National Vulnerability Database, CISA KEV, Exploit-DB
CVE-2026-115450 Overview
CVE-2026-115450 is a business logic flaw in the MarcosCamara01 Ecommerce Template. The cart and checkout flow trusts a client-supplied stripeId field independently of the variantId that identifies the ordered product. An authenticated user can submit a request to POST /api/user/cart that pairs any product variant with the Stripe price identifier of a cheaper catalogue item. The Stripe Checkout session then charges the cheaper price while the order record books the more expensive product. Because every stripeId is readable by any site visitor, no guessing is required, and the attack is unlimited in repetition.
Critical Impact
Authenticated users can place orders for any product at the price of the cheapest catalogue item, producing paid orders whose amounts do not match the goods shipped.
Affected Products
- MarcosCamara01 Ecommerce Template (Next.js reference project)
- Deployments of the template using the /api/user/cart and /api/stripe/payment routes
- Forks or derivatives that reuse the pre-patch cart schema and Stripe line-item builder
Discovery Timeline
- 2026-10-22 - CVE CVE-2026-115450 published to NVD
- 2026-10-22 - Last updated in NVD database
Technical Details for CVE-2026-115450
Vulnerability Analysis
The vulnerability is an instance of External Control of Assumed-Immutable Web Parameter ([CWE-472]). The cart API endpoint POST /api/user/cart accepts two independent fields in the request body: variantId, which identifies the product variant that will later be recorded on the order, and stripeId, which identifies the Stripe price object used to compute the amount charged. Both values are stored on the same cart row without server-side validation that they refer to the same product.
When checkout starts, POST /api/stripe/payment constructs the Stripe Checkout line items directly from the stored field as { price: item.stripeId, quantity }. Stripe therefore charges whatever price the client originally supplied. On successful payment, the checkout.session.completed webhook creates the order products from the variantId on the same cart row. The order record is decoupled from the amount collected.
Root Cause
The server treats stripeId as an immutable, catalogue-derived attribute even though it originates from the client request body. There is no referential check binding stripeId to the Stripe price configured for the given variantId. The template also exposes every stripeId in the public catalogue response, so the attacker has a direct inventory of substitutable price identifiers.
Attack Vector
An authenticated user with no special privileges reads the catalogue, extracts the stripeId of the cheapest item, and submits a cart request pairing the target variant with that stripeId. The user then completes Stripe Checkout. Stripe collects the cheapest-item amount, the webhook records an order for the targeted variant, and fulfillment proceeds against the inflated-value product.
// Patch excerpt – src/app/api/stripe/payment/route.ts
import { NextRequest, NextResponse } from "next/server";
import { z } from "zod";
import { stripe } from "@/lib/stripe";
+import { buildLineItems } from "@/lib/stripe/line-items";
import { stripeLogger } from "@/lib/stripe/logger";
import { getOrCreateStripeCustomer } from "@/services/stripe.service";
import { auth } from "@/utils/auth";
// Source: https://github.com/MarcosCamara01/ecommerce-template/commit/e6b364cd668f2ba875cfa7f6d55c63e771715df7
The fix routes line-item construction through a new buildLineItems helper that derives the Stripe price from the variant on the server, discarding any client-supplied stripeId.
Detect Identity Attacks the Moment Authentication Fails
Singularity™ Identity surfaces credential misuse, lateral movement, and privilege escalation in real time, so you can contain the breach before it spreads.
Stop Identity AttacksDetection Methods for CVE-2026-115450
Indicators of Compromise
- Order records in the application database where the summed Stripe charge amount does not equal the sum of catalogue prices for the listed variants.
- Repeated POST /api/user/cart requests from the same account where the submitted stripeId does not match the Stripe price mapped to the submitted variantId.
- Stripe Checkout sessions whose line_items.price references a product unrelated to the fulfilled order.
Detection Strategies
- Reconcile every completed order against the Stripe payment_intent.amount_received, flagging deltas greater than zero as suspect.
- Add server-side logging on POST /api/user/cart that records both submitted variantId and stripeId, and alert when the pair diverges from the catalogue mapping.
- Correlate checkout.session.completed webhook payloads with order records to identify mismatched product and price identifiers.
Monitoring Recommendations
- Monitor Stripe Dashboard for unusually low average order values relative to historical baselines for the same SKUs.
- Review customer accounts with high order volume at identical minimum amounts, a pattern consistent with repeated exploitation.
- Track application logs for cart mutations that reuse a single stripeId across many distinct variantId values.
How to Mitigate CVE-2026-115450
Immediate Actions Required
- Apply the upstream patch from commit e6b364c, which centralises line-item construction in buildLineItems and sources the Stripe price from the variant on the server.
- Audit historical orders against Stripe charge amounts and initiate refunds, chargebacks, or recovery actions for mismatched transactions.
- Rotate any Stripe restricted keys used by the application if evidence of abuse is found during the audit.
Patch Information
The maintainer fix is published in the project repository. See the GitHub commit details and the CVE-2026-115450 price manipulation analysis for the end-to-end description of the vulnerable code paths and the corrected buildLineItems logic.
Workarounds
- Remove stripeId from the request schema of POST /api/user/cart and resolve the Stripe price identifier server-side using the variantId as the sole key.
- Add a validation layer in POST /api/stripe/payment that re-derives each line_items.price from the variant and rejects any session where the stored stripeId does not match.
- Stop exposing stripeId in public catalogue API responses to reduce the attacker's visibility into substitutable price identifiers.
# Server-side invariant to enforce before creating a Stripe Checkout session
# Pseudocode: reject any cart row where stripeId does not match the canonical price for variantId
for item in cart.items:
expected = db.variants.find(item.variantId).stripePriceId
if item.stripeId != expected:
raise HTTPError(400, "cart integrity violation")
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.
Sources: National Vulnerability Database, CISA KEV, Exploit-DB

