fix(security): phase 2 high-severity hardening
CI / test (pull_request) Successful in 4m31s
CI / lint (pull_request) Successful in 56s

- Push heartbeat accepts Authorization: Bearer header (query string deprecated)
- Gotify alerts use X-Gotify-Key header instead of token in URL
- Per-IP rate limiting on all API endpoints (token-bucket)
- /metrics gated behind cluster secret (UPTOP_METRICS_PUBLIC=true to opt out)
- Config export redacts passwords/tokens by default (redact_secrets=false to override)
- Fix rewritePlaceholders for 100+ SQL parameters
- Fix AddSiteReturningID/AddAlertReturningID race with LastInsertId/RETURNING
- HTTP server timeouts: read 30s, write 60s, idle 120s
This commit is contained in:
2026-05-25 21:15:33 -04:00
parent b43dfae98f
commit d30d1460bd
6 changed files with 226 additions and 51 deletions
+6 -1
View File
@@ -25,6 +25,7 @@ type PayloadFunc func(title, message string) ([]byte, error)
type HTTPProvider struct {
URL string
Payload PayloadFunc
Headers map[string]string
}
func (h *HTTPProvider) Send(ctx context.Context, title, message string) error {
@@ -37,6 +38,9 @@ func (h *HTTPProvider) Send(ctx context.Context, title, message string) error {
return err
}
req.Header.Set("Content-Type", "application/json")
for k, v := range h.Headers {
req.Header.Set(k, v)
}
resp, err := alertClient.Do(req)
if err != nil {
return err
@@ -165,8 +169,9 @@ func GetProvider(cfg models.AlertConfig) Provider {
}
serverURL := strings.TrimRight(cfg.Settings["url"], "/")
return &HTTPProvider{
URL: fmt.Sprintf("%s/message?token=%s", serverURL, cfg.Settings["token"]),
URL: serverURL + "/message",
Payload: gotifyPayload(priority),
Headers: map[string]string{"X-Gotify-Key": cfg.Settings["token"]},
}
default:
return nil