isCreditCard: Mastercard regex anchoring bug accepts 4-digit and partial strings
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 84/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Quiet
- Tech stack
- javascript
- Domain
- backend
Research direction
Start in src/lib/isCreditCard.js by reading the Mastercard pattern and checking the other card regexes with alternation. Reproduce the short-string cases from the issue, then verify that Mastercard inputs are rejected when too short while valid 16-digit examples remain accepted. Done means the anchoring behavior is corrected consistently without breaking valid card formats.
Written by the indexing model from the issue text.
Description
Description
isCreditCard returns true for the 4-digit string "5108" (and many other short or partial strings) due to a regex anchoring bug in the Mastercard pattern.
Reproduction (validator 13.15.35, the latest version on npm at time of writing)
const v = require("validator");
console.log(v.isCreditCard("5108")); // true — expected false
console.log(v.isCreditCard("5108", { provider: "mastercard" })); // true — expected false
console.log(v.isCreditCard("5105105105105100")); // true — correct
Root cause
The Mastercard regex in src/lib/isCreditCard.js is:
mastercard: /^5[1-5][0-9]{2}|(222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}$/
Because | has lower precedence than ^ and $ anchors, the regex engine actually parses this as the union of two patterns:
^5[1-5][0-9]{2}— start-anchored only, matches any string beginning with51XX–55XXregardless of length (so"5108","5108foo", etc. all match).(222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}$— end-anchored only.
Result: format validation degenerates to "starts with 51-55 anywhere" or "ends with 2-series BIN + 12 digits anywhere".
The same shape (single-anchor due to | precedence) appears in a few other card regexes in this file; worth a quick audit.
Suggested fix
Wrap the alternation in a non-capturing group so both anchors bind to all branches:
- mastercard: /^5[1-5][0-9]{2}|(222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}$/
+ mastercard: /^(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}$/
After the fix, isCreditCard("5108") correctly returns false, and the valid 16-digit cases continue to return true.
Property that fails
// All credit-card-valid strings must have length within the documented per-issuer length ranges
// (Mastercard: 16; including 19-digit private/extension forms it's still ≥ 13).
function prop(s) {
if (v.isCreditCard(s, { provider: "mastercard" })) {
return s.length >= 13; // every passing input must be at least 13 chars
}
return true;
}
prop("5108"); // false — invariant violated
Environment
- validator:
13.15.35(also reproduces in13.12.0, so likely all 13.x) - Node: 20+
Happy to submit a PR if helpful.
- Dominant language
- JavaScript
- Stars
- 23.7k
- Forks
- 2.5k
- PR merge metrics
- No merged PRs in 30d
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from validatorjs/validator.js
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
validatorjs/validator.js#2885 ·
-
🐛 bug
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
validatorjs/validator.js#2862 ·
-
🐛 bug
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
validatorjs/validator.js#2861 ·
-
🐛 bug
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
validatorjs/validator.js#2860 ·
-
🐛 bug
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
validatorjs/validator.js#2859 ·
All issues in validatorjs/validator.js
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
HarperFast/skills#96 ·
-
[Block] Latest Posts [Type] Bug
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Automattic/studio#4908 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
sugarlabs/musicblocks#8847 ·