An 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.
Medium because format-only IBAN validation lets typoed account numbers through to payment processing, causing failed transfers and chargeback exposure.
Extend the IBAN validator in src/lib/validators.ts to include the mod-97 step after format checking. The algorithm rearranges the IBAN and reduces it modulo 97.
// src/lib/validators.ts
export function validateIBAN(iban: string): boolean {
iban = iban.replace(/\s/g, '').toUpperCase();
if (!/^[A-Z]{2}\d{2}[A-Z0-9]{1,30}$/.test(iban)) return false;
const rearranged = iban.slice(4) + iban.slice(0, 4);
const numeric = rearranged.replace(/[A-Z]/g, c =>
(c.charCodeAt(0) - 55).toString()
);
return BigInt(numeric) % 97n === 1n;
}
Wire this into the Zod schema used by src/app/api/transfers/route.ts via .refine(validateIBAN, 'Invalid IBAN').
finserv-form-validation.account-routing.iban-structure-validationmedium% 97n === 1n or just /^[A-Z]{2}\d{2}/). Report: "X of Y IBAN validations include mod-97 checksum."/^[A-Z]{2}\d{2}[A-Z0-9]+$/ is the only validation — this accepts structurally invalid IBANs."IBAN validation only checks format (2 letters + 2 digits + alphanumeric). No mod-97 checksum validation — invalid IBANs would be accepted."src/lib/validators.ts. See the IBAN validation code in the account-format-validation check above.