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.
Medium because unbounded server-side amounts enable over-limit transactions that the payment processor or banking rail will reject, corrupting order state.
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.
ID: finserv-form-validation.account-routing.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: 999999 or MAX_AMOUNT = 10000). Also check client-side inputs for max attributes. 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 max or 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');
}