coupon_abuse_test
Test coupon stacking and alternation to identify discount bypass vulnerabilities in e-commerce systems by applying coupons individually and in alternating sequences.
Instructions
Test coupon stacking and alternation bypass.
Tests each coupon individually, then alternates between coupons to see if discounts compound past the intended limit.
Returns: {"individual_results": [...], "stacking_results": [...], "stacking_possible": bool}.
Side effects: Applies coupons to the cart. May modify cart totals.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Coupon application endpoint URL | |
| coupon_endpoint | Yes | Full URL for applying coupons, e.g. https://target/cart/coupon | |
| coupons | Yes | Coupon codes to test, e.g. ['NEWCUST5', 'SIGNUP30', 'FREESHIP'] | |
| coupon_param | No | Form parameter name for the coupon code | |
| auth_cookie | No | Session cookie for authenticated requests | |
| stacking_rounds | No | Number of alternation rounds to test for coupon stacking |
Implementation Reference
- src/tools/bizlogic.ts:206-393 (handler)The implementation of the `coupon_abuse_test` tool, which tests coupon stacking and alternation bypass.
server.tool( "coupon_abuse_test", "Test coupon stacking and alternation bypass.\n\nTests each coupon individually, then alternates between coupons to see if discounts compound past the intended limit.\n\nReturns: {\"individual_results\": [...], \"stacking_results\": [...], \"stacking_possible\": bool}.\n\nSide effects: Applies coupons to the cart. May modify cart totals.", { url: z .string() .describe("Coupon application endpoint URL"), coupon_endpoint: z .string() .describe( "Full URL for applying coupons, e.g. https://target/cart/coupon" ), coupons: z .array(z.string()) .min(1) .max(20) .describe( "Coupon codes to test, e.g. ['NEWCUST5', 'SIGNUP30', 'FREESHIP']" ), coupon_param: z .string() .describe("Form parameter name for the coupon code") .optional(), auth_cookie: z .string() .optional() .describe("Session cookie for authenticated requests"), stacking_rounds: z .number() .min(1) .max(20) .describe( "Number of alternation rounds to test for coupon stacking" ) .optional(), }, async ({ url, coupon_endpoint, coupons, coupon_param = "coupon", auth_cookie, stacking_rounds = 5, }) => { requireTool("curl"); // Phase 1: Test each coupon individually const individualResults: Array<{ coupon: string; status: number; length: number; accepted: boolean; response_snippet: string; }> = []; for (const coupon of coupons) { const curlArgs = [ "-sk", "-o", "-", "-w", "\n__META__%{http_code}:%{size_download}", "-X", "POST", "-d", `${coupon_param}=${coupon}`, ]; if (auth_cookie) { curlArgs.push("-b", auth_cookie); } curlArgs.push(coupon_endpoint); const res = await runCmd("curl", curlArgs); let body = res.stdout; const metaMarker = body.lastIndexOf("__META__"); let status = 0; let length = 0; if (metaMarker !== -1) { const meta = body.slice(metaMarker + 8).trim(); const parts = meta.split(":"); status = parts[0] ? parseInt(parts[0], 10) : 0; length = parts[1] ? parseInt(parts[1], 10) : 0; body = body.slice(0, metaMarker); } individualResults.push({ coupon, status, length, accepted: [200, 201, 302].includes(status), response_snippet: body.slice(0, 300), }); } const validCoupons = individualResults .filter((r) => r.accepted) .map((r) => r.coupon); // Phase 2: Test coupon alternation/stacking const stackingResults: Array<{ round: number; coupon: string; status: number; accepted: boolean; response_snippet: string; }> = []; if (validCoupons.length >= 2) { for (let roundNum = 0; roundNum < stacking_rounds; roundNum++) { const coupon = validCoupons[roundNum % validCoupons.length]; const curlArgs = [ "-sk", "-o", "-", "-w", "\n__META__%{http_code}:%{size_download}", "-X", "POST", "-d", `${coupon_param}=${coupon}`, ]; if (auth_cookie) { curlArgs.push("-b", auth_cookie); } curlArgs.push(coupon_endpoint); const res = await runCmd("curl", curlArgs); let body = res.stdout; const metaMarker = body.lastIndexOf("__META__"); let status = 0; if (metaMarker !== -1) { const meta = body.slice(metaMarker + 8).trim(); const parts = meta.split(":"); status = parts[0] ? parseInt(parts[0], 10) : 0; body = body.slice(0, metaMarker); } stackingResults.push({ round: roundNum + 1, coupon, status, accepted: [200, 201, 302].includes(status), response_snippet: body.slice(0, 300), }); } } // Determine if stacking worked const stackingAccepted = stackingResults.filter((r) => r.accepted).length; const stackingPossible = stackingAccepted > validCoupons.length; // Check cart total after stacking let cartCheck: string | null = null; if (auth_cookie) { const cartArgs = [ "-sk", "-o", "-", "-w", "\n__META__%{http_code}:%{size_download}", "-b", auth_cookie, url, ]; const cartRes = await runCmd("curl", cartArgs); let cartBody = cartRes.stdout; const metaMarker = cartBody.lastIndexOf("__META__"); if (metaMarker !== -1) { cartBody = cartBody.slice(0, metaMarker); } cartCheck = cartBody.slice(0, 1000); } const result = { individual_results: individualResults, valid_coupons: validCoupons, stacking_results: stackingResults, stacking_accepted_count: stackingAccepted, stacking_possible: stackingPossible, cart_after_stacking: cartCheck, hint: stackingPossible ? "Coupon stacking/alternation bypass detected! Discounts compounded beyond intended limit." : "Coupon stacking blocked. Server enforces single-use correctly.", }; return { content: [{ type: "text", text: JSON.stringify(result) }] }; } );