Currency inputs reject negative values at validation layer
Why it matters
A currency input that allows negative values on either layer hands an attacker a trivial path to credit-back fraud: submit a negative transfer amount and the ledger logic subtracts from the recipient instead of the sender. OWASP A03 (Injection) and PCI DSS Req-6.2.4 both treat unvalidated numeric inputs as critical exposure. Client-side only guards are bypassed with a two-second curl command, so the server must independently reject any value below zero before it touches business logic or database writes.
Severity rationale
Critical because an unblocked negative amount on the server layer enables direct ledger manipulation, allowing an attacker to reverse funds flow without authentication.
Remediation
Add a min="0" attribute to the HTML input and a z.number().min(0) constraint in the server route. Both layers must enforce the rule independently — client validation is a UX aid, not a security control.
// src/app/api/transfers/route.ts
const schema = z.object({
amountCents: z.number().int().min(0, 'Amount must be non-negative'),
});
const { amountCents } = schema.parse(await req.json());
For the form component in src/components/TransferForm.tsx, add type="number" min="0" step="0.01" to the input element.
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the Financial Form Validation Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
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