@feardread/fear 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/FEAR.js +459 -0
- package/FEARServer.js +280 -0
- package/controllers/agent.js +438 -0
- package/controllers/auth/index.js +345 -0
- package/controllers/auth/token.js +50 -0
- package/controllers/blog.js +105 -0
- package/controllers/brand.js +10 -0
- package/controllers/cart.js +425 -0
- package/controllers/category.js +9 -0
- package/controllers/coupon.js +63 -0
- package/controllers/crud/crud.js +508 -0
- package/controllers/crud/index.js +36 -0
- package/controllers/email.js +34 -0
- package/controllers/enquiry.js +65 -0
- package/controllers/events.js +9 -0
- package/controllers/order.js +125 -0
- package/controllers/payment.js +31 -0
- package/controllers/product.js +147 -0
- package/controllers/review.js +247 -0
- package/controllers/tag.js +10 -0
- package/controllers/task.js +10 -0
- package/controllers/upload.js +41 -0
- package/controllers/user.js +401 -0
- package/index.js +7 -0
- package/libs/agent/index.js +561 -0
- package/libs/agent/modules/ai/ai.js +285 -0
- package/libs/agent/modules/ai/chat.js +518 -0
- package/libs/agent/modules/ai/config.js +688 -0
- package/libs/agent/modules/ai/operations.js +787 -0
- package/libs/agent/modules/analyze/api.js +546 -0
- package/libs/agent/modules/analyze/dorks.js +395 -0
- package/libs/agent/modules/ccard/README.md +454 -0
- package/libs/agent/modules/ccard/audit.js +479 -0
- package/libs/agent/modules/ccard/checker.js +674 -0
- package/libs/agent/modules/ccard/payment-processors.json +16 -0
- package/libs/agent/modules/ccard/validator.js +629 -0
- package/libs/agent/modules/code/analyzer.js +303 -0
- package/libs/agent/modules/code/jquery.js +1093 -0
- package/libs/agent/modules/code/react.js +1536 -0
- package/libs/agent/modules/code/refactor.js +499 -0
- package/libs/agent/modules/crypto/exchange.js +564 -0
- package/libs/agent/modules/net/proxy.js +409 -0
- package/libs/agent/modules/security/cve.js +442 -0
- package/libs/agent/modules/security/monitor.js +360 -0
- package/libs/agent/modules/security/scanner.js +300 -0
- package/libs/agent/modules/security/vulnerability.js +506 -0
- package/libs/agent/modules/security/web.js +465 -0
- package/libs/agent/modules/utils/browser.js +492 -0
- package/libs/agent/modules/utils/colorizer.js +285 -0
- package/libs/agent/modules/utils/manager.js +478 -0
- package/libs/cloud/index.js +228 -0
- package/libs/config/db.js +21 -0
- package/libs/config/validator.js +82 -0
- package/libs/db/index.js +318 -0
- package/libs/emailer/imap.js +126 -0
- package/libs/emailer/info.js +41 -0
- package/libs/emailer/smtp.js +77 -0
- package/libs/handler/async.js +3 -0
- package/libs/handler/error.js +66 -0
- package/libs/handler/index.js +161 -0
- package/libs/logger/index.js +49 -0
- package/libs/logger/morgan.js +24 -0
- package/libs/passport/passport.js +109 -0
- package/libs/search/api.js +384 -0
- package/libs/search/features.js +219 -0
- package/libs/search/service.js +64 -0
- package/libs/swagger/config.js +18 -0
- package/libs/swagger/index.js +35 -0
- package/libs/validator/index.js +254 -0
- package/models/blog.js +31 -0
- package/models/brand.js +12 -0
- package/models/cart.js +14 -0
- package/models/category.js +11 -0
- package/models/coupon.js +9 -0
- package/models/customer.js +0 -0
- package/models/enquiry.js +29 -0
- package/models/events.js +13 -0
- package/models/order.js +94 -0
- package/models/product.js +32 -0
- package/models/review.js +14 -0
- package/models/tag.js +10 -0
- package/models/task.js +11 -0
- package/models/user.js +68 -0
- package/package.json +12 -0
- package/routes/agent.js +615 -0
- package/routes/auth.js +13 -0
- package/routes/blog.js +19 -0
- package/routes/brand.js +15 -0
- package/routes/cart.js +105 -0
- package/routes/category.js +16 -0
- package/routes/coupon.js +15 -0
- package/routes/enquiry.js +14 -0
- package/routes/events.js +16 -0
- package/routes/mail.js +170 -0
- package/routes/order.js +19 -0
- package/routes/product.js +22 -0
- package/routes/review.js +11 -0
- package/routes/task.js +12 -0
- package/routes/user.js +17 -0
|
@@ -0,0 +1,629 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const colorizer = require('../utils/colorizer');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Card Validator Module
|
|
7
|
+
* Educational module for validating and analyzing payment card numbers
|
|
8
|
+
* DOES NOT GENERATE REAL CARD NUMBERS - For security testing education only
|
|
9
|
+
*/
|
|
10
|
+
class CardValidator {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.name = 'Card Validator';
|
|
13
|
+
|
|
14
|
+
// BIN (Bank Identification Number) database for card type detection
|
|
15
|
+
this.binRanges = {
|
|
16
|
+
visa: {
|
|
17
|
+
name: 'Visa',
|
|
18
|
+
prefixes: ['4'],
|
|
19
|
+
lengths: [13, 16, 19],
|
|
20
|
+
cvvLength: 3
|
|
21
|
+
},
|
|
22
|
+
mastercard: {
|
|
23
|
+
name: 'Mastercard',
|
|
24
|
+
prefixes: ['51', '52', '53', '54', '55', '2221-2720'],
|
|
25
|
+
lengths: [16],
|
|
26
|
+
cvvLength: 3
|
|
27
|
+
},
|
|
28
|
+
amex: {
|
|
29
|
+
name: 'American Express',
|
|
30
|
+
prefixes: ['34', '37'],
|
|
31
|
+
lengths: [15],
|
|
32
|
+
cvvLength: 4
|
|
33
|
+
},
|
|
34
|
+
discover: {
|
|
35
|
+
name: 'Discover',
|
|
36
|
+
prefixes: ['6011', '622126-622925', '644', '645', '646', '647', '648', '649', '65'],
|
|
37
|
+
lengths: [16, 19],
|
|
38
|
+
cvvLength: 3
|
|
39
|
+
},
|
|
40
|
+
dinersclub: {
|
|
41
|
+
name: 'Diners Club',
|
|
42
|
+
prefixes: ['300', '301', '302', '303', '304', '305', '36', '38'],
|
|
43
|
+
lengths: [14, 16],
|
|
44
|
+
cvvLength: 3
|
|
45
|
+
},
|
|
46
|
+
jcb: {
|
|
47
|
+
name: 'JCB',
|
|
48
|
+
prefixes: ['3528-3589'],
|
|
49
|
+
lengths: [16, 19],
|
|
50
|
+
cvvLength: 3
|
|
51
|
+
},
|
|
52
|
+
unionpay: {
|
|
53
|
+
name: 'UnionPay',
|
|
54
|
+
prefixes: ['62'],
|
|
55
|
+
lengths: [16, 17, 18, 19],
|
|
56
|
+
cvvLength: 3
|
|
57
|
+
},
|
|
58
|
+
maestro: {
|
|
59
|
+
name: 'Maestro',
|
|
60
|
+
prefixes: ['5018', '5020', '5038', '5893', '6304', '6759', '6761', '6762', '6763'],
|
|
61
|
+
lengths: [12, 13, 14, 15, 16, 17, 18, 19],
|
|
62
|
+
cvvLength: 3
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// Test card numbers from official payment processor documentation
|
|
67
|
+
this.testCards = {
|
|
68
|
+
stripe: [
|
|
69
|
+
{ number: '4242424242424242', type: 'Visa', description: 'Stripe test card - succeeds' },
|
|
70
|
+
{ number: '4000056655665556', type: 'Visa (debit)', description: 'Stripe test card - succeeds' },
|
|
71
|
+
{ number: '5555555555554444', type: 'Mastercard', description: 'Stripe test card - succeeds' },
|
|
72
|
+
{ number: '378282246310005', type: 'Amex', description: 'Stripe test card - succeeds' }
|
|
73
|
+
],
|
|
74
|
+
paypal: [
|
|
75
|
+
{ number: '4111111111111111', type: 'Visa', description: 'PayPal test card' },
|
|
76
|
+
{ number: '5555555555554444', type: 'Mastercard', description: 'PayPal test card' }
|
|
77
|
+
]
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Luhn Algorithm (Mod 10) - Used to validate card numbers
|
|
83
|
+
*/
|
|
84
|
+
luhnCheck(cardNumber) {
|
|
85
|
+
const digits = cardNumber.replace(/\D/g, '');
|
|
86
|
+
let sum = 0;
|
|
87
|
+
let isEven = false;
|
|
88
|
+
|
|
89
|
+
// Process digits from right to left
|
|
90
|
+
for (let i = digits.length - 1; i >= 0; i--) {
|
|
91
|
+
let digit = parseInt(digits[i], 10);
|
|
92
|
+
|
|
93
|
+
if (isEven) {
|
|
94
|
+
digit *= 2;
|
|
95
|
+
if (digit > 9) {
|
|
96
|
+
digit -= 9;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
sum += digit;
|
|
101
|
+
isEven = !isEven;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return sum % 10 === 0;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Detect card type from number
|
|
109
|
+
*/
|
|
110
|
+
detectCardType(cardNumber) {
|
|
111
|
+
const digits = cardNumber.replace(/\D/g, '');
|
|
112
|
+
|
|
113
|
+
for (const [key, card] of Object.entries(this.binRanges)) {
|
|
114
|
+
for (const prefix of card.prefixes) {
|
|
115
|
+
if (prefix.includes('-')) {
|
|
116
|
+
// Handle ranges like "2221-2720"
|
|
117
|
+
const [start, end] = prefix.split('-').map(Number);
|
|
118
|
+
const cardPrefix = parseInt(digits.substring(0, start.toString().length), 10);
|
|
119
|
+
if (cardPrefix >= start && cardPrefix <= end) {
|
|
120
|
+
return { type: key, ...card };
|
|
121
|
+
}
|
|
122
|
+
} else {
|
|
123
|
+
if (digits.startsWith(prefix)) {
|
|
124
|
+
return { type: key, ...card };
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return { type: 'unknown', name: 'Unknown', prefixes: [], lengths: [], cvvLength: 3 };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Validate a card number
|
|
135
|
+
*/
|
|
136
|
+
validateCard(args) {
|
|
137
|
+
if (args.length === 0) {
|
|
138
|
+
console.log(colorizer.error('Usage: validate-card <card-number>'));
|
|
139
|
+
console.log(colorizer.info('Example: validate-card 4242424242424242'));
|
|
140
|
+
return Promise.resolve();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const cardNumber = args.join('').replace(/\s/g, '');
|
|
144
|
+
const digits = cardNumber.replace(/\D/g, '');
|
|
145
|
+
|
|
146
|
+
console.log(colorizer.section('Card Number Validation'));
|
|
147
|
+
console.log(colorizer.cyan(' Card Number: ') + colorizer.dim(this.formatCardNumber(digits)));
|
|
148
|
+
console.log();
|
|
149
|
+
|
|
150
|
+
// Detect card type
|
|
151
|
+
const cardType = this.detectCardType(digits);
|
|
152
|
+
console.log(colorizer.cyan(' Card Type: ') + colorizer.bright(cardType.name));
|
|
153
|
+
|
|
154
|
+
// Check length
|
|
155
|
+
const lengthValid = cardType.lengths.includes(digits.length);
|
|
156
|
+
const lengthStatus = lengthValid ? colorizer.green('✓ Valid') : colorizer.red('✗ Invalid');
|
|
157
|
+
console.log(colorizer.cyan(' Length: ') + digits.length + ' ' + lengthStatus);
|
|
158
|
+
|
|
159
|
+
if (!lengthValid && cardType.lengths.length > 0) {
|
|
160
|
+
console.log(colorizer.dim(' Expected: ' + cardType.lengths.join(', ') + ' digits'));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Luhn check
|
|
164
|
+
const luhnValid = this.luhnCheck(digits);
|
|
165
|
+
const luhnStatus = luhnValid ? colorizer.green('✓ Valid') : colorizer.red('✗ Invalid');
|
|
166
|
+
console.log(colorizer.cyan(' Luhn Check: ') + luhnStatus);
|
|
167
|
+
|
|
168
|
+
// Overall validation
|
|
169
|
+
const isValid = lengthValid && luhnValid && cardType.type !== 'unknown';
|
|
170
|
+
console.log();
|
|
171
|
+
console.log(colorizer.cyan(' Overall Status: ') +
|
|
172
|
+
(isValid ? colorizer.green('✓ VALID FORMAT') : colorizer.red('✗ INVALID')));
|
|
173
|
+
|
|
174
|
+
// Check if it's a known test card
|
|
175
|
+
const testCard = this.findTestCard(digits);
|
|
176
|
+
if (testCard) {
|
|
177
|
+
console.log();
|
|
178
|
+
console.log(colorizer.yellow(' ⚠ This is a known test card:'));
|
|
179
|
+
console.log(colorizer.dim(' ' + testCard.description));
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
console.log();
|
|
183
|
+
console.log(colorizer.warning('Note: This only validates format. Does not verify if card is active or has funds.'));
|
|
184
|
+
console.log();
|
|
185
|
+
|
|
186
|
+
return Promise.resolve();
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Batch validate multiple cards
|
|
191
|
+
*/
|
|
192
|
+
validateBatch(args) {
|
|
193
|
+
if (args.length === 0) {
|
|
194
|
+
console.log(colorizer.error('Usage: validate-batch <file.txt>'));
|
|
195
|
+
console.log(colorizer.info('File should contain one card number per line'));
|
|
196
|
+
return Promise.resolve();
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const filePath = args[0];
|
|
200
|
+
|
|
201
|
+
if (!fs.existsSync(filePath)) {
|
|
202
|
+
console.log(colorizer.error('File not found: ' + filePath));
|
|
203
|
+
return Promise.resolve();
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
207
|
+
const cards = content.split('\n')
|
|
208
|
+
.map(line => line.trim())
|
|
209
|
+
.filter(line => line && !line.startsWith('#'));
|
|
210
|
+
|
|
211
|
+
console.log(colorizer.section('Batch Card Validation'));
|
|
212
|
+
console.log(colorizer.dim('Processing ' + cards.length + ' card numbers...'));
|
|
213
|
+
console.log();
|
|
214
|
+
|
|
215
|
+
const results = {
|
|
216
|
+
valid: 0,
|
|
217
|
+
invalid: 0,
|
|
218
|
+
details: []
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
cards.forEach((cardNumber, index) => {
|
|
222
|
+
const digits = cardNumber.replace(/\D/g, '');
|
|
223
|
+
const cardType = this.detectCardType(digits);
|
|
224
|
+
const lengthValid = cardType.lengths.includes(digits.length);
|
|
225
|
+
const luhnValid = this.luhnCheck(digits);
|
|
226
|
+
const isValid = lengthValid && luhnValid && cardType.type !== 'unknown';
|
|
227
|
+
|
|
228
|
+
if (isValid) results.valid++;
|
|
229
|
+
else results.invalid++;
|
|
230
|
+
|
|
231
|
+
results.details.push({
|
|
232
|
+
number: this.maskCardNumber(digits),
|
|
233
|
+
type: cardType.name,
|
|
234
|
+
valid: isValid,
|
|
235
|
+
luhn: luhnValid,
|
|
236
|
+
length: lengthValid
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
const status = isValid ? colorizer.green('✓') : colorizer.red('✗');
|
|
240
|
+
console.log(colorizer.numbered(index + 1,
|
|
241
|
+
status + ' ' + this.maskCardNumber(digits) + ' - ' + colorizer.dim(cardType.name)));
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
console.log();
|
|
245
|
+
console.log(colorizer.cyan('Summary:'));
|
|
246
|
+
console.log(colorizer.green(' Valid: ' + results.valid));
|
|
247
|
+
console.log(colorizer.red(' Invalid: ' + results.invalid));
|
|
248
|
+
console.log(colorizer.cyan(' Total: ' + cards.length));
|
|
249
|
+
console.log();
|
|
250
|
+
|
|
251
|
+
return Promise.resolve();
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Analyze BIN (Bank Identification Number)
|
|
256
|
+
*/
|
|
257
|
+
analyzeBIN(args) {
|
|
258
|
+
if (args.length === 0) {
|
|
259
|
+
console.log(colorizer.error('Usage: analyze-bin <bin-number>'));
|
|
260
|
+
console.log(colorizer.info('Example: analyze-bin 424242'));
|
|
261
|
+
console.log(colorizer.dim('BIN is typically the first 6-8 digits of a card number'));
|
|
262
|
+
return Promise.resolve();
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const bin = args[0].replace(/\D/g, '');
|
|
266
|
+
|
|
267
|
+
if (bin.length < 4) {
|
|
268
|
+
console.log(colorizer.error('BIN must be at least 4 digits'));
|
|
269
|
+
return Promise.resolve();
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
console.log(colorizer.section('BIN Analysis'));
|
|
273
|
+
console.log(colorizer.cyan(' BIN: ') + colorizer.bright(bin));
|
|
274
|
+
console.log();
|
|
275
|
+
|
|
276
|
+
// Detect card type from BIN
|
|
277
|
+
const cardType = this.detectCardType(bin + '0000000000');
|
|
278
|
+
|
|
279
|
+
console.log(colorizer.cyan(' Card Network: ') + colorizer.bright(cardType.name));
|
|
280
|
+
console.log(colorizer.cyan(' Valid Lengths: ') + cardType.lengths.join(', ') + ' digits');
|
|
281
|
+
console.log(colorizer.cyan(' CVV Length: ') + cardType.cvvLength + ' digits');
|
|
282
|
+
console.log();
|
|
283
|
+
|
|
284
|
+
console.log(colorizer.dim('BIN Information:'));
|
|
285
|
+
console.log(colorizer.dim(' • First digit: ' + bin[0] + ' - Major Industry Identifier (MII)'));
|
|
286
|
+
|
|
287
|
+
const miiMap = {
|
|
288
|
+
'0': 'ISO/TC 68 and other future industry assignments',
|
|
289
|
+
'1': 'Airlines',
|
|
290
|
+
'2': 'Airlines and other future industry assignments',
|
|
291
|
+
'3': 'Travel and entertainment',
|
|
292
|
+
'4': 'Banking and financial',
|
|
293
|
+
'5': 'Banking and financial',
|
|
294
|
+
'6': 'Merchandising and banking/financial',
|
|
295
|
+
'7': 'Petroleum and other future industry assignments',
|
|
296
|
+
'8': 'Healthcare, telecommunications and other future industry assignments',
|
|
297
|
+
'9': 'National assignment'
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
console.log(colorizer.dim(' ' + (miiMap[bin[0]] || 'Unknown')));
|
|
301
|
+
console.log(colorizer.dim(' • First 6 digits: Bank Identification Number (BIN)'));
|
|
302
|
+
console.log(colorizer.dim(' • Identifies the institution that issued the card'));
|
|
303
|
+
console.log();
|
|
304
|
+
|
|
305
|
+
return Promise.resolve();
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Show test cards from various payment processors
|
|
310
|
+
*/
|
|
311
|
+
showTestCards(args) {
|
|
312
|
+
console.log(colorizer.section('Official Test Card Numbers'));
|
|
313
|
+
console.log(colorizer.warning('These cards are for testing ONLY and will not work in production'));
|
|
314
|
+
console.log();
|
|
315
|
+
|
|
316
|
+
Object.entries(this.testCards).forEach(([processor, cards]) => {
|
|
317
|
+
console.log(colorizer.cyan(processor.toUpperCase() + ' Test Cards:'));
|
|
318
|
+
cards.forEach(card => {
|
|
319
|
+
console.log(colorizer.bullet(
|
|
320
|
+
colorizer.bright(this.formatCardNumber(card.number)) +
|
|
321
|
+
' - ' + card.type
|
|
322
|
+
));
|
|
323
|
+
console.log(colorizer.dim(' ' + card.description));
|
|
324
|
+
});
|
|
325
|
+
console.log();
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
console.log(colorizer.info('Always use official test cards provided by your payment processor'));
|
|
329
|
+
console.log(colorizer.dim('• Stripe: https://stripe.com/docs/testing'));
|
|
330
|
+
console.log(colorizer.dim('• PayPal: https://developer.paypal.com/tools/sandbox/card-testing/'));
|
|
331
|
+
console.log();
|
|
332
|
+
|
|
333
|
+
return Promise.resolve();
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Explain card validation algorithms
|
|
338
|
+
*/
|
|
339
|
+
explainAlgorithm(args) {
|
|
340
|
+
console.log(colorizer.section('Card Validation Algorithms'));
|
|
341
|
+
console.log();
|
|
342
|
+
|
|
343
|
+
console.log(colorizer.cyan('1. Luhn Algorithm (Mod 10 Check)'));
|
|
344
|
+
console.log(colorizer.dim(' Used to validate card numbers and detect typos'));
|
|
345
|
+
console.log();
|
|
346
|
+
console.log(colorizer.dim(' How it works:'));
|
|
347
|
+
console.log(colorizer.dim(' a) Start from the rightmost digit (check digit)'));
|
|
348
|
+
console.log(colorizer.dim(' b) Moving left, double every second digit'));
|
|
349
|
+
console.log(colorizer.dim(' c) If doubling results in > 9, subtract 9'));
|
|
350
|
+
console.log(colorizer.dim(' d) Sum all digits'));
|
|
351
|
+
console.log(colorizer.dim(' e) If sum % 10 = 0, the number is valid'));
|
|
352
|
+
console.log();
|
|
353
|
+
|
|
354
|
+
console.log(colorizer.cyan(' Example: 4242 4242 4242 4242'));
|
|
355
|
+
console.log(colorizer.dim(' 4 2 4 2 4 2 4 2 4 2 4 2 4 2 4 2'));
|
|
356
|
+
console.log(colorizer.dim(' × 2 × 2 × 2 × 2 × 2 × 2 × 2 ×'));
|
|
357
|
+
console.log(colorizer.dim(' 8 2 8 2 8 2 8 2 8 2 8 2 8 2 8 2'));
|
|
358
|
+
console.log(colorizer.dim(' Sum: 8+2+8+2+8+2+8+2+8+2+8+2+8+2+8+2 = 80'));
|
|
359
|
+
console.log(colorizer.dim(' 80 % 10 = 0 → Valid! ✓'));
|
|
360
|
+
console.log();
|
|
361
|
+
|
|
362
|
+
console.log(colorizer.cyan('2. BIN Validation'));
|
|
363
|
+
console.log(colorizer.dim(' • First 6-8 digits identify the issuing institution'));
|
|
364
|
+
console.log(colorizer.dim(' • First digit (MII) identifies the industry'));
|
|
365
|
+
console.log(colorizer.dim(' • Different card types have specific BIN ranges'));
|
|
366
|
+
console.log();
|
|
367
|
+
|
|
368
|
+
console.log(colorizer.cyan('3. Length Validation'));
|
|
369
|
+
console.log(colorizer.dim(' • Visa: 13, 16, or 19 digits'));
|
|
370
|
+
console.log(colorizer.dim(' • Mastercard: 16 digits'));
|
|
371
|
+
console.log(colorizer.dim(' • American Express: 15 digits'));
|
|
372
|
+
console.log(colorizer.dim(' • Discover: 16 or 19 digits'));
|
|
373
|
+
console.log();
|
|
374
|
+
|
|
375
|
+
console.log(colorizer.cyan('4. CVV/CVC Validation'));
|
|
376
|
+
console.log(colorizer.dim(' • Most cards: 3 digits on back'));
|
|
377
|
+
console.log(colorizer.dim(' • American Express: 4 digits on front'));
|
|
378
|
+
console.log(colorizer.dim(' • Never stored after authorization (PCI DSS)'));
|
|
379
|
+
console.log();
|
|
380
|
+
|
|
381
|
+
console.log(colorizer.info('Security Note:'));
|
|
382
|
+
console.log(colorizer.warning('These algorithms only validate FORMAT, not if a card is:'));
|
|
383
|
+
console.log(colorizer.dim(' • Actually issued and active'));
|
|
384
|
+
console.log(colorizer.dim(' • Has sufficient funds'));
|
|
385
|
+
console.log(colorizer.dim(' • Authorized for the transaction'));
|
|
386
|
+
console.log();
|
|
387
|
+
|
|
388
|
+
return Promise.resolve();
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Generate educational report on card security
|
|
393
|
+
*/
|
|
394
|
+
securityReport(args) {
|
|
395
|
+
const outputFile = args[0] || 'card-security-report.txt';
|
|
396
|
+
|
|
397
|
+
console.log(colorizer.section('Generating Card Security Report'));
|
|
398
|
+
console.log();
|
|
399
|
+
|
|
400
|
+
const report = this.generateSecurityReport();
|
|
401
|
+
|
|
402
|
+
fs.writeFileSync(outputFile, report);
|
|
403
|
+
|
|
404
|
+
console.log(colorizer.green('✓ Report saved to: ' + outputFile));
|
|
405
|
+
console.log(colorizer.dim(' Lines: ' + report.split('\n').length));
|
|
406
|
+
console.log(colorizer.dim(' Size: ' + (report.length / 1024).toFixed(2) + ' KB'));
|
|
407
|
+
console.log();
|
|
408
|
+
|
|
409
|
+
return Promise.resolve();
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Helper: Generate security report content
|
|
414
|
+
*/
|
|
415
|
+
generateSecurityReport() {
|
|
416
|
+
const date = new Date().toISOString().split('T')[0];
|
|
417
|
+
|
|
418
|
+
return `
|
|
419
|
+
PAYMENT CARD SECURITY REPORT
|
|
420
|
+
Generated: ${date}
|
|
421
|
+
=============================================================================
|
|
422
|
+
|
|
423
|
+
1. CARD NUMBER STRUCTURE
|
|
424
|
+
|
|
425
|
+
A payment card number consists of:
|
|
426
|
+
- IIN/BIN (Issuer Identification Number): First 6-8 digits
|
|
427
|
+
- Account Number: Middle digits
|
|
428
|
+
- Check Digit: Last digit (calculated using Luhn algorithm)
|
|
429
|
+
|
|
430
|
+
2. VALIDATION METHODS
|
|
431
|
+
|
|
432
|
+
a) Luhn Algorithm (Mod 10)
|
|
433
|
+
- Industry standard since 1960s
|
|
434
|
+
- Detects single-digit errors and most transpositions
|
|
435
|
+
- Does NOT validate if card is real or active
|
|
436
|
+
|
|
437
|
+
b) BIN Database Validation
|
|
438
|
+
- Verifies card type matches expected patterns
|
|
439
|
+
- Checks if BIN is from a known issuer
|
|
440
|
+
|
|
441
|
+
c) Length Validation
|
|
442
|
+
- Different card types have specific lengths
|
|
443
|
+
- Visa: 13, 16, or 19 digits
|
|
444
|
+
- Mastercard: 16 digits
|
|
445
|
+
- Amex: 15 digits
|
|
446
|
+
|
|
447
|
+
3. SECURITY STANDARDS
|
|
448
|
+
|
|
449
|
+
PCI DSS (Payment Card Industry Data Security Standard):
|
|
450
|
+
- Never store CVV/CVC after authorization
|
|
451
|
+
- Encrypt cardholder data in transit and at rest
|
|
452
|
+
- Mask PAN (Primary Account Number) when displayed
|
|
453
|
+
- Implement strong access controls
|
|
454
|
+
- Regular security testing and monitoring
|
|
455
|
+
|
|
456
|
+
4. COMMON VULNERABILITIES
|
|
457
|
+
|
|
458
|
+
a) Card Testing/Carding
|
|
459
|
+
- Automated testing of card numbers
|
|
460
|
+
- Prevention: Rate limiting, CAPTCHA, fraud detection
|
|
461
|
+
|
|
462
|
+
b) BIN Attacks
|
|
463
|
+
- Using valid BINs to generate card numbers
|
|
464
|
+
- Prevention: Velocity checks, device fingerprinting
|
|
465
|
+
|
|
466
|
+
c) Man-in-the-Middle
|
|
467
|
+
- Intercepting card data in transit
|
|
468
|
+
- Prevention: TLS/SSL encryption, tokenization
|
|
469
|
+
|
|
470
|
+
d) SQL Injection
|
|
471
|
+
- Extracting card data from databases
|
|
472
|
+
- Prevention: Parameterized queries, input validation
|
|
473
|
+
|
|
474
|
+
5. BEST PRACTICES FOR DEVELOPERS
|
|
475
|
+
|
|
476
|
+
a) Never Store Sensitive Data
|
|
477
|
+
- Don't store CVV/CVC
|
|
478
|
+
- Don't store magnetic stripe data
|
|
479
|
+
- Use tokenization when possible
|
|
480
|
+
|
|
481
|
+
b) Use Payment Processors
|
|
482
|
+
- Stripe, PayPal, Square handle PCI compliance
|
|
483
|
+
- Reduces your compliance scope
|
|
484
|
+
- Better fraud protection
|
|
485
|
+
|
|
486
|
+
c) Implement Proper Validation
|
|
487
|
+
- Client-side: Luhn check, format validation
|
|
488
|
+
- Server-side: Full validation, fraud checks
|
|
489
|
+
- Never trust client-side validation alone
|
|
490
|
+
|
|
491
|
+
d) Use Test Cards for Development
|
|
492
|
+
- Official test cards from payment processors
|
|
493
|
+
- Never use real card numbers in development
|
|
494
|
+
- Implement test/production environment separation
|
|
495
|
+
|
|
496
|
+
6. TESTING GUIDELINES
|
|
497
|
+
|
|
498
|
+
Approved Testing Methods:
|
|
499
|
+
- Use official test cards from processors
|
|
500
|
+
- Stripe: 4242 4242 4242 4242
|
|
501
|
+
- PayPal: 4111 1111 1111 1111
|
|
502
|
+
- Test in sandbox/test environments only
|
|
503
|
+
|
|
504
|
+
NEVER:
|
|
505
|
+
- Generate random card numbers for testing
|
|
506
|
+
- Use real card numbers in test environments
|
|
507
|
+
- Test against production payment systems
|
|
508
|
+
- Share or expose test credentials
|
|
509
|
+
|
|
510
|
+
7. REGULATORY COMPLIANCE
|
|
511
|
+
|
|
512
|
+
Key Regulations:
|
|
513
|
+
- PCI DSS: Payment card security standards
|
|
514
|
+
- GDPR: Data protection (EU)
|
|
515
|
+
- CCPA: Consumer privacy (California)
|
|
516
|
+
- SOX: Financial reporting accuracy
|
|
517
|
+
|
|
518
|
+
Requirements:
|
|
519
|
+
- Annual security audits
|
|
520
|
+
- Vulnerability scanning
|
|
521
|
+
- Penetration testing
|
|
522
|
+
- Incident response plans
|
|
523
|
+
- Employee security training
|
|
524
|
+
|
|
525
|
+
8. FRAUD PREVENTION TECHNIQUES
|
|
526
|
+
|
|
527
|
+
a) Address Verification Service (AVS)
|
|
528
|
+
- Matches billing address with card issuer
|
|
529
|
+
|
|
530
|
+
b) CVV Verification
|
|
531
|
+
- Ensures card is physically present
|
|
532
|
+
|
|
533
|
+
c) 3D Secure (3DS)
|
|
534
|
+
- Two-factor authentication for online payments
|
|
535
|
+
- Verified by Visa, Mastercard SecureCode
|
|
536
|
+
|
|
537
|
+
d) Device Fingerprinting
|
|
538
|
+
- Tracks device characteristics
|
|
539
|
+
- Identifies suspicious patterns
|
|
540
|
+
|
|
541
|
+
e) Machine Learning
|
|
542
|
+
- Behavioral analysis
|
|
543
|
+
- Anomaly detection
|
|
544
|
+
- Real-time risk scoring
|
|
545
|
+
|
|
546
|
+
9. INCIDENT RESPONSE
|
|
547
|
+
|
|
548
|
+
If Card Data is Compromised:
|
|
549
|
+
1. Immediately notify payment processor
|
|
550
|
+
2. Contact law enforcement
|
|
551
|
+
3. Preserve forensic evidence
|
|
552
|
+
4. Notify affected cardholders
|
|
553
|
+
5. Conduct security audit
|
|
554
|
+
6. Implement corrective measures
|
|
555
|
+
7. Document incident and response
|
|
556
|
+
|
|
557
|
+
10. RESOURCES
|
|
558
|
+
|
|
559
|
+
Standards & Documentation:
|
|
560
|
+
- PCI Security Standards Council: www.pcisecuritystandards.org
|
|
561
|
+
- OWASP Payment Testing: owasp.org
|
|
562
|
+
|
|
563
|
+
Payment Processor Documentation:
|
|
564
|
+
- Stripe: stripe.com/docs/security
|
|
565
|
+
- PayPal: developer.paypal.com/docs/security
|
|
566
|
+
- Square: squareup.com/us/en/developers/security
|
|
567
|
+
|
|
568
|
+
Security Testing:
|
|
569
|
+
- OWASP ZAP: zaproxy.org
|
|
570
|
+
- Burp Suite: portswigger.net
|
|
571
|
+
- Metasploit: metasploit.com
|
|
572
|
+
|
|
573
|
+
=============================================================================
|
|
574
|
+
END OF REPORT
|
|
575
|
+
|
|
576
|
+
DISCLAIMER: This report is for educational purposes only. Always follow
|
|
577
|
+
your payment processor's guidelines and comply with PCI DSS requirements.
|
|
578
|
+
`;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* Helper: Format card number for display
|
|
583
|
+
*/
|
|
584
|
+
formatCardNumber(number) {
|
|
585
|
+
const digits = number.replace(/\D/g, '');
|
|
586
|
+
const cardType = this.detectCardType(digits);
|
|
587
|
+
|
|
588
|
+
// American Express: 4-6-5 format
|
|
589
|
+
if (cardType.type === 'amex') {
|
|
590
|
+
return digits.replace(/(\d{4})(\d{6})(\d{5})/, '$1 $2 $3');
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
// Most cards: 4-4-4-4 format
|
|
594
|
+
return digits.replace(/(\d{4})/g, '$1 ').trim();
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/**
|
|
598
|
+
* Helper: Mask card number for security
|
|
599
|
+
*/
|
|
600
|
+
maskCardNumber(number) {
|
|
601
|
+
const digits = number.replace(/\D/g, '');
|
|
602
|
+
if (digits.length < 8) return '****';
|
|
603
|
+
|
|
604
|
+
const first4 = digits.substring(0, 4);
|
|
605
|
+
const last4 = digits.substring(digits.length - 4);
|
|
606
|
+
const masked = '*'.repeat(digits.length - 8);
|
|
607
|
+
|
|
608
|
+
return first4 + masked + last4;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
/**
|
|
612
|
+
* Helper: Find if card is a known test card
|
|
613
|
+
*/
|
|
614
|
+
findTestCard(number) {
|
|
615
|
+
const digits = number.replace(/\D/g, '');
|
|
616
|
+
|
|
617
|
+
for (const processor of Object.values(this.testCards)) {
|
|
618
|
+
for (const card of processor) {
|
|
619
|
+
if (card.number === digits) {
|
|
620
|
+
return card;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
return null;
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
module.exports = CardValidator;
|