{"id":"CVE-2026-115450","kind":"vulnerability","aliases":["CVE-2026-115450"],"related":[],"title":"MarcosCamara01 Ecommerce Template: cart lets users pay less for expensive goods","description":"External Control of Assumed-Immutable Web Parameter (CWE-472) in the cart and checkout flow of MarcosCamara01 Ecommerce Template allows an authenticated user with no special privileges to be charged the price of one product while placing an order for another, because POST /api/user/cart accepts variantId, which determines what the order records, and stripeId, which determines what Stripe charges, as two independent fields of the request body, stores both on the cart row, and no check requires the stripeId to be the one that belongs to the variantId. POST /api/stripe/payment builds the Stripe Checkout line items from the stored value, as { price: item.stripeId, quantity }, so the amount charged is the amount of that Stripe price. The checkout.session.completed webhook then creates the order products from the variantId of the same cart row, so the order records a product that was not paid for. Every stripeId in the catalogue is readable by any visitor, so no value has to be guessed. This results in orders for goods at the price of the cheapest item in the catalogue, repeatable without limit, and in order records whose amount does not correspond to the product they list.","summary":"The ecommerce template's cart endpoint accepts a product ID and a Stripe price ID as independent fields, so a logged-in user can pay the price of a cheap item while ordering a different product. Every Stripe price ID in the catalogue is public, so the mismatch needs no guessing and can be repeated without limit.","severity":"high","cvss":7.1,"epss":0.00235,"exploited":false,"exploited_at":null,"products":[{"name":"MarcosCamara01/ecommerce-template","fixed":["e6b364cd668f2ba875cfa7f6d55c63e771715df7"],"affected":">= commit 2aa8ec53 (2025-11-16), < commit e6b364cd (2026-07-31)","ecosystem":"github"}],"ecosystems":[],"tags":["authenticated","ecommerce","nextjs","other","self-hosted","stripe"],"not_affected_if":["commit-e6b364cd-or-later","no-stripe-checkout","not-this-template"],"how_to_check":"Check whether your checkout code descends from MarcosCamara01/ecommerce-template at or after commit 2aa8ec53 (16 Nov 2025) and lacks e6b364cd (run: git merge-base --is-ancestor e6b364cd HEAD). Vulnerable if src/app/api/user/cart/route.ts accepts stripeId in the request body, or if src/app/api/stripe/payment/route.ts builds line_items from item.stripeId. To find past abuse, compare the variant recorded on each order with the amount Stripe actually charged. The charge is valid in Stripe, so it raises no dispute or fraud signal.","fix":"Pull the upstream repo to a revision that includes commit e6b364cd668f2ba875cfa7f6d55c63e771715df7 (31 Jul 2026). It derives the Stripe price from the variant server-side, and addToCartSchema no longer accepts stripeId. No versioned releases or tags exist, and package.json stays at 0.1.0. Forks must port the change. No configuration workaround exists. Afterwards, audit past orders by comparing each order's variant price with the amount Stripe charged.","status":"open","published_at":"2026-10-22T16:17:35+00:00","first_seen_at":"2026-10-23T21:57:31+00:00","triaged_at":"2026-10-25T03:31:33+00:00","updated_at":"2026-10-25T04:02:48+00:00","category":"other","confidence":0.85,"triage":{"at":"2026-10-25T03:31:33Z","model":"claude-haiku-5-5","output":{"fix":"unknown","reach":"internet","title":"MarcosCamara01 Ecommerce Template: cart lets users pay less for expensive goods","impact":"medium","summary":"The ecommerce template's cart endpoint accepts a product ID and a Stripe price ID as independent fields, so a logged-in user can pay the price of a cheap item while ordering a different product. Every Stripe price ID in the catalogue is public, so the mismatch needs no guessing and can be repeated without limit.","category":"other","nicknames":[],"who_cares":["ecommerce","stripe","nextjs","self-hosted"],"confidence":0.7,"needs_auth":"yes","worst_case":"Customers buy expensive goods at the cheapest catalogue price, repeatedly","analyst_note":"Check the NVD entry and the upstream repository for a patched commit or version; sources give no fixed version, so how_to_check and fix are unknown.","how_to_check":"unknown","needs_analyst":true,"not_affected_if":["not-this-template","no-stripe-checkout"],"who_is_affected":"Teams running the MarcosCamara01 Ecommerce Template or a fork of it with Stripe checkout enabled. The flaw sits in the cart and payment path: POST /api/user/cart stores variantId and stripeId without checking they match, and POST /api/stripe/payment charges the stored stripeId. Stores that do not use this template, or that do not expose this cart flow, can skip it.","user_interaction":"no","needs_special_setup":"no","severity_if_unknown":"high"},"cost_usd":0.000631,"input_tokens":3626,"output_tokens":536,"severity_before":"high"},"analyst_status":"done","analyst_note":"Check the NVD entry and the upstream repository for a patched commit or version; sources give no fixed version, so how_to_check and fix are unknown.","search":"'-115450':14A,17A '-2026':13A,16A '-472':94C '/api/stripe/payment':175C '/api/user/cart':129C 'accept':33B,130C 'allow':105C 'amount':192C,196C,269C 'anoth':126C 'assum':89C 'assumed-immut':88C 'authent':19B,107C 'belong':170C 'bodi':152C 'build':176C 'cart':4A,31B,97C,157C,215C 'catalogu':70B,232C,260C 'charg':115C,144C,193C 'cheap':57B 'cheapest':256C 'check':161C 'checkout':99C,179C 'checkout.session.completed':202C 'control':86C 'correspond':272C 'creat':205C 'cve':12A,15A 'cwe':93C 'determin':133C,141C 'differ':62B 'ecommerc':2A,20B,28B,103C 'endpoint':32B 'everi':64B,228C 'expens':10A 'extern':85C 'field':44B,148C 'flow':100C 'good':11A,250C 'guess':78B,244C 'host':25B 'id':36B,41B,67B 'immut':90C 'independ':43B,147C 'item':58B,181C,257C 'item.stripeid':188C 'less':8A 'let':5A 'limit':84B,263C 'line':180C 'list':277C 'log':48B 'logged-in':47B 'marcoscamara01':1A,102C 'marcoscamara01/ecommerce-template':18A 'mismatch':75B 'need':76B 'nextj':21B 'one':119C,168C 'order':60B,124C,136C,207C,219C,248C,266C 'paid':226C 'paramet':92C 'pay':7A,52B 'place':122C 'post':128C,174C 'price':40B,54B,66B,117C,187C,200C,253C 'privileg':112C 'product':35B,63B,120C,208C,222C,275C 'public':72B 'quantiti':189C 'readabl':234C 'record':137C,220C,267C 'repeat':82B,261C 'request':151C 'requir':162C 'result':246C 'row':158C,216C 'self':24B 'self-host':23B 'special':111C 'store':153C,184C 'stripe':26B,39B,65B,143C,178C,199C 'stripeid':139C,164C,229C 'templat':3A,29B,104C 'two':146C 'user':6A,50B,108C 'valu':185C,240C 'variantid':131C,173C,211C 'visitor':237C 'web':91C 'webhook':203C 'whose':268C 'without':83B,262C","nicknames":[],"mitigations":[],"who_affected":"Teams running the MarcosCamara01 Ecommerce Template or a fork of it with Stripe checkout enabled. The flaw sits in the cart and payment path: POST /api/user/cart stores variantId and stripeId without checking they match, and POST /api/stripe/payment charges the stored stripeId. Stores that do not use this template, or that do not expose this cart flow, can skip it.","tier":"B","verified":{"fix":{"at":"2026-10-25T04:02:48Z","by":"analyst","run_id":807}},"analyst_revisit_at":null,"first_public_at":"2026-10-22T16:17:35+00:00","kev":null,"cvss_vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","cvss_by":"4daa8cea-433a-44bd-9456-53b127fc289a","poc_count":0,"sources":[{"source":"nvd","external_id":"CVE-2026-115450","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-115450","severity":null,"published_at":"2026-10-22T16:17:35+00:00","modified_at":"2026-10-22T17:40:46+00:00","first_seen_at":"2026-10-23T21:57:31+00:00","fetched_at":"2026-10-23T22:29:02+00:00","note":null},{"source":"epss","external_id":"CVE-2026-115450","url":"https://api.first.org/data/v1/epss?cve=CVE-2026-115450","severity":null,"published_at":null,"modified_at":null,"first_seen_at":"2026-10-24T07:15:51+00:00","fetched_at":"2026-10-24T07:15:51+00:00","note":null},{"source":"analyst","external_id":"CVE-2026-115450:807","url":null,"severity":null,"published_at":"2026-10-25T04:02:48+00:00","modified_at":"2026-10-25T04:02:48+00:00","first_seen_at":"2026-10-25T04:02:48+00:00","fetched_at":"2026-10-25T04:02:48+00:00","note":"Read maintainer fix commit e6b364c (2026-07-31) and Secur0 CNA advisory: no versions/tags exist, affected by commit range from 2aa8ec53 (2025-11-16) to before e6b364cd. No exploitation or PoC found."}],"documents":[{"id":3375,"url":"https://github.com/MarcosCamara01/ecommerce-template/commit/e6b364cd668f2ba875cfa7f6d55c63e771715df7","title":"Fix commit e6b364c: derive Stripe price from the variant","kind":"release","source":"analyst","text":null,"published_at":null,"relation":"fix","confidence":null,"note":null},{"id":3376,"url":"https://secur0.com/en/cna/cve-list/cve-2026-115450-price-manipulation-stripe-checkout","title":"Secur0 CNA CVE-2026-115450","kind":"advisory","source":"analyst","text":null,"published_at":null,"relation":"advisory","confidence":null,"note":null}],"notice":"Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai"}