How to Redact Production Logs Before Sharing Them

2026-05-28

Production logs are often the fastest route to a diagnosis—and an accidental route to leaking credentials, customer data, or internal infrastructure details. Before attaching logs to an issue, chat, or vendor ticket, make a redacted copy. Preserve the original only in the approved, access-controlled logging system.

Start by narrowing the time window and component in the Log Workbench. Less data means less exposure and a clearer investigation.

Decide what must be removed

Treat these values as sensitive unless your policy says otherwise:

  • Authorization headers, cookies, API keys, passwords, tokens, and connection strings
  • Email addresses, phone numbers, names, addresses, and account identifiers
  • Request or response bodies containing customer or payment data
  • Private IPs, hostnames, file paths, database names, and internal URLs
  • Cryptographic material and environment-variable dumps

Do not assume a value is safe because it is encoded. Base64, JWT payloads, URL encoding, and hexadecimal are representations, not redaction.

Create a deterministic redacted copy

For structured JSON Lines, redact by field name before using broad regular expressions:

import hashlib
import json
import sys

SENSITIVE_KEYS = {
    "authorization", "cookie", "set-cookie", "password",
    "access_token", "refresh_token", "api_key", "email"
}

def pseudonym(value):
    digest = hashlib.sha256(str(value).encode()).hexdigest()[:12]
    return f"[ID:{digest}]"

def clean(value, key=""):
    if key.lower() in SENSITIVE_KEYS:
        return "[REDACTED]"
    if isinstance(value, dict):
        return {k: clean(v, k) for k, v in value.items()}
    if isinstance(value, list):
        return [clean(item) for item in value]
    return value

for line in sys.stdin:
    record = json.loads(line)
    print(json.dumps(clean(record), separators=(",", ":")))

Run it into a new file and never overwrite the source:

python3 redact_logs.py < production.jsonl > production.redacted.jsonl

The example removes known sensitive fields. If correlation is important, pseudonymize selected identifiers consistently rather than deleting them. An unsalted hash may still reveal low-entropy values through guessing, so use a keyed HMAC under controlled conditions when resistant pseudonyms are required. Do not share that key.

Handle unstructured text carefully

Stack traces and plain-text logs need layered checks. Replace high-confidence patterns first, then manually inspect:

import re

text = re.sub(
    r"(?i)(authorization:\s*bearer\s+)[A-Za-z0-9._~+/-]+=*",
    r"\1[REDACTED]",
    text,
)
text = re.sub(
    r"(?i)(password|api[_-]?key|secret)=([^&\s]+)",
    r"\1=[REDACTED]",
    text,
)

Regex cannot understand every log format. Multiline values, escaped JSON, custom token formats, and secrets split across fields can evade it. Use the Secret Detector as a second pass, not proof that a file is safe. Format exception output with the stack trace viewer after sanitizing it.

Keep enough diagnostic value

Retain timestamps, severity, service name, operation, error class, non-sensitive status codes, and stable correlation labels. Replace customer IDs with consistent placeholders such as customer-A. Trim unrelated requests and repeated stack frames, but do not alter ordering or invent events.

Document the transformation alongside the shared artifact:

Window: 2026-07-19 19:10–19:15 UTC
Scope: checkout-api instance group
Removed: credentials, cookies, bodies, email addresses
Pseudonymized: request and customer identifiers

The safe log-sharing recipe provides a repeatable handoff checklist.

Common mistakes and incident response

Searching only for the literal word password misses bearer tokens, signed URLs, cookies, and vendor-specific keys. Screenshots can expose browser tabs or terminal history. Archive files may include the original beside the redacted copy. Ticket systems, public gists, and AI assistants may have broader retention and access than your production log platform.

Review the final artifact as if it were public: inspect beginning and end, search for credential prefixes and personal data, list archive contents, and ask a second person to review high-risk cases. Share through the narrowest approved channel with an expiration time.

If a real secret was shared, deleting the message is not enough. Revoke or rotate it, review access logs, invalidate affected sessions, notify the appropriate security or privacy owner, and preserve an audit trail. Better still, prevent sensitive values at ingestion through allowlisted structured logging and centralized redaction.