Security & Redaction
API keys stay out of logs. Drivers use raw HTTP with no third-party SDKs.
Redaction is opt-in, not automatic
go-notification does not auto-redact via struct tags or a custom
String(). If you log a Config, an error message, or a request URL
that embeds credentials, the secret will appear in plain text.
Wrap anything you log around the library through middleware.Redact /
middleware.RedactAttr (see below). Never log a whole config struct.
go-notification is built around two security defaults:
- No secrets logged by the library itself — the notifier's own logging never prints your API keys. But anything you log around it is your responsibility — use the helper below.
- Zero third-party SDKs — every driver uses
net/httpdirectly.
Redaction helper
Redaction is a regex-based string scrubber in the middleware package — not a struct-tag or String() mechanism. It replaces bearer tokens, api_key=…, password=…, and token=… patterns with ***:
import "github.com/gopackx/go-notification/middleware"
safe := middleware.Redact(`Authorization: Bearer abc123 api_key=key-secret`)
// "Authorization: Bearer *** api_key=***"For structured logging, RedactAttr returns a redacted slog.Attr:
slog.Info("calling provider", middleware.RedactAttr("url", requestURL))There is no redact:"true" struct tag, no notification.Redact(cfg), and
no redacting String() on config types. Don't log whole config structs with
%+v — pass individual values through middleware.Redact instead.
Keeping secrets out of logs
The notifier's own logging never prints credentials. When you log around the library — request URLs, headers, error strings that may embed a key — run the value through middleware.Redact/RedactAttr first. That covers the common leak vectors (bearer tokens, api_key/token/password pairs).
Zero SDK dependencies
Every driver uses net/http. No Twilio Go SDK, no AWS SDK, no SendGrid client library.
Why it matters:
- Tiny binary. Adding WhatsApp support doesn't pull in the Twilio SDK's ~10MB dependency tree.
- Audit surface. You audit this library's raw HTTP calls. You don't transitively audit six SDK versions with their own CVE history.
- Upgradeability. If an upstream API changes, fixing the driver is editing one file — no waiting for the SDK maintainer.
Trade-off: when upstream APIs add brand-new features (e.g., FCM's new batching API), this library has to catch up manually. That's explicit project scope.
Secrets in environment variables
A common pitfall: shell scripts that print env vars. Don't echo $FCM_SERVICE_ACCOUNT_JSON. Don't include API keys in git-committed .env.example files.
Recommended:
- Use a secrets manager in production (AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault).
- Load secrets at application boot, pass them as
[]bytewhere possible, and avoid roundtripping through the environment after boot.
TLS
Every HTTP driver talks HTTPS using Go's default transport and the system CA bundle; each builds its own client from the Timeout you configure. There is no HTTPClient config field to inject a custom CA or mutual-TLS client. If you need a custom CA or client certificates, the supported path is a network-level egress proxy or a custom channel (Writing a Custom Channel) where you control the http.Client.
Reporting a vulnerability
Email the maintainer directly (not a public issue) per the SECURITY.md in the repo. Don't disclose publicly until a fix ships.