Private Data Redactor
Redacts passwords, tokens, API keys, emails, phone numbers, and card-like values from logs.
Function signature
ogRedactSensitiveData(payload, extra_keys = array(), depth = 0)
Categories
- Security
Parameters
payloadString or array payload to redact.extra_keysAdditional sensitive key fragments.depthCurrent recursion depth.Return value
Short public-safe status message.
- payload
Compatibility
Existing function name and call order preserved; metadata signature corrected to source.
Minimum PHP version: 7.4
Security notes
Validate request method, identity, permissions, and caller-owned allowlists before use; keep secrets and internal paths out of public output.
Code
<?php
/*
* Copyright (c) 2026 Jeffery L. Paris <jparis@phpog.com>.
* Free for personal and internal use. Paid project use requires visible credit
* to Jeffery L. Paris. Corporate use requires a paid license fee unless a
* separate written license states otherwise.
*/
/**
* Redacts passwords, tokens, API keys, emails, phone numbers, and card-like values from logs.
*
* Primary use case: Safe logs and debug outputs.
* Typical inputs: array or string payload, redaction rules.
* Typical output: redacted payload.
*
* Implementation note: Make rules recursive and configurable.
*
* @param mixed $payload String or array payload to redact.
* @param array $extra_keys Additional sensitive key fragments.
* @param int $depth Current recursion depth.
* @return array Structured redaction result.
*/
function ogRedactSensitiveData($payload, $extra_keys = array(), $depth = 0) {
$result = array(
'success' => false,
'message' => '',
'data' => array('payload' => '')
);
if (!is_array($extra_keys)) {
$extra_keys = array();
}
$depth = (int)$depth;
if ($depth > 10) {
$result['message'] = 'Maximum redaction depth reached.';
$result['data']['payload'] = '[redacted-depth-limit]';
return $result;
}
$default_keys = array('password', 'passwd', 'pass', 'token', 'secret', 'api_key', 'apikey', 'authorization', 'cookie', 'csrf', 'card', 'cvv');
$keys = array_merge($default_keys, $extra_keys);
$redacted = $payload;
if (is_array($redacted)) {
foreach ($redacted as $key => $value) {
$lower_key = strtolower((string)$key);
$is_sensitive_key = false;
foreach ($keys as $sensitive_key) {
$sensitive_key = strtolower((string)$sensitive_key);
if (!empty($sensitive_key) && strpos($lower_key, $sensitive_key) !== false) {
$is_sensitive_key = true;
}
}
if ($is_sensitive_key) {
$redacted[$key] = '[redacted]';
} elseif (is_array($value)) {
$child = ogRedactSensitiveData($value, $extra_keys, $depth + 1);
$redacted[$key] = $child['data']['payload'];
} elseif (is_scalar($value)) {
$child = ogRedactSensitiveData((string)$value, $extra_keys, $depth + 1);
$redacted[$key] = $child['data']['payload'];
}
}
} else {
$redacted = (string)$redacted;
$redacted = preg_replace('/(password|passwd|token|secret|api[_-]?key)\s*[:=]\s*[^\s,&]+/i', '$1=[redacted]', $redacted);
$redacted = preg_replace('/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/i', '[redacted-email]', $redacted);
$redacted = preg_replace('/\b(?:\+?1[-.\s]?)?(?:\(?[0-9]{3}\)?[-.\s]?[0-9]{3}[-.\s]?[0-9]{4})\b/', '[redacted-phone]', $redacted);
$redacted = preg_replace('/\b(?:[0-9][ -]*?){13,19}\b/', '[redacted-card]', $redacted);
}
$result['success'] = true;
$result['message'] = 'Sensitive data redacted.';
$result['data'] = array('payload' => $redacted);
return $result;
}