@bugspotter/sdk
Version:
Professional bug reporting SDK with screenshots, session replay, and automatic error capture for web applications
283 lines (282 loc) • 9.04 kB
JavaScript
;
/**
* PII Pattern Definitions
* Configurable regex patterns for detecting sensitive data (PII + credentials)
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.PATTERN_PRESETS = exports.PatternBuilder = exports.PATTERN_CATEGORIES = exports.DEFAULT_PATTERNS = void 0;
exports.getPatternsByPriority = getPatternsByPriority;
exports.getPattern = getPattern;
exports.getPatternsByCategory = getPatternsByCategory;
exports.getAllPatternNames = getAllPatternNames;
exports.createPatternConfig = createPatternConfig;
exports.validatePattern = validatePattern;
exports.mergePatternConfigs = mergePatternConfigs;
/**
* Default built-in patterns
*/
exports.DEFAULT_PATTERNS = {
email: {
name: 'email',
regex: /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g,
description: 'Email addresses',
examples: ['user@example.com', 'john.doe+tag@company.co.uk', 'test_user@sub.domain.com'],
priority: 1, // Highest priority - most specific
},
creditcard: {
name: 'creditcard',
regex: /\b(?:\d{4}[-\s]){3}\d{4}\b|\b\d{4}[-\s]\d{6}[-\s]\d{5}\b|\b\d{13,19}\b/g,
description: 'Credit card numbers (Visa, MC, Amex, Discover, etc.)',
examples: [
'4532-1488-0343-6467',
'4532148803436467',
'5425 2334 3010 9903',
'3782 822463 10005',
],
priority: 2,
},
ssn: {
name: 'ssn',
regex: /\b\d{3}-\d{2}-\d{4}\b|\b(?<!\d)\d{9}(?!\d)\b/g,
description: 'US Social Security Numbers',
examples: ['123-45-6789', '987654321'],
priority: 3,
},
iin: {
name: 'iin',
regex: /\b[0-9]{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12][0-9]|3[01])\d{6}\b/g,
description: 'Kazakhstan IIN/BIN (12 digits with date validation)',
examples: ['950315300123', '880612500456', '021225123456'],
priority: 4,
},
ip: {
name: 'ip',
regex: /\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b|(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\b/g,
description: 'IPv4 and IPv6 addresses',
examples: ['192.168.1.100', '127.0.0.1', '2001:0db8:85a3:0000:0000:8a2e:0370:7334'],
priority: 5,
},
phone: {
name: 'phone',
regex: /\+\d{1,3}[-.\s]\d{3}[-.\s]\d{4}\b|\+\d{1,3}[-.\s]\d{3}[-.\s]\d{3}[-.\s]\d{4}\b|\(\d{3}\)\s*\d{3}[-.\s]\d{4}\b|\b\d{3}[-.\s]\d{3}[-.\s]\d{4}\b/g,
description: 'International phone numbers',
examples: [
'+1-555-1234',
'+1-555-123-4567',
'(555) 123-4567',
'555-123-4567',
'+7 777 123 4567',
],
priority: 6,
},
apikey: {
name: 'apikey',
regex: /\b(?:sk|pk)_(?:live|test)_[a-zA-Z0-9]{24,}\b|AIza[a-zA-Z0-9_-]{35}|ya29\.[a-zA-Z0-9_-]+|AKIA[a-zA-Z0-9]{16}\b/g,
description: 'API keys (Stripe, Google, AWS, etc.)',
examples: [
'sk_live_abc123def456ghi789jkl',
'pk_test_xyz789abc123def456',
'AIzaSyD1234567890abcdefghijklmnopqrst',
'AKIAIOSFODNN7EXAMPLE',
],
priority: 7,
},
token: {
name: 'token',
regex: /\b(?:Bearer\s+)?[a-zA-Z0-9_-]{32,}\b|ghp_[a-zA-Z0-9]{36}|gho_[a-zA-Z0-9]{36}|github_pat_[a-zA-Z0-9_]{82}/g,
description: 'Authentication tokens (Bearer, GitHub, JWT-like)',
examples: [
'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9',
'ghp_abc123def456ghi789jkl012mno345pqr',
'gho_xyz789abc123def456ghi789jkl012mno',
],
priority: 8,
},
password: {
name: 'password',
regex: /(?:password|passwd|pwd)[\s:=]+[^\s]{6,}|(?:password|passwd|pwd)["']?\s*[:=]\s*["']?[^\s"']{6,}/gi,
description: 'Password fields in text (password=..., pwd:...)',
examples: ['password: MySecret123!', 'passwd=SecurePass456', 'pwd: "MyP@ssw0rd"'],
priority: 9,
},
};
/**
* Pattern categories for grouping
*/
exports.PATTERN_CATEGORIES = {
financial: ['creditcard', 'ssn'],
contact: ['email', 'phone'],
identification: ['ssn', 'iin'],
network: ['ip', 'email'],
credentials: ['apikey', 'token', 'password'],
kazakhstan: ['iin'],
};
/**
* Get patterns sorted by priority
*/
function getPatternsByPriority(patterns) {
return [...patterns].sort((a, b) => {
return a.priority - b.priority;
});
}
/**
* Get pattern by name
*/
function getPattern(name) {
return exports.DEFAULT_PATTERNS[name];
}
/**
* Get patterns by category
*/
function getPatternsByCategory(category) {
return exports.PATTERN_CATEGORIES[category].map((name) => {
return exports.DEFAULT_PATTERNS[name];
});
}
/**
* Get all pattern names
*/
function getAllPatternNames() {
return Object.keys(exports.DEFAULT_PATTERNS);
}
/**
* Custom pattern builder for advanced use cases
*/
class PatternBuilder {
constructor() {
this.pattern = {};
}
name(name) {
this.pattern.name = name;
return this;
}
regex(regex) {
// Ensure global flag
if (!regex.global) {
const flags = regex.flags.includes('g') ? regex.flags : regex.flags + 'g';
this.pattern.regex = new RegExp(regex.source, flags);
}
else {
this.pattern.regex = regex;
}
return this;
}
description(description) {
this.pattern.description = description;
return this;
}
examples(examples) {
this.pattern.examples = examples;
return this;
}
priority(priority) {
this.pattern.priority = priority;
return this;
}
build() {
var _a;
if (!this.pattern.name || !this.pattern.regex) {
throw new Error('Pattern must have at least name and regex');
}
return {
name: this.pattern.name,
regex: this.pattern.regex,
description: this.pattern.description || this.pattern.name,
examples: this.pattern.examples || [],
priority: (_a = this.pattern.priority) !== null && _a !== void 0 ? _a : 99,
};
}
}
exports.PatternBuilder = PatternBuilder;
/**
* Pre-configured pattern sets for common use cases
*/
exports.PATTERN_PRESETS = {
/** All patterns enabled (PII + credentials) - default */
all: getAllPatternNames(),
/** Minimal - only most critical PII */
minimal: ['email', 'creditcard', 'ssn'],
/** Financial data only */
financial: exports.PATTERN_CATEGORIES.financial,
/** Contact information only */
contact: exports.PATTERN_CATEGORIES.contact,
/** Identification numbers only */
identification: exports.PATTERN_CATEGORIES.identification,
/** Credentials and secrets only */
credentials: exports.PATTERN_CATEGORIES.credentials,
/** Kazakhstan-specific patterns */
kazakhstan: ['email', 'phone', 'iin'],
/** GDPR compliance recommended set */
gdpr: ['email', 'phone', 'ip'],
/** PCI DSS compliance required */
pci: ['creditcard'],
/** Security-focused: PII + credentials */
security: [
'email',
'phone',
'creditcard',
'ssn',
'apikey',
'token',
'password',
],
};
/**
* Create custom pattern configuration
*/
function createPatternConfig(preset) {
const names = typeof preset === 'string' ? exports.PATTERN_PRESETS[preset] : preset;
return names.map((name) => {
return exports.DEFAULT_PATTERNS[name];
});
}
/**
* Validate pattern regex
*/
function validatePattern(pattern) {
const errors = [];
if (!pattern.name) {
errors.push('Pattern must have a name');
}
if (!pattern.regex) {
errors.push('Pattern must have a regex');
}
else {
if (!pattern.regex.global) {
errors.push('Pattern regex must have global flag');
}
// Test regex doesn't cause catastrophic backtracking
try {
const testString = 'a'.repeat(1000);
const start = Date.now();
testString.match(pattern.regex);
const duration = Date.now() - start;
if (duration > 100) {
errors.push(`Pattern regex may cause performance issues (took ${duration}ms on test)`);
}
}
catch (error) {
errors.push(`Pattern regex error: ${error.message}`);
}
}
if (pattern.priority < 0) {
errors.push('Pattern priority must be non-negative');
}
return {
valid: errors.length === 0,
errors,
};
}
/**
* Merge pattern configurations
*/
function mergePatternConfigs(...configs) {
const merged = new Map();
configs.forEach((config) => {
config.forEach((pattern) => {
// Later configs override earlier ones
merged.set(pattern.name, pattern);
});
});
return getPatternsByPriority([...merged.values()]);
}