From 4af10364235ac9abf8612bc355c47777fdb99478 Mon Sep 17 00:00:00 2001 From: Mathias Date: Tue, 19 May 2026 13:04:12 +0200 Subject: [PATCH] fix(ingestion): redact password from BRAIN_PG_DSN log line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous "crude redaction" — pgDSN[:strings.IndexByte(pgDSN+"@", '@')] — sliced up to the `@` character, which sits *after* the password in a postgres URL, so the log line included the password in plaintext (caught on first activation, 2026-05-18 startup log). Use url.Parse + URL.Redacted() instead. Falls back to "postgres://***" if parsing fails — we never log a raw DSN. --- ingestion/cmd/server/main.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/ingestion/cmd/server/main.go b/ingestion/cmd/server/main.go index 79f4927..fda853f 100644 --- a/ingestion/cmd/server/main.go +++ b/ingestion/cmd/server/main.go @@ -6,6 +6,7 @@ import ( "fmt" "log/slog" "net/http" + "net/url" "os" "strconv" "strings" @@ -24,6 +25,17 @@ import ( "github.com/mathiasbq/hyperguild/ingestion/internal/watcher" ) +// redactDSN parses a Postgres URL and replaces its password with `***` +// for safe inclusion in logs. Falls back to a non-leaking placeholder +// if parsing fails — we never log a raw DSN. +func redactDSN(dsn string) string { + u, err := url.Parse(dsn) + if err != nil || u.User == nil { + return "postgres://***" + } + return u.Redacted() +} + // vectorAdapter bridges *vectorstore.PGStore (returns []vectorstore.Hit) // to the search.VectorSearcher interface (which uses []search.VectorHit). // Kept here, not in either package, so neither has to import the other. @@ -126,7 +138,7 @@ func main() { mcpSrv = mcpSrv.WithHybridRetrieval(vectorAdapter{s: store}, embedder) h.WithEmbedSync(store, embedder) logger.Info("brain hybrid retrieval enabled", - "pg", pgDSN[:strings.IndexByte(pgDSN+"@", '@')], // crude redaction + "pg", redactDSN(pgDSN), "embed_url", embedURL, "embed_model", embedModel) case pgDSN == "" && embedURL == "": // disabled — fine