0
# Masking Utilities
1
2
Security-focused utilities for parsing masking patterns and applying masks to sensitive data in log messages. These utilities enable safe logging by automatically obfuscating credentials, tokens, passwords, and other sensitive information using regex patterns.
3
4
## Capabilities
5
6
### Pattern Parsing
7
8
Parse comma-separated regex pattern strings into an array of RegExp objects for use in masking operations.
9
10
```typescript { .api }
11
/**
12
* Parses comma-separated regex patterns into RegExp objects
13
* Supports both /pattern/flags and plain pattern formats
14
* @param maskingRegexString - String containing regex patterns separated by commas
15
* @returns Array of RegExp objects or undefined if input is invalid
16
*/
17
function parseMaskingPatterns(
18
maskingRegexString: string | undefined
19
): RegExp[] | undefined;
20
```
21
22
**Supported Pattern Formats:**
23
- **Plain patterns**: `--key=[^ ]*` (becomes `new RegExp('--key=[^ ]*')`)
24
- **With flags**: `/--key=[^ ]*/i` (becomes `new RegExp('--key=[^ ]*', 'i')`)
25
- **Multiple patterns**: `--key=[^ ]*,--secret=[^ ]*` (comma-separated)
26
- **With capturing groups**: `/--key=([^ ]*)/i` (only captured groups are masked)
27
28
**Usage Examples:**
29
30
```typescript
31
import { parseMaskingPatterns } from '@wdio/logger';
32
33
// Parse simple patterns
34
const patterns1 = parseMaskingPatterns('--key=[^ ]*,--secret=[^ ]*');
35
// Returns: [/--key=[^ ]*/, /--secret=[^ ]*/]
36
37
// Parse patterns with flags
38
const patterns2 = parseMaskingPatterns('/--key=([^ ]*)/i,/password=([^ ]*)/gi');
39
// Returns: [/--key=([^ ]*)/i, /password=([^ ]*)/gi]
40
41
// Handle mixed formats
42
const patterns3 = parseMaskingPatterns('token=[^ ]*,/bearer\\s+([^ ]*)/i');
43
// Returns: [/token=[^ ]*/, /bearer\s+([^ ]*)/i]
44
45
// Invalid patterns are filtered out
46
const patterns4 = parseMaskingPatterns('valid=[^ ]*,invalid[,another=[^ ]*');
47
// Returns: [/valid=[^ ]*/, /another=[^ ]*/] (invalid pattern excluded)
48
49
// Handle undefined/empty input
50
const patterns5 = parseMaskingPatterns(undefined);
51
// Returns: undefined
52
53
const patterns6 = parseMaskingPatterns('');
54
// Returns: []
55
```
56
57
### Text Masking
58
59
Apply masking patterns to text, replacing sensitive data with a masked placeholder.
60
61
```typescript { .api }
62
/**
63
* Masks sensitive data in text using provided masking patterns
64
* @param text - The text to mask
65
* @param maskingPatterns - Array of RegExp patterns to use for masking
66
* @returns The masked text, or original text if no patterns provided
67
*/
68
function mask(
69
text: string,
70
maskingPatterns: RegExp[] | undefined
71
): string;
72
```
73
74
**Masking Behavior:**
75
- **No capturing groups**: Entire match is replaced with `**MASKED**`
76
- **With capturing groups**: Only captured groups are replaced with `**MASKED**`
77
- **Multiple matches**: All matches are replaced
78
- **Newline preservation**: Trailing newlines are preserved
79
80
**Usage Examples:**
81
82
```typescript
83
import { mask, parseMaskingPatterns } from '@wdio/logger';
84
85
// Basic masking without capturing groups
86
const patterns1 = parseMaskingPatterns('--key=[^ ]*');
87
const result1 = mask('Command: wdio --key=secretKey123 --verbose', patterns1);
88
// Result: "Command: wdio **MASKED** --verbose"
89
90
// Masking with capturing groups (more precise)
91
const patterns2 = parseMaskingPatterns('/--key=([^ ]*)/');
92
const result2 = mask('Command: wdio --key=secretKey123 --verbose', patterns2);
93
// Result: "Command: wdio --key=**MASKED** --verbose"
94
95
// Multiple patterns and matches
96
const patterns3 = parseMaskingPatterns('/--key=([^ ]*)/,/--token=([^ ]*)/');
97
const result3 = mask('wdio --key=secret --token=abc123 test', patterns3);
98
// Result: "wdio --key=**MASKED** --token=**MASKED** test"
99
100
// Complex patterns with flags
101
const patterns4 = parseMaskingPatterns('/authorization:\\s*bearer\\s+([^ ]*)/i');
102
const result4 = mask('Headers: { Authorization: Bearer token123 }', patterns4);
103
// Result: "Headers: { Authorization: Bearer **MASKED** }"
104
105
// Multiple capturing groups
106
const patterns5 = parseMaskingPatterns('/user:([^ ]*) pass:([^ ]*)/');
107
const result5 = mask('Connecting with user:admin pass:secret123', patterns5);
108
// Result: "Connecting with user:**MASKED** pass:**MASKED**"
109
110
// Preserve newlines
111
const text = 'Line 1: --key=secret\nLine 2: normal\n';
112
const result6 = mask(text, parseMaskingPatterns('--key=([^ ]*)'));
113
// Result: "Line 1: --key=**MASKED**\nLine 2: normal\n"
114
```
115
116
### Masking Constant
117
118
Constant string used as replacement text for masked sensitive data.
119
120
```typescript { .api }
121
/**
122
* String constant used to replace masked sensitive data
123
*/
124
const SENSITIVE_DATA_REPLACER: "**MASKED**";
125
```
126
127
**Usage Examples:**
128
129
```typescript
130
import { SENSITIVE_DATA_REPLACER } from '@wdio/logger';
131
132
// Use in custom masking implementations
133
function customMask(text: string, pattern: RegExp): string {
134
return text.replace(pattern, SENSITIVE_DATA_REPLACER);
135
}
136
137
// Check for masked content
138
function containsMaskedData(text: string): boolean {
139
return text.includes(SENSITIVE_DATA_REPLACER);
140
}
141
142
// Custom validation
143
if (logMessage.includes(SENSITIVE_DATA_REPLACER)) {
144
console.log('Log contains masked sensitive data');
145
}
146
```
147
148
## Advanced Pattern Examples
149
150
### Common Security Patterns
151
152
```typescript
153
import { parseMaskingPatterns, mask } from '@wdio/logger';
154
155
// AWS credentials
156
const awsPatterns = parseMaskingPatterns(
157
'/aws_access_key_id=([^ ]*)/i,/aws_secret_access_key=([^ ]*)/i'
158
);
159
160
// Database connections
161
const dbPatterns = parseMaskingPatterns(
162
'/password=([^ ]*)/i,/pwd=([^ ]*)/i,/connectionString=([^ ]*)/i'
163
);
164
165
// API tokens and keys
166
const apiPatterns = parseMaskingPatterns(
167
'/authorization:\\s*bearer\\s+([^ ]*)/i,/api[_-]?key=([^ ]*)/i,/token=([^ ]*)/i'
168
);
169
170
// URLs with credentials
171
const urlPatterns = parseMaskingPatterns(
172
'/\\/\\/([^:]+):([^@]+)@/g' // Matches user:pass in URLs
173
);
174
175
const logText = 'Connecting to mongodb://user:password123@localhost:27017/db';
176
const masked = mask(logText, urlPatterns);
177
// Result: "Connecting to mongodb://**MASKED**:**MASKED**@localhost:27017/db"
178
```
179
180
### Complex Patterns
181
182
```typescript
183
// JSON structures
184
const jsonPatterns = parseMaskingPatterns(
185
'/"password"\\s*:\\s*"([^"]*)"/,/"token"\\s*:\\s*"([^"]*)"/,/"secret"\\s*:\\s*"([^"]*)"/i'
186
);
187
188
const jsonLog = 'Request body: {"username": "admin", "password": "secret123"}';
189
const maskedJson = mask(jsonLog, jsonPatterns);
190
// Result: 'Request body: {"username": "admin", "password": "**MASKED**"}'
191
192
// Command line arguments
193
const cmdPatterns = parseMaskingPatterns(
194
'/--[a-zA-Z-]*(?:key|pass|secret|token)[a-zA-Z-]*[=\\s]+([^ ]*)/gi'
195
);
196
197
const cmdLog = 'Executing: myapp --api-key secret123 --db-password mypass --verbose';
198
const maskedCmd = mask(cmdLog, cmdPatterns);
199
// Result: "Executing: myapp --api-key **MASKED** --db-password **MASKED** --verbose"
200
```
201
202
## Security Considerations
203
204
- **Pattern Safety**: All patterns are validated using `safe-regex2` to prevent ReDoS attacks
205
- **Performance**: Patterns are compiled once and reused across log messages
206
- **Memory**: Failed pattern compilation returns `undefined` (filtered out) rather than throwing
207
- **Precision**: Use capturing groups for precise masking rather than masking entire matches
208
- **Testing**: Always test patterns with sample data to ensure correct masking behavior