We ran 100,000 random card numbers through the Luhn check. 10% passed.

PromptScrub ships with eight rule groups. Seven are on by default. The eighth, credit card detection, is off, and people ask why a redaction tool would leave a rule for card numbers switched off.

The short answer is a number we measured: 10.17%.

What the Luhn check actually proves

Nearly every payment card number carries a checksum, calculated with an algorithm published by Hans Peter Luhn at IBM in 1954. Double every second digit from the right, subtract 9 from any result above 9, sum everything, and a valid card number comes out divisible by 10.

It is a good check for what it was designed for: catching a digit typed wrong at a checkout. It was never designed to answer "is this string a card number", and that is the question a redaction tool has to answer.

The measurement

We generated 100,000 random 16-digit strings and ran each through the same luhnOk() function the tool uses, with no other filtering:

随机 16 位数字串 100000 个, Luhn 通过: 10167 (10.17%)

That result is not surprising once you look at the algorithm. The checksum has ten possible outcomes and only one of them means "valid", so roughly one in ten arbitrary digit runs passes by coincidence. Luhn removes 90% of noise. It does not remove the last 10%.

Ten percent is small until you consider what it is ten percent of. A support transcript, an order confirmation, a shipping notification, a log file full of transaction IDs: these documents are dense with long digit runs. Flag one in ten of them as a credit card and the tool starts crying wolf, which is worse than useless. A person who learns to dismiss the warnings will dismiss the real one too.

So we tested real formats instead

Random strings are a worst case. The more useful question is whether the identifiers people actually paste get flagged. We ran seven real-world formats through the rule set, both with the default rules and with card detection switched on:

FormatExampleDefault rulesCard rule on
Amazon order number113-7782991-4406620no hitno hit
UPS tracking1Z999AA10123456784no hitno hit
FedEx tracking7712 3456 7890no hitno hit
ISBN-139780306406157no hitno hit
IMEI490154203237518no hitflagged
Invoice numberINV-2024-0098431no hitno hit
Unix timestamp (ms)1721800000000no hitno hit

Six of the seven survive even with the card rule enabled, because the rule requires either a 4-4-4-x grouping with one consistent separator, or an unbroken run of 13 to 19 digits, and then a passing Luhn check on top.

The IMEI is the instructive failure. IMEI numbers carry a Luhn checksum too, by design, and this one is 15 digits: inside the card-length window, and a valid checksum. There is no way to distinguish it from a card number by shape alone. Every phone in a device inventory is a false positive waiting to happen.

What this means for you

If you are pasting payment data, turn the rule on. It will catch what it is meant to catch.

If you are pasting a support transcript, a shipping log, or a device inventory, leave it off and rely on the seven default rules. You will not lose much: card numbers are rarer in ordinary business text than the other seven categories, and a card number that appears alongside an email address will still be surrounded by redacted context.

The general principle matters more than this one rule. Any tool that promises to find sensitive data by pattern alone is making a trade between what it misses and what it wrongly flags. A tool that hides that trade from you has made the decision on your behalf. Every rule here is a visible switch, and this article is the reasoning behind the one that ships off.

Check the arithmetic yourself

The Luhn implementation is fifteen lines and is served with the page. Open /js/scrub/rules.js, find luhnOk, and run the same experiment. If your number comes out different from ours, we would like to know.