All 20 checks with why-it-matters prose, severity, and cross-references to related audits.
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.
Why this severity: Critical because an unblocked negative amount on the server layer enables direct ledger manipulation, allowing an attacker to reverse funds flow without authentication.
finserv-form-validation.currency-amount.negative-amounts-blockedSee full patternIEEE 754 floating-point arithmetic cannot represent most decimal fractions exactly. Storing `19.99` as a float in PostgreSQL or MongoDB introduces rounding errors that compound across thousands of transactions — a classic fintech data-integrity failure cited under CWE-681 (Incorrect Conversion Between Numeric Types) and CWE-682 (Incorrect Calculation). At scale, accumulated errors produce off-by-one-cent discrepancies in statements, reconciliation failures, and potential regulatory exposure under GAAP precision requirements. Integer cent storage eliminates the issue entirely: `1999` is exact in every language and database type system.
Why this severity: Critical because floating-point accumulation in monetary storage produces unbounded rounding drift that corrupts financial records and triggers compliance failures.
finserv-form-validation.currency-amount.integer-cents-storageSee full patternStandard `Math.round()` always rounds 0.5 upward, introducing a systematic positive bias in interest calculations. Over millions of compounding periods this bias is non-trivial and legally relevant — financial regulators and ISO 25010 functional-correctness standards expect rounding to be demonstrably unbiased. Banker's rounding (round-half-to-even) is the industry standard because it distributes rounding error evenly across the dataset. CWE-682 covers this class of incorrect calculation leading to incorrect financial results.
Why this severity: High because systematic rounding bias in interest accrual produces incorrect balances at scale, creating regulatory exposure and customer disputes.
finserv-form-validation.currency-amount.bankers-roundingSee full patternA client-side exchange rate is fetched at page load and may be stale seconds later. More critically, it can be tampered: any user with browser devtools can edit the rate in memory before submitting, receiving a conversion at an artificially favorable rate. OWASP A03 (Injection) and CWE-602 (Client-Side Enforcement of Server-Side Security) both flag trusting client-calculated financial values. PCI DSS Req-6.2.4 requires server-side validation of all input data used in financial operations.
Why this severity: High because a client-side exchange rate is directly tamper-able via devtools, enabling users to execute currency conversions at fraudulent rates.
finserv-form-validation.currency-amount.server-side-conversionSee full patternABA routing numbers embed a mod-10 checksum across all nine digits — a format-only regex like `/^\d{9}$/` accepts the vast majority of structurally invalid routing numbers that would fail at the ACH network. Invalid routing numbers cause failed or misdirected ACH transactions, NSF fees, and customer support costs. NACHA Operating Rules require validation of routing-number integrity before origination, and OWASP A03 names improper input validation among the top application-security failure modes. The fix is a 10-line checksum function, not a library dependency.
Why this severity: High because routing numbers without checksum validation allow invalid bank identifiers that cause ACH transaction failures and potential misdirected fund transfers.
finserv-form-validation.currency-amount.routing-number-checksumSee full patternFloating-point errors in a single step are small; across a multi-step chain they compound unpredictably. A refund pipeline that subtracts a fee, applies a discount, and then taxes the result in float arithmetic will produce a different final amount depending on the order of operations — a determinism failure that makes reconciliation impossible. CWE-682 covers incorrect calculation; ISO 25010 functional-correctness requires financial outputs to be exact. Even a one-cent error per transaction becomes a material accounting discrepancy at tens of thousands of monthly transactions.
Why this severity: High because floating-point intermediates in chained calculations produce non-deterministic results that break financial reconciliation and audit trails.
finserv-form-validation.currency-amount.no-float-accumulationSee full patternIBAN and US ABA account numbers have structurally incompatible formats — IBANs are 15-34 alphanumeric characters with a country prefix; US account numbers are 8-17 digits. A single generic regex that accepts either format will reject valid inputs from one region and accept invalid inputs from the other. OWASP A03 and PCI DSS Req-6.2.4 require input validation appropriate to the data type. Misrouted payments due to format confusion create irreversible ACH or SWIFT transactions, customer losses, and regulatory liability.
Why this severity: High because accepting incorrect account number formats routes payments to invalid destinations, causing irreversible transaction failures and potential fund loss.
finserv-form-validation.account-routing.account-format-validationSee full patternAn IBAN regex that validates structure but skips the mod-97 checksum accepts the majority of typoed IBANs — the check digit exists precisely to catch single-digit and transposition errors. Without it, `GB82WEST12345698765432` and `GB82WEST12345698765431` are indistinguishable to the validator, but only one is real. OWASP A03 treats insufficient input validation as an injection-class failure; an unvalidated IBAN that reaches payment processing triggers a failed SWIFT/SEPA transfer, chargeback risk, and customer trust damage.
Why this severity: Medium because format-only IBAN validation lets typoed account numbers through to payment processing, causing failed transfers and chargeback exposure.
finserv-form-validation.account-routing.iban-structure-validationSee full patternWithout 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.
Why this severity: Medium because unbounded server-side amounts enable over-limit transactions that the payment processor or banking rail will reject, corrupting order state.
finserv-form-validation.account-routing.max-amount-limitsSee full patternAccepting zero-amount or sub-minimum transactions creates two concrete problems: payment processors (Stripe, Adyen) reject amounts below their floor and return errors that must be handled; and zero-amount transactions that do commit pollute the ledger with noise records that complicate reconciliation. OWASP A03 covers this as inadequate input validation. The error message matters too — WCAG 2.2 SC 3.3.1 and 3.3.3 require error messages to identify the constraint, not just report failure, so users know what to correct.
Why this severity: Medium because zero and sub-minimum amounts cause payment processor rejections that surface as user-visible errors and create invalid ledger records.
finserv-form-validation.account-routing.min-amount-enforcementSee full patternEthereum EIP-55 mixed-case checksum and Bitcoin Base58Check both exist to catch single-character typos that would otherwise route funds to a valid-looking but incorrect address. A format-only regex (`/^0x[0-9a-fA-F]{40}$/`) accepts thousands of invalid checksummed Ethereum addresses — funds sent to those addresses are irreversibly lost. OWASP A03 applies: crypto wallet addresses are untrusted user input that requires structural validation, not just length checks.
Why this severity: Low because checksum-only failures affect a minority of malformed addresses, but any missed typo results in an irreversible fund loss with no recourse.
finserv-form-validation.account-routing.crypto-checksumSee full patternClient-side validation is UX; server-side validation is security. When the two diverge, the gap is exploitable: a client that allows `$0.01-$9,999.99` but a server with no upper bound means any user who bypasses the form (curl, Burp, modified JS) can submit arbitrary amounts. CWE-602 (Client-Side Enforcement of Server-Side Security) and OWASP A03 both flag this pattern. Parity isn't just a correctness concern — inconsistent constraints produce confusing UX when server validation rejects what the client accepted.
Why this severity: Low because mismatched constraints require an attacker to bypass client validation, which is trivial but limits casual exploitation to motivated users.
finserv-form-validation.calculation-accuracy.client-server-paritySee full patternAny fee or tax value that the server accepts directly from the client request body is tamper-able: a user reduces `fee` to 0 before submitting and pays less. This is OWASP A03 (Injection) and CWE-602 (Client-Side Enforcement of Server-Side Security) in one pattern. PCI DSS Req-6.2.4 requires server-side validation of all payment parameters. The client can display a fee preview for UX purposes — but the server must independently compute and verify the fee amount before it reaches the ledger.
Why this severity: Low because exploiting this requires a user to intentionally modify a network request, limiting exposure to motivated actors with basic HTTP tooling.
finserv-form-validation.calculation-accuracy.tax-fee-verificationSee full patternTwo calculation sites that both compute interest but use different rounding functions — one `Math.round()`, one `Math.floor()` — will produce different balances for identical inputs. The discrepancy shows up as a mismatch between the displayed APY and the actual accrued interest, leading to customer disputes and reconciliation failures. CWE-682 covers incorrect financial calculation; ISO 25010 maintainability requires that the same logical operation produce the same result regardless of call site.
Why this severity: Low because inconsistent rounding accumulates slowly and typically surfaces only during reconciliation or customer disputes, not as immediate transaction failures.
finserv-form-validation.calculation-accuracy.interest-rounding-consistencySee full patternAn APY input that accepts 500% or a discount input that accepts -20% doesn't just produce wrong results — it can crash downstream calculations, trigger integer overflow in cents conversion, or be exploited to generate artificially favorable rates. OWASP A03 covers unvalidated numeric inputs. Even without malicious intent, an accidental entry of `5` instead of `0.05` for a decimal rate doubles or quintuples a fee, producing silent data corruption that's hard to detect in logs.
Why this severity: Low because unrealistic percentage values typically fail at a downstream calculation step, limiting direct financial impact but creating data corruption risk.
finserv-form-validation.calculation-accuracy.percentage-range-validationSee full patternA client-submitted `grandTotal` that the server uses directly is tamper-able: subtract $5 from the total before submitting and pay less. CWE-602 and OWASP A03 both flag trusting client-calculated aggregates. PCI DSS Req-6.2.4 requires independent server-side validation of all payment amounts. This pattern is particularly risky because the individual components (subtotal, tax, fee) may each be validated correctly while the tampered total bypasses all of them.
Why this severity: Info because exploiting this requires deliberate request manipulation, and the mismatch is often caught by downstream payment processors — but it remains a meaningful integrity gap.
finserv-form-validation.calculation-accuracy.total-recalculationSee full patternMobile users who see a text keyboard instead of a numeric pad when entering a routing number or transfer amount experience significant friction: they must switch keyboard modes manually, increasing the chance of typos and form abandonment. WCAG 2.2 SC 1.3.5 (Identify Input Purpose) covers this by requiring inputs to expose their expected input type to browsers and assistive technology. While not a security issue, it directly impacts conversion rates for financial flows where precision matters most.
Why this severity: Low because incorrect inputmode degrades mobile UX and increases typo rates but does not expose data or enable exploitation.
finserv-form-validation.error-edge-cases.inputmode-attributesSee full patternNetwork timeouts cause users and retry logic to resubmit financial transactions. Without idempotency keys, each retry creates a new transaction: one timeout during a fund transfer can result in two or more debits from the same account. CWE-362 (race condition) covers this class of failure; OWASP A04 (Insecure Design) applies to payment flows without duplicate-submission protection. Idempotency is a standard transaction-integrity control across PCI-DSS-scoped systems (enforced through Requirement 6 engineering practices) and the Stripe / Square API security guides explicitly require idempotency keys on financial endpoints. Client-side submit-button disabling is not a substitute — it doesn't protect against server retries, load balancer replays, or network-level retransmission.
Why this severity: Medium because network retries in the absence of idempotency keys directly cause duplicate transactions and double charges, producing immediate financial harm.
finserv-form-validation.error-edge-cases.idempotency-keySee full patternA validation error that says "Invalid input" tells the user nothing about what to change. In a financial form, that friction causes abandonment — and for accessibility, WCAG 2.2 SC 3.3.1 (Error Identification) and SC 3.3.3 (Error Suggestion) require that errors both identify what is wrong and suggest a correction. "Amount must be between $0.01 and $9,999.99" passes both; "Validation failed" fails both. Generic messages also force users to guess which constraint was violated, producing support tickets that cost real money.
Why this severity: Info because generic error messages degrade UX and violate WCAG 2.2 SC 3.3.1 and 3.3.3 but do not directly expose data or enable exploitation.
finserv-form-validation.error-edge-cases.error-claritySee full patternFinancial calculation functions — rounding, interest accrual, fee application — are high-stakes and frequently modified. Without unit tests that cover zero amounts, min/max boundary values, and rounding-boundary inputs like $10.005, a refactor that silently changes behavior at those boundaries will ship undetected. ISO 25010 maintainability requires that critical business logic be verifiable without running the full application. Missing edge-case coverage is the most common root cause of financial bugs found only in production, often after incorrect charges have been issued.
Why this severity: Info because absent tests don't cause immediate failures but increase the probability of undetected regressions in financial calculation logic during future changes.
finserv-form-validation.error-edge-cases.calculation-testingSee full patternRun this audit in your AI coding tool (Claude Code, Cursor, Bolt, etc.) and submit results here for scoring and benchmarks.
Open Financial Form Validation Audit