fix(security): mask alert secrets in the TUI detail panel and table
The alert detail panel dumped a.Settings raw — SMTP passwords, bot tokens, API keys on screen and into any recording or screen share. The table view leaked the PagerDuty routing key, Pushover user key, and full discord/slack/webhook URLs (the URL path is the credential). The redaction allowlist moves from internal/server to models.RedactAlertSettings so the backup export and the TUI render through one policy. Panel keys are sorted so rows stop reshuffling every tick; webhook URLs show scheme+host only; keys show first4…last4.
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
package models
|
||||
|
||||
// safeAlertSettingKeys lists, per provider type, the alert settings that are
|
||||
// NOT secret and may be shown or exported in the clear. Everything else is
|
||||
// redacted. Providers absent from this map (discord, slack, webhook, pushover)
|
||||
// carry their secret in a field a denylist would miss — the webhook URL, the
|
||||
// pushover token/user — so all of their settings are redacted.
|
||||
var safeAlertSettingKeys = map[string]map[string]bool{
|
||||
"email": {"host": true, "port": true, "to": true, "from": true},
|
||||
"ntfy": {"topic": true, "priority": true},
|
||||
"telegram": {"chat_id": true},
|
||||
"pagerduty": {"severity": true},
|
||||
"gotify": {"priority": true},
|
||||
"opsgenie": {"priority": true, "eu": true},
|
||||
}
|
||||
|
||||
// RedactAlertSettings keeps only the known-safe keys for the alert type and
|
||||
// redacts everything else. An allowlist fails safe: an unknown or newly added
|
||||
// setting is redacted by default instead of leaking. Shared by the backup
|
||||
// export path and the TUI alert detail panel so both render through the same
|
||||
// policy.
|
||||
func RedactAlertSettings(alertType string, settings map[string]string) map[string]string {
|
||||
safe := safeAlertSettingKeys[alertType]
|
||||
redacted := make(map[string]string, len(settings))
|
||||
for k, v := range settings {
|
||||
switch {
|
||||
case v == "":
|
||||
redacted[k] = ""
|
||||
case safe[k]:
|
||||
redacted[k] = v
|
||||
default:
|
||||
redacted[k] = "***REDACTED***"
|
||||
}
|
||||
}
|
||||
return redacted
|
||||
}
|
||||
Reference in New Issue
Block a user