API keys are the quietest breach vector in most codebases. They sit in environment variables, config files, and request headers — and every time your application logs a request for debugging, there is a chance one of them lands in plaintext in a log aggregator. Redaction tools promise to clean that up. In practice, they are the last line of defense, not the first.
Why redaction fails
Redaction at the log ingestion layer works by pattern matching. It looks for strings that resemble known secret formats — sk_live_..., AWS key shapes, UUIDs — and replaces them with a placeholder. That works until it doesn't.
- Regex is structure, not intent. A key split across a JSON boundary, base64-encoded, or embedded in a nested payload can slip past a pattern that expects a contiguous string.
- Formats change. Internal gateways, third-party SDKs, and homegrown auth schemes all produce credentials that do not match the vendor's list.
- Pressure weakens the filter. During a production incident, teams routinely raise log verbosity and relax redaction rules to see more. That is exactly when a key gets logged.
The better default: do not log the secret
The most reliable redaction is the one you never need. Treat logging as a data-minimization problem:
- Log a derived identifier, not the secret. Store a key ID or the last four characters alongside the secret in your vault. Log the identifier.
- Fetch secrets at runtime, never at boot. Use a secret manager (Vault, AWS Secrets Manager, GCP Secret Manager) and short-lived credentials. The application authenticates to the vault with its own identity, reads the secret, uses it, and never passes the raw value through a log statement.
- Redact at the source, not the sink. Add a logging serializer that strips
Authorization,Cookie,api_key, and similar fields before the record is written.
Test the pipeline, not just the pattern
A redaction rule that works in a unit test can fail in production. Prove it end to end:
- Fuzz the logging middleware with known secrets in JSON, query strings, headers, and error stack traces.
- Trace a request from the ingress gateway through the service and logging library to the final sink, and assert that the secret never appears in any of them.
- Add an automated check that fails the build if a known test key shows up in captured logs.
import re def assert_no_secret(log_entry: str, pattern: str) -> None: if re.search(pattern, log_entry): raise AssertionError("sensitive pattern found in log") Rotate like a key is already leaked
Assume every long-lived key will eventually be exposed. Automate rotation on a schedule — 90 days for most keys, 30 for database and payment credentials — and use a grace period where old and new keys both work so rotation does not cause an outage.
The goal is not a perfect regex. It is a design where a missed redaction cannot turn into a breach.
This is an expanded technical note based on our analysis. The original is here: https://hsecurities.in/blog/api-key-survives-log-redaction
![Localization Mapping and SLAM — Ch.20: Map Server Architecture [KR]](https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F25xyjqac9fxdq03fcrwv.png)
![Localization Mapping and SLAM — Ch.25: Future of SLAM [KR]](https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1mc9rptwgplvcf7jil7b.png)