Why card numbers in logs are a problem
A card number, or PAN (primary account number), is exactly what fraudsters want, and handling it is regulated. PCI DSS, the security standard for anyone who processes card data, requires the PAN to be masked when displayed, so that at most the BIN (the first digits, which identify the issuer) and the last four digits are visible. In PCI DSS 4.0 that is requirement 3.4.1. Stored PANs must be unreadable, and card security codes must not be kept at all after authorization.
A log file full of card numbers means the log storage, its backups and everyone who can read them are handling card data too.
How to recognize a card number
- Length: 13 to 19 digits, usually printed in groups of four. American Express uses 15 digits grouped 4, 6 and 5.
- Prefix: the first digits identify the network. Visa starts with 4, Mastercard with 51 to 55 or 2221 to 2720, American Express with 34 or 37.
- Checksum: the last digit is a Luhn check digit. Starting from the right, double every second digit, subtract 9 from any result over 9, and add everything up. A valid number gives a multiple of 10.
The Luhn check is what separates a card number from an order ID or a timestamp. It does not prove a card exists: the test numbers below all pass it.
Example: masking card numbers in a log
These are the standard test card numbers. Before highlights what PasteSafe finds, After is its exact output.
2026-09-15T09:41:09Z ERROR charge declined card=4242 4242 4242 4242 exp=12/34 cvc=123 name="Jane Doe"
2026-09-15T09:41:10Z INFO retry pan=5555555555554444 amount=49.00 currency=USD
2026-09-15T09:41:11Z INFO amex 3782 822463 10005 approved, receipt to jane.doe@example.com
2026-09-15T09:41:12Z WARN import row 88: 4242.4242.4242.4242 stored as 424242******42422026-09-15T09:41:09Z ERROR charge declined card=CARD_1 exp=12/34 cvc=123 name="Jane Doe"
2026-09-15T09:41:10Z INFO retry pan=CARD_2 amount=49.00 currency=USD
2026-09-15T09:41:11Z INFO amex CARD_3 approved, receipt to EMAIL_1
2026-09-15T09:41:12Z WARN import row 88: 4242.4242.4242.4242 stored as 424242******4242The Visa, Mastercard and American Express numbers each get their own placeholder. The expiry date, the CVC and the cardholder name stay, and so does the number written with dots, because PasteSafe only accepts spaces or dashes between groups. The already masked number is left alone, which is what you want.
Mask a card number in code
To display a card number, keep only the last four digits. In JavaScript:
const maskPan = pan => pan.replace(/\d(?=(?:\D*\d){4})/g, '*');
maskPan('4242 4242 4242 4242'); // '**** **** **** 4242'
To find card numbers in free text, match candidates first and keep only those that pass the Luhn check. In Python:
import re
CANDIDATE = re.compile(r'\b(?:\d[ -]?){12,18}\d\b')
def luhn_ok(digits):
total = 0
for i, d in enumerate(reversed(digits)):
n = int(d)
if i % 2:
n *= 2
if n > 9:
n -= 9
total += n
return total % 10 == 0
def mask_cards(text):
def repl(m):
digits = re.sub(r'\D', '', m.group())
return '[CARD]' if luhn_ok(digits) else m.group()
return CANDIDATE.sub(repl, text)
print(mask_cards('card 4242 4242 4242 4242 order 1234 5678 9012 3456'))
# card [CARD] order 1234 5678 9012 3456
This is a starting point: two numbers written next to each other can merge into one candidate that fails the check.
On the command line
sed -E 's/\b([0-9]{4}[ -]?){3}[0-9]{4}\b/[CARD]/g' payments.log > payments.masked.log
This masks any 16 digit number in groups of four. There is no Luhn check, so it also masks order numbers, and it misses 15 digit American Express numbers.
Clean a log with PasteSafe
- Paste the log into PasteSafe, or drop the file onto the editor.
- Card numbers that pass the prefix and Luhn checks become
CARD_1,CARD_2and so on. The same card always gets the same placeholder, so you can still see that two failed charges used the same card. - Remove expiry dates, CVCs and names by hand if they are in the log.
- Copy the cleaned text and share it.
What PasteSafe does not catch
- Expiry dates, CVCs and cardholder names.
- Numbers with dots or other separators between groups, and numbers that fail the Luhn check, such as a mistyped card number.
- Card numbers split across fields or lines.
It recognizes numbers that start like Visa, Mastercard, American Express, Diners Club, JCB, Discover and UnionPay cards. Check the result before you share it.
Questions
What does masking a credit card number mean?
Replacing most of its digits so the full number cannot be read, for example **** **** **** 4242. People can still recognize which card was used without seeing the number.
How many digits of a card number can I show?
PCI DSS allows at most the BIN and the last four digits to be displayed to people without a business need to see more. Most apps show only the last four.
How can I tell if a number is a credit card number?
Check the length (13 to 19 digits), the prefix and the Luhn checksum. A number that passes all three is shaped like a card number, but only the card network can say whether the card exists.
Does PasteSafe keep the card numbers it finds?
Only in the memory of your browser tab, so it can put them back into an AI reply if you ask it to. Nothing is uploaded or saved, and closing the tab clears it.