Citibank / Revlon — August 11, 2020
Cost: ~$894M wired in error; ~$500M never recovered after Second Circuit reversal · Time-to-detect: discovered next morning; final legal recovery took 25+ months · Root cause class: T7 (UI / range invariant on payment routing fields)
What happened
On the night of August 11, 2020, Citibank intended to send Revlon's lenders a routine ~$7.8M interest payment. Instead, it wired the full $894M loan principal — money not due for three more years — to those lenders. Per the Southern District of New York's February 2021 opinion and the Second Circuit's September 2022 reversal, the operator was using a six-eyes wire-processing app called Flexcube. To route an interest payment correctly, three checkboxes had to be set with specific account routing values; only one was. The other two defaulted to Citibank's own internal wash account, which the system interpreted as "send the principal to the lenders." Three Citibank reviewers approved the screen. Some lenders refunded the money; others kept it. The Second Circuit ultimately ordered ~$500M returned.
The pattern
A multi-field form encoded a critical semantic invariant — "principal is only ever wired on a scheduled prepayment" — across the configuration of three independent UI controls, with no validation that the three were mutually consistent. Any system where a high-impact action requires N fields to be set in a coordinated way, with no write-time check that the combination is valid, has this exposure: dbt models with three macro args that must agree, ETL configs with overlapping enable flags, payment APIs with field combinations that mean different things together than apart.
How veric would catch it
veric supports range and combinatorial invariants on declared schema fields. In a PR adding a new wire-form configuration, the verifier would have flagged: "fields principal_account, front_account, fund_account jointly determine routing; combination (wash, wash, set) is reachable but lacks a stated allowed-output range — declare invariant or expect T7 violation at deploy." This is the T7 tier (information flow + range). Honest scope: veric would not have caught the operator's individual checkbox choice; it would have caught that the form's design permitted that combination at all — which is the actual root cause the courts and Citi's own auditors named.
Try it: open the example below and watch the verdict change as you toggle the offending pattern on and off.
See also
- /explore — the class — Revlon sits in the SQL-shaped-failure family alongside Knight, the London Whale, and the PHE truncation.
- Adjacent incidents: Knight Capital 2012, Robinhood 2021.
Sources
- In re Citibank August 11, 2020, No. 21-487 (2d Cir. Sept 8, 2022): https://law.justia.com/cases/federal/appellate-courts/ca2/21-487/21-487-2022-09-08.html
- PRMIA case study, "Citibank Transaction Processing for Revlon": https://prmia.org/common/Uploaded%20files/ORM%20Designation/PRMIA_Citibank-Revlon_021122.pdf
- Robert H. Smith School, "Lessons from Citi's Revlon Error": https://www.rhsmith.umd.edu/research/lessons-citis-revlon-error