Capture redacted error messages in telemetry
- Dominant language
- Go
- Stars
- 569
- Forks
- 364
- Avg merge
- 2d 19h
- Merged PRs (30d)
- 136
Description
Deferred phase of #8011 — kept open for future revisit, **not currently prioritized**.
## Status
Per the design discussion that produced the phased plan in #8011, this work is **deferred indefinitely**. The reasoning:
- The triage need that this issue addresses (understanding *what* the error said) is mostly answerable today via the chain types and origin frame attributes shipping in Phases 1, 2, and 4 (#8015, #8017, #8077).
- The required PII redaction pipeline plus formal privacy review is a substantial cost; without a demonstrated triage gap, that cost outweighs the marginal value over location + chain.
- Revisit only if Phases 1–5 leave a meaningful subset of failures that operators cannot triage from Kusto without local repro.
## Original design (preserved for future implementation)
Build a reusable PII redactor at `cli/azd/internal/tracing/redact/` and wire it through the shared classifier (#8017) to emit redacted `error.message.redacted` and `error.message.hash` as additive **span properties** on every error span. Keep `Status.Description` / `RequestData.ResponseCode` stable — the redacted message is not the bin name.
Also re-emit through the redactor on the `*azdext.LocalError` / `*azdext.ServiceError` branches in `MapError` that currently drop the underlying `Message`.
### Redactor design
Safe-by-construction, not "regex over arbitrary strings and hope":
1. **Type-aware safe rendering** for known error types (e.g. `*azcore.ResponseError` rendered as `service=arm status=503 code=...` rather than its raw `err.Error()`).
2. **Conservative regex denylist** on remaining text — JWT, SAS, Bearer, ARM resource paths, Azure URLs, GitHub URLs, email/UPN, file paths, IPv4, GUIDs (hashed).
3. **Final allowlist verifier** that drops the message entirely if a forbidden marker (JWT, Bearer, email) survives a round trip.
Hard length cap of ~4KB on the output. Feature-flag rollout. Formal privacy review required before enabling by default.
### Tests
- Table tests for the regex set
- Fuzz test asserting no input produces a forbidden token in the output
- Functional test asserting `error.message.redacted` and `error.message.hash` round-trip through `--trace-log-file`
### Existing primitives
These are inspiration only — don't promote any of them as-is:
- `cli/azd/internal/agent/tools/mcp/redact.go` — Authorization/Bearer regex set; closest match for the new shared package.
- `cli/azd/pkg/exec/sanitizer.go` — narrow `key=value` scrubber for command exec; too blunt for diagnostic messages.
- `cli/azd/internal/tracing/fields/key.go` — `StringHashed` / `Sha256Hash` for the `error.message.hash` field.
## Privacy considerations to revisit if reopened
- Should `error.message.hash` be derived from the **raw** error message (correlates more aggressively, harder PII story) or from the **canonical redacted** message (safer, looser correlation)?
- AppInsights privacy classification for `error.message.redacted` — likely `CallstackOrException` rather than `SystemMetadata` since the content is derived from runtime/user input even after redaction.
- Opt-out env var (`AZD_TELEMETRY_NO_MESSAGE=true`) for users with strict policies.
Contributor guide
Assessment
This issue has not been assessed yet.