A high-performance, security-focused utility to mask strings β perfect for hiding secrets, emails, API keys, credit cards, and sensitive data. Fully customizable with zero dependencies.
- π Production-Ready Security - Built-in DoS protection, input sanitization, and secure error handling
- β‘ Blazing Fast - Optimized for performance: 10,000+ operations/sec on small strings
- π― Smart Presets - Email, credit card, and phone number patterns built-in
- π Unicode-Safe - Handles emojis, multi-byte characters, and special characters correctly
- βοΈ Highly Customizable - Multiple masking modes: standard, full, reverse, percentage-based
- πͺΆ Zero Dependencies - Lightweight with no external dependencies
- π§ͺ 100% Test Coverage - Extensively tested with 100+ test cases including stress tests
- π§ TypeScript First - Fully typed with comprehensive type definitions
- π¦ Universal - Works in Node.js, browsers, and all modern bundlers
- π‘οΈ Safe by Default - Validates all inputs, prevents common vulnerabilities
npm install obscure-string
# or
yarn add obscure-string
# or
pnpm add obscure-stringconst { obscureString } = require('obscure-string');
// Basic usage
obscureString('mysecretkey');
// β 'mys******ey'
// Custom configuration
obscureString('john.doe@example.com', {
prefixLength: 2,
suffixLength: 4,
maskChar: '#',
});
// β 'jo##############.com'
// Email preset
obscureString('john.doe@example.com', { preset: 'email' });
// β 'jo******@example.com'
// Credit card preset
obscureString('4111-1111-1111-1111', { preset: 'creditCard' });
// β '************1111'
// Batch processing
const { obscureStringBatch } = require('obscure-string');
obscureStringBatch(['secret1', 'secret2', 'secret3']);
// β ['sec**t1', 'sec**t2', 'sec**t3']Optimized for real-world usage with smart algorithms:
- Small strings (< 100 chars): 10,000+ operations/second
- Large strings (10K chars): 100+ operations/second
- Batch processing: 1,000 strings in < 100ms
Perfect for high-traffic logging systems and real-time applications.
Built with security in mind from day one:
- DoS Protection: Configurable
maxLengthprevents memory exhaustion - Input Sanitization: Validates and safely handles all input types
- No Data Leaks: Errors never expose sensitive information
- XSS Safe: Doesn't introduce injection vulnerabilities
- Zero Dependencies: No supply chain risks
Correctly handles the modern web:
- Emojis:
πsecretπβπse***etπ - Multi-byte chars:
γγγ«γ‘γ―βγγ*γ«γ‘γ― - Special chars:
<script>β<sc***ipt> - Mixed content:
user@δΎγ.comβuse****com
Flexible options for any use case:
- Standard: Show prefix and suffix (default)
- Full Mask: Hide everything
- Reverse Mask: Show middle, hide edges
- Percentage: Mask a specific percentage
- Presets: Smart patterns for emails, cards, phones
Main function to obscure a string.
| Parameter | Type | Description |
|---|---|---|
str |
string | null | undefined |
The string to obscure |
options |
ObscureStringOptions |
Configuration options (optional) |
| Option | Type | Default | Description |
|---|---|---|---|
maskChar |
string |
'*' |
Character(s) to use for masking |
prefixLength |
number |
3 |
Visible characters at the beginning |
suffixLength |
number |
3 |
Visible characters at the end |
minMaskLength |
number |
0 |
Minimum masked characters required |
fullMask |
boolean |
false |
Mask the entire string |
reverseMask |
boolean |
false |
Show middle, hide edges |
percentage |
number |
- | Mask a percentage (0-100) |
maxLength |
number |
1000000 |
Max string length (DoS protection) |
preset |
string |
- | Use preset: 'email', 'creditCard', 'phone' |
string- The masked string
// Standard masking
obscureString('mysecretkey');
// β 'mys******ey'
// Custom mask character
obscureString('secret', { maskChar: 'β' });
// β 'secββt'
// Longer mask character
obscureString('secret', { maskChar: '...' });
// β 'sec......t'
// Custom prefix/suffix
obscureString('confidential', { prefixLength: 5, suffixLength: 2 });
// β 'confi****al'
// Minimum mask length (won't mask if too short)
obscureString('test', { prefixLength: 1, suffixLength: 1, minMaskLength: 5 });
// β 'test' (unchanged because mask would only be 2 chars)Efficiently mask multiple strings with the same options.
| Parameter | Type | Description |
|---|---|---|
strings |
string[] |
Array of strings to obscure |
options |
ObscureStringOptions |
Configuration options (optional) |
string[]- Array of masked strings
const { obscureStringBatch } = require('obscure-string');
const secrets = [
'api_key_12345',
'api_key_67890',
'api_key_abcde'
];
obscureStringBatch(secrets, { prefixLength: 7, suffixLength: 2 });
// β [
// 'api_key***45',
// 'api_key***90',
// 'api_key***de'
// ]Analyze how a string would be masked without actually masking it.
| Parameter | Type | Description |
|---|---|---|
str |
string | null | undefined |
The string to analyze |
options |
ObscureStringOptions |
Configuration options (optional) |
MaskInfo- Information about the masking
interface MaskInfo {
willBeMasked: boolean;
reason?: string;
originalLength?: number;
maskedLength?: number;
visibleChars?: number;
maskedChars?: number;
prefixLength?: number;
suffixLength?: number;
}const { getMaskInfo } = require('obscure-string');
getMaskInfo('mysecretkey');
// β {
// willBeMasked: true,
// originalLength: 11,
// maskedLength: 5,
// visibleChars: 6,
// maskedChars: 5,
// prefixLength: 3,
// suffixLength: 3
// }
getMaskInfo('short');
// β {
// willBeMasked: false,
// reason: 'string too short',
// originalLength: 5
// }Hide the entire string:
obscureString('sensitive', { fullMask: true });
// β '*********'
obscureString('data', { fullMask: true, maskChar: 'β' });
// β 'ββββ'Show the middle, hide the edges (useful for showing token types):
obscureString('sk_live_1234567890abcdef', {
reverseMask: true,
prefixLength: 3,
suffixLength: 3
});
// β '***live_1234567890abc***'Mask a specific percentage of the string:
obscureString('1234567890', { percentage: 50 });
// β '12***67890'
obscureString('test', { percentage: 75 });
// β '****'Shows first 2 chars of local part and full domain:
obscureString('john.doe@example.com', { preset: 'email' });
// β 'jo******@example.com'
obscureString('support@company.org', { preset: 'email' });
// β 'su*****@company.org'Shows only last 4 digits:
obscureString('4111111111111111', { preset: 'creditCard' });
// β '************1111'
obscureString('4111-1111-1111-1111', { preset: 'creditCard' });
// β '************1111'Shows only last 4 digits:
obscureString('1234567890', { preset: 'phone' });
// β '******7890'
obscureString('(123) 456-7890', { preset: 'phone' });
// β '******7890'const logger = {
log: (msg, data) => {
// Automatically mask sensitive fields
const safe = {
...data,
apiKey: obscureString(data.apiKey),
email: obscureString(data.email, { preset: 'email' }),
creditCard: obscureString(data.creditCard, { preset: 'creditCard' })
};
console.log(msg, safe);
}
};
logger.log('User checkout', {
apiKey: 'sk_live_1234567890abcdef',
email: 'user@example.com',
creditCard: '4111-1111-1111-1111'
});
// Logs safe versions: 'sk_***def', 'us**@example.com', '************1111'function sanitizeResponse(user) {
return {
...user,
email: obscureString(user.email, { preset: 'email' }),
phone: obscureString(user.phone, { preset: 'phone' }),
ssn: obscureString(user.ssn, { prefixLength: 0, suffixLength: 4 })
};
}const sensitiveStrings = logs.map(log => log.apiKey);
const maskedStrings = obscureStringBatch(sensitiveStrings, {
prefixLength: 7,
suffixLength: 4
});function smartMask(value, showFull = false) {
if (showFull) return value;
const info = getMaskInfo(value);
if (!info.willBeMasked) {
return obscureString(value, { fullMask: true });
}
return obscureString(value);
}All inputs are validated and sanitized:
obscureString(null) // β ''
obscureString(undefined) // β ''
obscureString('') // β ''
obscureString(12345) // β Coerced to string
obscureString('x'.repeat(1e7)) // β Throws RangeError (DoS protection)Configurable maximum length prevents memory exhaustion:
// Default limit: 1 million characters
obscureString(veryLongString);
// Custom limit
obscureString(longString, { maxLength: 10000 });Errors never leak sensitive data:
try {
obscureString('password123', { maskChar: '' });
} catch (e) {
// Error message does NOT contain 'password123'
console.log(e.message); // β "maskChar must be a non-empty string"
}Safely handles potentially malicious input:
obscureString('<script>alert("xss")</script>');
// β '<sc*******************ript>'
obscureString("'; DROP TABLE users; --");
// β "'; ***************; --"Optimized for different string sizes:
| String Size | Operations/sec | Use Case |
|---|---|---|
| 10 chars | 10,000+ | API keys, tokens |
| 100 chars | 5,000+ | URLs, addresses |
| 1,000 chars | 1,000+ | Documents, configs |
| 10,000 chars | 100+ | Large text blocks |
- Batch Processing: Use
obscureStringBatch()for multiple strings - Reuse Options: Pass the same options object for repeated calls
- Check First: Use
getMaskInfo()to avoid unnecessary masking - Set Limits: Use
maxLengthto prevent processing huge strings
Full TypeScript definitions included:
import {
obscureString,
obscureStringBatch,
getMaskInfo,
type ObscureStringOptions,
type MaskInfo
} from 'obscure-string';
const options: ObscureStringOptions = {
maskChar: '*',
prefixLength: 3,
suffixLength: 3,
preset: 'email'
};
const result: string = obscureString('test@example.com', options);
const info: MaskInfo = getMaskInfo('test', options);npm test # Run all tests with coverage
npm run test:watch # Run tests in watch modeThe test suite includes:
- β 100+ test cases
- β Unit tests for all features
- β Performance benchmarks
- β Security edge cases
- β Unicode handling tests
- β Stress tests with large strings
- β Integration tests
| Feature | obscure-string | string-mask | redact-pii |
|---|---|---|---|
| Zero dependencies | β | β | β |
| TypeScript | β | β | β |
| Unicode support | β | β | |
| DoS protection | β | β | β |
| Presets | β | β | β |
| Performance | β‘ Fast | π Slow | β‘ Fast |
| Bundle size | < 1KB | > 5KB | > 10KB |
| Batch processing | β | β | β |
| Reverse masking | β | β | β |
npm run formatUses Prettier with .prettierrc config.
The package includes a command-line interface for quick masking:
npm install -g obscure-string
# or use npx
npx obscure-string <string> [options]# Basic masking
obscure-string "mysecretkey"
# β mys******ey
# Custom prefix/suffix and mask character
obscure-string "my-secret-token" --prefix 2 --suffix 4 --char "#"
# β my##########oken
# Email preset
obscure-string "john.doe@example.com" --preset email
# β jo******@example.com
# Credit card preset
obscure-string "4111111111111111" --preset creditCard
# β ************1111
# Full masking
obscure-string "sensitive" --full
# β *********
# Percentage-based
obscure-string "1234567890" --percentage 50
# β 12***67890| Option | Alias | Description | Example |
|---|---|---|---|
--prefix <num> |
-p |
Visible chars at start | -p 2 |
--suffix <num> |
-s |
Visible chars at end | -s 4 |
--char <char> |
-c |
Mask character | -c "#" |
--preset <type> |
Use preset (email, creditCard, phone) | --preset email |
|
--full |
Mask entire string | --full |
|
--reverse |
Show middle, hide edges | --reverse |
|
--percentage <num> |
Mask percentage (0-100) | --percentage 50 |
|
--min-mask <num> |
Min masked chars required | --min-mask 5 |
|
--max-length <num> |
Max string length (DoS protection) | --max-length 10000 |
|
--help |
-h |
Show help message | -h |
# Hide API keys in logs
echo "API_KEY=sk_live_1234567890" | obscure-string "sk_live_1234567890" -p 7 -s 4
# Mask email addresses
obscure-string "support@company.com" --preset email
# Process multiple values (using xargs)
cat secrets.txt | xargs -I {} obscure-string {}Contributions welcome! Please:
- π΄ Fork the repo
- π Create a feature branch
- β Add tests and update docs
- π Open a pull request
See CHANGELOG.md for version history.
MIT Β© PDR
If you find this package useful, please consider giving it a β on GitHub!
string-maskβ Pattern-based masking (more complex)redact-piiβ Automatic PII redactioncommon-tagsβ Tag helpers for strings
Made with β€οΈ to keep your secrets secret.