Max amount limits enforced at submission
Why it matters
Without a server-side maximum, any user can craft a request with an arbitrarily large amount value and bypass whatever HTML max attribute the form presents. This opens the door to accidental or malicious over-drafts, integer overflow in downstream calculations, and Stripe or payment processor rejections that can cascade into failed order states. OWASP A03 and PCI DSS Req-6.2.4 require server-side input validation for all payment parameters — client constraints are cosmetic until the server enforces them independently.
Severity rationale
Medium because unbounded server-side amounts enable over-limit transactions that the payment processor or banking rail will reject, corrupting order state.
Remediation
Define a named constant for the limit and enforce it in the API route handler before any payment processor call.
// src/app/api/transfers/route.ts
const MAX_AMOUNT_CENTS = 99999; // $999.99 — adjust per business rules
const schema = z.object({
amountCents: z.number().int().min(1).max(MAX_AMOUNT_CENTS),
});
const { amountCents } = schema.parse(await req.json());
Also set max={MAX_AMOUNT_CENTS / 100} on the HTML <input type="number"> in src/components/TransferForm.tsx to keep client and server limits aligned.
Detection
-
ID:
max-amount-limits -
Severity:
medium -
What to look for: Count all financial amount submission endpoints (API routes that accept monetary values). For each, check whether a maximum amount limit is enforced server-side. Quote the limit value found (e.g.,
max: 999999orMAX_AMOUNT = 10000). Also check client-side inputs formaxattributes. Report: "X of Y amount endpoints enforce a server-side maximum." -
Pass criteria: At least 100% of amount submission endpoints enforce a maximum limit server-side. The limit value is at least 1 and no more than a reasonable ceiling. Client-side also shows the constraint (HTML
maxor visible UI text). Report even on pass: "X endpoints enforce max limit of $Y." -
Fail criteria: Any amount endpoint accepts unbounded values server-side, or the limit is only client-side.
-
Skip (N/A) when: The project has no concept of amount limits (0 financial submission endpoints found, or explicitly unlimited by design).
-
Detail on fail: Example:
"Amount input has no max attribute. Server-side API accepts any amount value without limit check."or"HTML max='10000' set, but server-side API does not validate against this limit" -
Cross-reference: The min-amount-enforcement check in this category covers the lower bound; together they define the valid amount range.
-
Remediation: Enforce maximum amounts server-side in
src/app/api/route handlers:In
src/app/api/transfers/route.ts:const MAX_TRANSACTION_AMOUNT = 999999; // cents, i.e., $9,999.99 if (amountCents > MAX_TRANSACTION_AMOUNT) { throw new Error('Amount exceeds maximum limit'); }
External references
- cwe · CWE-20 — Improper Input Validation
- owasp:2021 · A03
- pci-dss:4.0 · Req-6.2.4 — Prevent common software attacks including injection and improper input validation
Taxons
History
- 2026-04-18·v1.0.0·Initial import from finserv-form-validation·automated