Redaction
Where it runs
Section titled “Where it runs”In the agent process, before the event leaves the host. z4j never sees unredacted values. This is critical: even a compromised brain cannot exfiltrate your secrets from historical events because they were never sent in the first place. The canonical pattern catalog lives in z4j_core.redaction.patterns.
Default key-name patterns (full-match, case-insensitive)
Section titled “Default key-name patterns (full-match, case-insensitive)”Field names that match any of these regexes have their value replaced with the redaction marker:
- Passwords:
password,password_confirmation,password_hash,passwd,pwd,old_password,new_password. - Secrets:
secret,secrets,client_secret,webhook_secret. - Tokens:
token,access_token,refresh_token,id_token,api_token,bearer_token,session_token. - API keys:
api_key(alsoapikey,api-key),x-api-key,x_api_key. - Authorization and cookies:
authorization,auth,credentials,cookie,set-cookie,set_cookie. - Personal identifiers:
ssn,social_security,social_security_number,credit_card,credit_card_number,card_number,cvv,cvc.
Default value patterns (substring match, case-insensitive)
Section titled “Default value patterns (substring match, case-insensitive)”String values that match any of these regexes are fully redacted regardless of the surrounding key name:
- JWT (
eyJ...three-segment base64). Authorization: Bearer <16+ chars>.- Stripe (
sk_live_*,sk_test_*,pk_live_*,pk_test_*,whsec_*,rk_live_*). - Slack tokens (
xoxb-,xoxp-,xoxa-) and Slack incoming-webhook URLs. - GitHub PATs (
ghp_,gho_,ghs_) and fine-grained PATs (github_pat_). - AWS access key IDs (
AKIA...,ASIA...for STS). - Google Cloud / Firebase API keys (
AIza...). - Twilio account tokens (
SK[hex32]). - SendGrid API keys (
SG.<base64>.<base64>). - Database URIs with embedded credentials (
postgresql://user:pw@host,mysql://,mongodb://,mongodb+srv://,redis://,rediss://,amqp://,amqps://). - PEM private key BEGIN lines (
-----BEGIN RSA PRIVATE KEY-----, etc.). - Email addresses (PII for most apps; reduced to a placeholder).
- US SSN format (
XXX-XX-XXXX).
Long strings are length-tagged (<str len=142>) and binary / bytes payloads become <bytes len=N>.
Customization
Section titled “Customization”Per-project overrides land in the project’s settings (redaction_overrides):
{ "redaction_overrides": { "field_names": ["internal_token", "my_secret_field"], "patterns": ["^user-[0-9a-f]{8}-secret-[0-9a-f]{16}$"] }}Overrides are additive to the built-in rules, never subtractive. If a built-in rule produces false positives for your domain, rename the field rather than disabling the rule.
What is NOT redacted
Section titled “What is NOT redacted”- Task names (
email.sendvsemail.send_welcome). Operator metadata, not secrets. - Queue names and routing keys.
- Error class names (
ValueError,MyDomainError). - Error messages — be careful. An error message containing a known secret pattern (e.g. “invalid API key: sk_live_abc123”) will be redacted via value-pattern match, but custom exception types that interpolate secrets into their message in a non-matching shape are your risk.
Traceback redaction
Section titled “Traceback redaction”Tracebacks are scrubbed line-by-line with the same rules. Stack frames preserve file, line, and function name; local-variable values fall under the key-name and value-pattern rules.
Size limits
Section titled “Size limits”- Single argument value: 64 KiB max; truncated above.
- Total event payload: 2 MiB max; truncated above.
These caps keep the redactor and the wire bounded.
Field-name collisions
Section titled “Field-name collisions”A kwarg called password_hint is redacted because password is a substring of the field name and the engine uses fullmatch with case-insensitivity (the regex password matches when the field is exactly password; longer field names are matched only when they appear in the pattern list). Inspect the patterns above; rename or add an override if you have a legitimate non-secret field that collides.
Disable entirely
Section titled “Disable entirely”Not supported. If your workload genuinely has no secrets and you want raw values in events, you are likely using the wrong tool.