Data redaction
InfraSage masks secrets and personal data at three points. Each is a separate switch, because each protects a different boundary.
| Where | What is masked | Switch | Default |
|---|---|---|---|
| Ingestion gateway, before storage | Log bodies, span and log attributes, Prometheus series labels | INGEST_REDACTION = off, secrets or pii | off (pii in values-enterprise.yaml) |
| Alert evidence | Sample log lines, log patterns and extracted fields on the alert, and so in Slack, email and pager messages | EVIDENCE_REDACTION=off turns it off | on |
| Copilot | Tool results, the context bundle and replayed tool history sent to the model | REDACT_PROMPTS_ENABLED (also covers RCA prompts) | on |
What counts as secret or PII
secrets masks values that are secrets by shape: PEM private keys, AWS access key ids, GitHub, Slack and Google tokens, JWTs, Bearer and Basic credentials, and any password=, token:, "api_key": "..." style pair. An attribute whose key names a credential (db.password, http.request.header.authorization, x-api-key, cookie) is masked whatever its value.
pii adds:
- Card numbers, spaced or dashed, only with a real network's prefix and length and a valid Luhn check digit. Timestamps and most ids don't qualify. About one in ten ids that happen to have a card's shape pass Luhn by chance and are masked too.
- IBANs that pass the ISO 13616 mod-97 check.
- Email addresses, US SSNs (
123-45-6789) and E.164 phone numbers (with the leading+).
Masked values become typed placeholders such as [CARD], [EMAIL] or [SECRET]. That way a reader can still tell what was there. Identity fields are never rewritten, because grouping, joins and trace lookups depend on them: service, environment, trace and span ids, status codes, route, host and Kubernetes names, and job, instance and le labels.
The gateway counts what it masks in infrasage_gateway_redacted_values_total{where="log_body|attribute|series_label"}.
Limits
This is pattern matching, not a classifier. It won't find names, street addresses or free-text account numbers. If your logs carry those, remove them at the source. The collector recipe below does that before data leaves your network, and it is the stronger control of the two.
Redaction applies to data ingested after it is turned on. Rows already stored keep their values until retention removes them.
Collector recipe
Run this in your OpenTelemetry Collector to mask data before it reaches InfraSage. Add your own attribute names to the pattern and your own formats to blocked_values. Checked against collector-contrib 0.115.
processors:
# Deletes credential-named attributes outright.
attributes/drop-credentials:
actions:
- pattern: "(?i).*(password|passwd|secret|token|api[_-]?key|authorization|cookie).*"
action: delete
# Masks card numbers and emails in every attribute that remains.
redaction:
allow_all_keys: true
blocked_values:
- "\\b(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13})\\b" # Visa, Mastercard, Amex
- "\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}\\b" # email
summary: silent
# The redaction processor reads attributes only; log bodies need transform.
transform/log-bodies:
log_statements:
- context: log
statements:
- replace_pattern(body, "\\b(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13})\\b", "[CARD]")
- replace_pattern(body, "\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}\\b", "[EMAIL]")
- replace_pattern(body, "(?i)(password|token|api[_-]?key)=\\S+", "$$1=[SECRET]")
service:
pipelines:
logs:
processors: [attributes/drop-credentials, redaction, transform/log-bodies, batch]
traces:
processors: [attributes/drop-credentials, redaction, batch]
The collector's patterns don't check Luhn digits, so they mask more than InfraSage's pii mode does. Run both if you can: the collector keeps the data inside your network, and the gateway catches whatever the recipe misses.