Skip to content

Commit 9266156

Browse files
authored
Merge pull request #20 from PostHog/fix/redact-password-logging
Redact passwords from DuckLake connection string logs
2 parents 3d51fbf + 261047f commit 9266156

File tree

2 files changed

+58
-2
lines changed

2 files changed

+58
-2
lines changed

server/conn_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,3 +224,51 @@ func TestGetCommandType(t *testing.T) {
224224
})
225225
}
226226
}
227+
228+
func TestRedactConnectionString(t *testing.T) {
229+
tests := []struct {
230+
name string
231+
input string
232+
expected string
233+
}{
234+
{
235+
name: "postgres connection string with password",
236+
input: "postgres:host=localhost user=postgres password=secretpass dbname=ducklake",
237+
expected: "postgres:host=localhost user=postgres password=[REDACTED] dbname=ducklake",
238+
},
239+
{
240+
name: "connection string with password= format",
241+
input: "host=localhost password=mysecret user=admin",
242+
expected: "host=localhost password=[REDACTED] user=admin",
243+
},
244+
{
245+
name: "connection string with PASSWORD uppercase",
246+
input: "host=localhost PASSWORD=mysecret user=admin",
247+
expected: "host=localhost PASSWORD=[REDACTED] user=admin",
248+
},
249+
{
250+
name: "connection string without password",
251+
input: "host=localhost user=postgres dbname=test",
252+
expected: "host=localhost user=postgres dbname=test",
253+
},
254+
{
255+
name: "empty string",
256+
input: "",
257+
expected: "",
258+
},
259+
{
260+
name: "password with special characters",
261+
input: "host=localhost password=p@ss!word123 user=admin",
262+
expected: "host=localhost password=[REDACTED] user=admin",
263+
},
264+
}
265+
266+
for _, tt := range tests {
267+
t.Run(tt.name, func(t *testing.T) {
268+
result := redactConnectionString(tt.input)
269+
if result != tt.expected {
270+
t.Errorf("redactConnectionString(%q) = %q, want %q", tt.input, result, tt.expected)
271+
}
272+
})
273+
}
274+
}

server/server.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,21 @@ import (
77
"fmt"
88
"log"
99
"net"
10+
"regexp"
1011
"sync"
1112
"sync/atomic"
1213
"time"
1314

1415
_ "github.com/duckdb/duckdb-go/v2"
1516
)
1617

18+
// redactConnectionString removes sensitive information (passwords) from connection strings for logging
19+
var passwordPattern = regexp.MustCompile(`(?i)(password\s*[=:]\s*)([^\s]+)`)
20+
21+
func redactConnectionString(connStr string) string {
22+
return passwordPattern.ReplaceAllString(connStr, "${1}[REDACTED]")
23+
}
24+
1725
type Config struct {
1826
Host string
1927
Port int
@@ -317,10 +325,10 @@ func (s *Server) attachDuckLake(db *sql.DB) error {
317325
attachStmt = fmt.Sprintf("ATTACH 'ducklake:%s' AS ducklake (DATA_PATH '%s')",
318326
s.cfg.DuckLake.MetadataStore, s.cfg.DuckLake.ObjectStore)
319327
log.Printf("Attaching DuckLake catalog with object store: metadata=%s, data=%s",
320-
s.cfg.DuckLake.MetadataStore, s.cfg.DuckLake.ObjectStore)
328+
redactConnectionString(s.cfg.DuckLake.MetadataStore), s.cfg.DuckLake.ObjectStore)
321329
} else {
322330
attachStmt = fmt.Sprintf("ATTACH 'ducklake:%s' AS ducklake", s.cfg.DuckLake.MetadataStore)
323-
log.Printf("Attaching DuckLake catalog: %s", s.cfg.DuckLake.MetadataStore)
331+
log.Printf("Attaching DuckLake catalog: %s", redactConnectionString(s.cfg.DuckLake.MetadataStore))
324332
}
325333

326334
if _, err := db.Exec(attachStmt); err != nil {

0 commit comments

Comments
 (0)