Browse Source

fix(db): redact credentials in client-merge conflict logs

CodeQL flagged go/clear-text-logging: the merge conflict logger printed
raw Old/New/Kept values, which for password/auth/uuid/subId fields meant
credentials landed in plain-text logs. Mask those four fields at the log
site so operators still see which field collided without leaking secrets.
MHSanaei 20 hours ago
parent
commit
66f946ee54
1 changed files with 18 additions and 1 deletions
  1. 18 1
      database/db.go

+ 18 - 1
database/db.go

@@ -48,6 +48,22 @@ func Dialect() string {
 	return db.Dialector.Name()
 }
 
+var sensitiveConflictFields = map[string]struct{}{
+	"uuid":     {},
+	"password": {},
+	"auth":     {},
+	"subId":    {},
+}
+
+// redactConflictValues masks values for credential-bearing merge fields so
+// they never reach plain-text logs. Non-sensitive fields pass through.
+func redactConflictValues(x model.ClientMergeConflict) (oldV, newV, keptV any) {
+	if _, sensitive := sensitiveConflictFields[x.Field]; sensitive {
+		return "<redacted>", "<redacted>", "<redacted>"
+	}
+	return x.Old, x.New, x.Kept
+}
+
 const (
 	defaultUsername = "admin"
 	defaultPassword = "admin"
@@ -249,8 +265,9 @@ func seedClientsFromInboundJSON() error {
 				} else {
 					conflicts := model.MergeClientRecord(row, incoming)
 					for _, x := range conflicts {
+						oldV, newV, keptV := redactConflictValues(x)
 						log.Printf("client merge: email=%s conflict on %s old=%v new=%v kept=%v",
-							email, x.Field, x.Old, x.New, x.Kept)
+							email, x.Field, oldV, newV, keptV)
 					}
 					if err := tx.Save(row).Error; err != nil {
 						return err