Skip to content

Custom Patterns

Cloak uses regex patterns to identify and redact sensitive information. You can customize these patterns to match your application’s specific needs.

Cloak ships with patterns for common sensitive data:

'patterns' => [
// MySQL connections
'/mysql:\/\/([^:]+):([^@]+)@([^\/]+)\/(.+)/i',
// PostgreSQL connections
'/postgres:\/\/([^:]+):([^@]+)@([^\/]+)\/(.+)/i',
// MongoDB connections
'/mongodb:\/\/([^:]+):([^@]+)@([^\/]+)\/(.+)/i',
// Redis connections
'/redis:\/\/([^:]+):([^@]+)@([^\/]+)/i',
],
'patterns' => [
'/host=([^\s;]+)/i',
'/user=([^\s;]+)/i',
'/password=([^\s;]+)/i',
'/dbname=([^\s;]+)/i',
],
'patterns' => [
// Generic API keys
'/api[_-]?key["\']?\s*[:=]\s*["\']?([a-zA-Z0-9_\-]+)/i',
// Tokens
'/token["\']?\s*[:=]\s*["\']?([a-zA-Z0-9_\-\.]+)/i',
// Bearer tokens
'/bearer\s+([a-zA-Z0-9_\-\.]+)/i',
],
'patterns' => [
// AWS Access Keys
'/aws[_-]?access[_-]?key[_-]?id["\']?\s*[:=]\s*["\']?([A-Z0-9]+)/i',
// AWS Secret Keys
'/aws[_-]?secret[_-]?access[_-]?key["\']?\s*[:=]\s*["\']?([A-Za-z0-9\/\+]+)/i',
],

Add your own patterns in config/cloak.php:

'patterns' => [
// Add to existing patterns
...config('cloak.patterns'),
// Custom patterns
'/your-custom-pattern-here/i',
'/secret[_-]?token["\']?\s*[:=]\s*["\']?([a-zA-Z0-9]+)/i',
],

Always use the i flag for case-insensitive matching:

'/api[_-]?key/i' // ✅ Matches "api_key", "API_KEY", "Api-Key"
'/api[_-]?key/' // ❌ Only matches "api_key" or "api-key"

Use capture groups () to identify what to redact:

'/password=([^\s;]+)/i' // ✅ Captures the password value
'/password=/i' // ❌ Doesn't capture what to redact

Include context to avoid false positives:

'/api[_-]?key["\']?\s*[:=]\s*["\']?([a-zA-Z0-9_\-]+)/i' // ✅ Requires "api_key=" prefix
'/[a-zA-Z0-9_\-]+/i' // ❌ Matches everything

Test patterns against real exception messages:

use Cline\Cloak\Sanitizers\PatternBasedSanitizer;
$sanitizer = new PatternBasedSanitizer(
patterns: ['/your-pattern/i'],
replacement: '[REDACTED]',
);
$message = 'Error with secret_token=abc123';
$sanitized = $sanitizer->sanitizeMessage($message);
dump($sanitized); // "Error with [REDACTED]"

Use different patterns per environment:

'patterns' => env('APP_ENV') === 'production' ? [
// Aggressive sanitization in production
'/mysql:\/\//i',
'/password/i',
'/secret/i',
'/token/i',
] : [
// Minimal sanitization in development
'/password=([^\s;]+)/i',
],
'/\b(?:\d{4}[-\s]?){3}\d{4}\b/'
'/\b\d{3}-\d{2}-\d{4}\b/'
'/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/'
'/\b(?:\d{1,3}\.){3}\d{1,3}\b/'
// Unix/Linux paths
'/\/home\/([^\/\s]+)/i',
'/\/Users\/([^\/\s]+)/i',
// Windows paths
'/C:\\\\Users\\\\([^\\\\]+)/i',
'/eyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+/'

Change the redaction text globally:

'replacement' => '[SENSITIVE_DATA_REMOVED]',

Or use different text for different patterns by creating multiple sanitizers:

use Cline\Cloak\Sanitizers\PatternBasedSanitizer;
$dbSanitizer = new PatternBasedSanitizer(
patterns: ['/mysql:\/\//i'],
replacement: '[DATABASE_CREDENTIALS]',
);
$apiSanitizer = new PatternBasedSanitizer(
patterns: ['/api[_-]?key/i'],
replacement: '[API_KEY]',
);

Keep patterns efficient:

// ✅ Efficient - specific and bounded
'/api_key=([a-zA-Z0-9]{20,40})/i'
// ❌ Inefficient - too greedy
'/api_key=(.+)/i'

Too many patterns can impact performance. Consider:

// ✅ Single comprehensive pattern
'/(?:password|secret|token|key)=([^\s;]+)/i'
// ❌ Multiple similar patterns
'/password=([^\s;]+)/i',
'/secret=([^\s;]+)/i',
'/token=([^\s;]+)/i',
'/key=([^\s;]+)/i',

Enable pattern debugging:

use Cline\Cloak\Sanitizers\PatternBasedSanitizer;
$sanitizer = new PatternBasedSanitizer(
patterns: config('cloak.patterns'),
replacement: '[REDACTED]',
);
$message = 'Error with mysql://root:pass@localhost/db and api_key=secret123';
// Test each pattern
foreach (config('cloak.patterns') as $pattern) {
if (preg_match($pattern, $message)) {
dump("Pattern matched: {$pattern}");
}
}
// See final result
dump($sanitizer->sanitizeMessage($message));