or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

browser.mdconfiguration.mdcore-logging.mdindex.mdmasking.md

masking.mddocs/

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