CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-wdio--logger

A helper utility for logging of WebdriverIO packages with enhanced features like progress logging and masking patterns for secure logging

Pending
Overview
Eval results
Files

masking.mddocs/

Masking Utilities

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.

Capabilities

Pattern Parsing

Parse comma-separated regex pattern strings into an array of RegExp objects for use in masking operations.

/**
 * Parses comma-separated regex patterns into RegExp objects
 * Supports both /pattern/flags and plain pattern formats
 * @param maskingRegexString - String containing regex patterns separated by commas
 * @returns Array of RegExp objects or undefined if input is invalid
 */
function parseMaskingPatterns(
  maskingRegexString: string | undefined
): RegExp[] | undefined;

Supported Pattern Formats:

  • Plain patterns: --key=[^ ]* (becomes new RegExp('--key=[^ ]*'))
  • With flags: /--key=[^ ]*/i (becomes new RegExp('--key=[^ ]*', 'i'))
  • Multiple patterns: --key=[^ ]*,--secret=[^ ]* (comma-separated)
  • With capturing groups: /--key=([^ ]*)/i (only captured groups are masked)

Usage Examples:

import { parseMaskingPatterns } from '@wdio/logger';

// Parse simple patterns
const patterns1 = parseMaskingPatterns('--key=[^ ]*,--secret=[^ ]*');
// Returns: [/--key=[^ ]*/, /--secret=[^ ]*/]

// Parse patterns with flags
const patterns2 = parseMaskingPatterns('/--key=([^ ]*)/i,/password=([^ ]*)/gi');
// Returns: [/--key=([^ ]*)/i, /password=([^ ]*)/gi]

// Handle mixed formats
const patterns3 = parseMaskingPatterns('token=[^ ]*,/bearer\\s+([^ ]*)/i');
// Returns: [/token=[^ ]*/, /bearer\s+([^ ]*)/i]

// Invalid patterns are filtered out
const patterns4 = parseMaskingPatterns('valid=[^ ]*,invalid[,another=[^ ]*');
// Returns: [/valid=[^ ]*/, /another=[^ ]*/] (invalid pattern excluded)

// Handle undefined/empty input
const patterns5 = parseMaskingPatterns(undefined);
// Returns: undefined

const patterns6 = parseMaskingPatterns('');
// Returns: []

Text Masking

Apply masking patterns to text, replacing sensitive data with a masked placeholder.

/**
 * Masks sensitive data in text using provided masking patterns
 * @param text - The text to mask
 * @param maskingPatterns - Array of RegExp patterns to use for masking
 * @returns The masked text, or original text if no patterns provided
 */
function mask(
  text: string, 
  maskingPatterns: RegExp[] | undefined
): string;

Masking Behavior:

  • No capturing groups: Entire match is replaced with **MASKED**
  • With capturing groups: Only captured groups are replaced with **MASKED**
  • Multiple matches: All matches are replaced
  • Newline preservation: Trailing newlines are preserved

Usage Examples:

import { mask, parseMaskingPatterns } from '@wdio/logger';

// Basic masking without capturing groups
const patterns1 = parseMaskingPatterns('--key=[^ ]*');
const result1 = mask('Command: wdio --key=secretKey123 --verbose', patterns1);
// Result: "Command: wdio **MASKED** --verbose"

// Masking with capturing groups (more precise)
const patterns2 = parseMaskingPatterns('/--key=([^ ]*)/');
const result2 = mask('Command: wdio --key=secretKey123 --verbose', patterns2);
// Result: "Command: wdio --key=**MASKED** --verbose"

// Multiple patterns and matches
const patterns3 = parseMaskingPatterns('/--key=([^ ]*)/,/--token=([^ ]*)/');
const result3 = mask('wdio --key=secret --token=abc123 test', patterns3);
// Result: "wdio --key=**MASKED** --token=**MASKED** test"

// Complex patterns with flags
const patterns4 = parseMaskingPatterns('/authorization:\\s*bearer\\s+([^ ]*)/i');
const result4 = mask('Headers: { Authorization: Bearer token123 }', patterns4);
// Result: "Headers: { Authorization: Bearer **MASKED** }"

// Multiple capturing groups
const patterns5 = parseMaskingPatterns('/user:([^ ]*) pass:([^ ]*)/');
const result5 = mask('Connecting with user:admin pass:secret123', patterns5);
// Result: "Connecting with user:**MASKED** pass:**MASKED**"

// Preserve newlines
const text = 'Line 1: --key=secret\nLine 2: normal\n';
const result6 = mask(text, parseMaskingPatterns('--key=([^ ]*)'));
// Result: "Line 1: --key=**MASKED**\nLine 2: normal\n"

Masking Constant

Constant string used as replacement text for masked sensitive data.

/**
 * String constant used to replace masked sensitive data
 */
const SENSITIVE_DATA_REPLACER: "**MASKED**";

Usage Examples:

import { SENSITIVE_DATA_REPLACER } from '@wdio/logger';

// Use in custom masking implementations
function customMask(text: string, pattern: RegExp): string {
  return text.replace(pattern, SENSITIVE_DATA_REPLACER);
}

// Check for masked content
function containsMaskedData(text: string): boolean {
  return text.includes(SENSITIVE_DATA_REPLACER);
}

// Custom validation
if (logMessage.includes(SENSITIVE_DATA_REPLACER)) {
  console.log('Log contains masked sensitive data');
}

Advanced Pattern Examples

Common Security Patterns

import { parseMaskingPatterns, mask } from '@wdio/logger';

// AWS credentials
const awsPatterns = parseMaskingPatterns(
  '/aws_access_key_id=([^ ]*)/i,/aws_secret_access_key=([^ ]*)/i'
);

// Database connections
const dbPatterns = parseMaskingPatterns(
  '/password=([^ ]*)/i,/pwd=([^ ]*)/i,/connectionString=([^ ]*)/i'
);

// API tokens and keys
const apiPatterns = parseMaskingPatterns(
  '/authorization:\\s*bearer\\s+([^ ]*)/i,/api[_-]?key=([^ ]*)/i,/token=([^ ]*)/i'
);

// URLs with credentials
const urlPatterns = parseMaskingPatterns(
  '/\\/\\/([^:]+):([^@]+)@/g'  // Matches user:pass in URLs
);

const logText = 'Connecting to mongodb://user:password123@localhost:27017/db';
const masked = mask(logText, urlPatterns);
// Result: "Connecting to mongodb://**MASKED**:**MASKED**@localhost:27017/db"

Complex Patterns

// JSON structures
const jsonPatterns = parseMaskingPatterns(
  '/"password"\\s*:\\s*"([^"]*)"/,/"token"\\s*:\\s*"([^"]*)"/,/"secret"\\s*:\\s*"([^"]*)"/i'
);

const jsonLog = 'Request body: {"username": "admin", "password": "secret123"}';
const maskedJson = mask(jsonLog, jsonPatterns);
// Result: 'Request body: {"username": "admin", "password": "**MASKED**"}'

// Command line arguments
const cmdPatterns = parseMaskingPatterns(
  '/--[a-zA-Z-]*(?:key|pass|secret|token)[a-zA-Z-]*[=\\s]+([^ ]*)/gi'
);

const cmdLog = 'Executing: myapp --api-key secret123 --db-password mypass --verbose';
const maskedCmd = mask(cmdLog, cmdPatterns);
// Result: "Executing: myapp --api-key **MASKED** --db-password **MASKED** --verbose"

Security Considerations

  • Pattern Safety: All patterns are validated using safe-regex2 to prevent ReDoS attacks
  • Performance: Patterns are compiled once and reused across log messages
  • Memory: Failed pattern compilation returns undefined (filtered out) rather than throwing
  • Precision: Use capturing groups for precise masking rather than masking entire matches
  • Testing: Always test patterns with sample data to ensure correct masking behavior

Install with Tessl CLI

npx tessl i tessl/npm-wdio--logger

docs

browser.md

configuration.md

core-logging.md

index.md

masking.md

tile.json