A CVV attack pattern is the fingerprint that card testing leaves in your authorization logs. You see short bursts of small or zero-dollar requests, a narrow BIN range, a decline rate far above baseline, and several attempts stacked on the same card in a few minutes. It looks nothing like shopping. It looks like a script checking whether a card number, expiry date, and security code still work together.
Why the pattern has that shape
Whoever is running the test does not care about your product. They care about a yes or no from the issuer. So they push volume through the cheapest path available: the smallest possible order, a card verification with no charge, or an authorization that will be voided. Each approval tells them a card is live. Each decline tells them to drop it.
The result is a signal that is loud in aggregate and quiet per transaction. One $1.00 authorization is noise. Four hundred of them in twenty minutes across a BIN range, from a handful of IPs, is a card testing run.
Signals I watch for
- Authorization velocity per card. More than two or three attempts on the same PAN inside a short window, especially with differing amounts.
- Amount clustering. Lots of requests at $0.00, $1.00, or other round figures that no real catalog produces.
- Decline ratio spikes. A sudden jump in issuer declines and CVV mismatches, concentrated in a few minutes rather than spread across a day.
- BIN concentration. Traffic that walks through sequential or adjacent card numbers, which is the clearest single indicator of enumeration.
- Identity drift. Card country, IP country, and billing address country that do not agree, rotated across attempts.
- Session behavior. No product views, no cart, no address book, straight to checkout and back out.
- Email and device reuse. One email or device fingerprint spread across dozens of distinct cards.
What gets mistaken for card testing
False positives are the reason teams turn detection off, so it pays to rule them out first. Dunning retries on subscription billing produce clusters of small attempts on the same card, but they come from one customer and one merchant ID. A failed checkout with client-side retry logic can fire three requests in five seconds. Travelers trigger geo mismatch flags constantly. And some legitimate businesses do sell $1.00 authorization holds.
The distinguishing factor is usually breadth. A retry loop touches one card. Card testing touches many cards from one small set of origins.
Building detection that lasts
I start with the fields that are already in the authorization payload and rarely leave them: PAN token, BIN, amount, response code, timestamp, IP, device ID, and email. From there, two rules catch most of it. First, a rolling count of attempts per PAN token over ten minutes. Second, a rolling count of distinct PAN tokens per IP, device, or email over the same window. Alert on the second one at a threshold well below what a busy day looks like.
Then layer in a decline-rate monitor per BIN. A BIN that normally declines 6 percent of the time and suddenly declines 70 percent is under attack or is the source of an attack. Both matter.
Response, in order
- Throttle or challenge the origin, not the whole checkout. Broad blocks cost you real sales.
- Require CVV and AVS for any authorization in the flagged window.
- Void and re-verify authorizations tied to the cluster before capture.
- Feed confirmed bad PAN tokens into your blocklist and share the pattern with your acquirer.
- Keep the logs. Chargeback disputes and issuer investigations both hinge on whether you can show what happened and when.
One last thing: a quiet period is not proof of a fix. Card testing moves to whichever merchant is easiest that week, so the pattern tends to return with a different BIN range and a new set of IPs. The rules that hold up are the ones keyed to behavior across many cards, not to any single bad actor.