Skip to content

Conversation

@coolwednesday
Copy link
Member

@coolwednesday coolwednesday commented Dec 1, 2025

Pull Request Template

Description:

Checklist:

  • I have formatted my code using goimport and golangci-lint.
  • All new code is covered by unit tests.
  • This PR does not decrease the overall code coverage.
  • I have reviewed the code comments and documentation for clarity.

Thank you for your contribution!

}

if r.logger != nil {
r.logger.Debugf("connecting to Redis at '%s'", r.cfg.Addr)

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

Sensitive data returned by an access to password
flows to a logging call.

Copilot Autofix

AI 6 days ago

To fix the problem, we should prevent sensitive information such as credentials from being logged in plaintext. Specifically, before logging the Redis address (r.cfg.Addr), we should sanitize it to remove any embedded credentials if they exist, or log only the host/port portion if that's all that's needed for troubleshooting.

  • In pkg/gofr/datasource/pubsub/redis/redis.go, modify the log statements that include r.cfg.Addr so that if Addr contains credentials (recognized by the presence of an @ and possibly a user:pass syntax before the host), those are omitted or replaced with a placeholder. This can be achieved by writing a small helper function that parses the address and removes obfuscated credentials if present.
  • Replace the instances of r.cfg.Addr in logging calls (Debugf, Errorf, Logf etc.) with calls to this helper sanitizing function.
  • Add the helper function in the same file (redis.go), as it needs to be accessible where logging occurs.
Suggested changeset 1
pkg/gofr/datasource/pubsub/redis/redis.go

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/pkg/gofr/datasource/pubsub/redis/redis.go b/pkg/gofr/datasource/pubsub/redis/redis.go
--- a/pkg/gofr/datasource/pubsub/redis/redis.go
+++ b/pkg/gofr/datasource/pubsub/redis/redis.go
@@ -18,6 +18,31 @@
 	"gofr.dev/pkg/gofr/datasource/pubsub"
 )
 
+// sanitizeRedisAddr removes credentials from a Redis address if present.
+func sanitizeRedisAddr(addr string) string {
+	// Handles Redis URIs with credentials: redis://user:pass@host:port or
+	// plain host:port
+	if strings.Contains(addr, "@") {
+		parts := strings.Split(addr, "@")
+		if len(parts) == 2 {
+			// Remove credentials part, retain host:port or rest.
+			// For URI, could be redis://user:pass@host:port
+			// Optionally retain scheme.
+			credsPart := parts[0]
+			hostPart := parts[1]
+			// If there's a scheme, preserve it.
+			schemeParts := strings.SplitN(credsPart, "//", 2)
+			if len(schemeParts) == 2 {
+				return schemeParts[0] + "//" + hostPart
+			}
+			return hostPart
+		}
+		// If address has multiple '@', keep right-most part.
+		return parts[len(parts)-1]
+	}
+	return addr
+}
+
 // Client represents a Redis PubSub client.
 type Client struct {
 	// Separate connections for pub/sub operations
@@ -119,7 +144,7 @@
 	}
 
 	if r.logger != nil {
-		r.logger.Debugf("connecting to Redis at '%s'", r.cfg.Addr)
+		r.logger.Debugf("connecting to Redis at '%s'", sanitizeRedisAddr(r.cfg.Addr))
 	}
 
 	options, err := createRedisOptions(r.cfg)
@@ -144,7 +169,7 @@
 
 	if err := r.testConnections(); err != nil {
 		if r.logger != nil {
-			r.logger.Errorf("failed to connect to Redis at '%s', error: %v", r.cfg.Addr, err)
+			r.logger.Errorf("failed to connect to Redis at '%s', error: %v", sanitizeRedisAddr(r.cfg.Addr), err)
 		}
 
 		go r.retryConnect()
@@ -158,12 +183,12 @@
 
 	if err := r.queryConn.Ping(ctx).Err(); err != nil {
 		if r.logger != nil {
-			r.logger.Errorf("failed to connect query connection to Redis at '%s', error: %v", r.cfg.Addr, err)
+			r.logger.Errorf("failed to connect query connection to Redis at '%s', error: %v", sanitizeRedisAddr(r.cfg.Addr), err)
 		}
 	}
 
 	if r.logger != nil {
-		r.logger.Logf("connected to Redis at '%s'", r.cfg.Addr)
+		r.logger.Logf("connected to Redis at '%s'", sanitizeRedisAddr(r.cfg.Addr))
 	}
 }
 
EOF
@@ -18,6 +18,31 @@
"gofr.dev/pkg/gofr/datasource/pubsub"
)

// sanitizeRedisAddr removes credentials from a Redis address if present.
func sanitizeRedisAddr(addr string) string {
// Handles Redis URIs with credentials: redis://user:pass@host:port or
// plain host:port
if strings.Contains(addr, "@") {
parts := strings.Split(addr, "@")
if len(parts) == 2 {
// Remove credentials part, retain host:port or rest.
// For URI, could be redis://user:pass@host:port
// Optionally retain scheme.
credsPart := parts[0]
hostPart := parts[1]
// If there's a scheme, preserve it.
schemeParts := strings.SplitN(credsPart, "//", 2)
if len(schemeParts) == 2 {
return schemeParts[0] + "//" + hostPart
}
return hostPart
}
// If address has multiple '@', keep right-most part.
return parts[len(parts)-1]
}
return addr
}

// Client represents a Redis PubSub client.
type Client struct {
// Separate connections for pub/sub operations
@@ -119,7 +144,7 @@
}

if r.logger != nil {
r.logger.Debugf("connecting to Redis at '%s'", r.cfg.Addr)
r.logger.Debugf("connecting to Redis at '%s'", sanitizeRedisAddr(r.cfg.Addr))
}

options, err := createRedisOptions(r.cfg)
@@ -144,7 +169,7 @@

if err := r.testConnections(); err != nil {
if r.logger != nil {
r.logger.Errorf("failed to connect to Redis at '%s', error: %v", r.cfg.Addr, err)
r.logger.Errorf("failed to connect to Redis at '%s', error: %v", sanitizeRedisAddr(r.cfg.Addr), err)
}

go r.retryConnect()
@@ -158,12 +183,12 @@

if err := r.queryConn.Ping(ctx).Err(); err != nil {
if r.logger != nil {
r.logger.Errorf("failed to connect query connection to Redis at '%s', error: %v", r.cfg.Addr, err)
r.logger.Errorf("failed to connect query connection to Redis at '%s', error: %v", sanitizeRedisAddr(r.cfg.Addr), err)
}
}

if r.logger != nil {
r.logger.Logf("connected to Redis at '%s'", r.cfg.Addr)
r.logger.Logf("connected to Redis at '%s'", sanitizeRedisAddr(r.cfg.Addr))
}
}

Copilot is powered by AI and may make mistakes. Always verify output.

if err := r.testConnections(); err != nil {
if r.logger != nil {
r.logger.Errorf("failed to connect to Redis at '%s', error: %v", r.cfg.Addr, err)

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

Sensitive data returned by an access to password
flows to a logging call.

Copilot Autofix

AI 6 days ago

To fix the issue:

  • Do not log sensitive configuration values directly, particularly connection strings that may embed credentials.
  • Specifically, update the log messages in pkg/gofr/datasource/pubsub/redis/redis.go within the Connect() method to omit r.cfg.Addr when logging errors or connection events. Optionally, if you want to indicate which Redis host is being connected, log only the host/port part after sanitizing the string to remove credentials. However, for safety and generality, it is best to omit or mask the address completely.
  • Edit any logging statements (lines 122, 147, 161, 166) using r.cfg.Addr to either remove the address, replace it with a non-sensitive identifier (like "Redis"), or show only the host/port (without credentials) through a helper method that removes any user info from the connection string.

To implement this:

  • Edit Connect() in pkg/gofr/datasource/pubsub/redis/redis.go, replacing log statements that reference r.cfg.Addr to not print it, or to use a sanitized/obfuscated form.
  • Optionally: If desired, add a helper function (within this file/region) that extracts host and port from a Redis URI (removing any credentials), and use that for logging, though its necessity is debatable.

Suggested changeset 1
pkg/gofr/datasource/pubsub/redis/redis.go

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/pkg/gofr/datasource/pubsub/redis/redis.go b/pkg/gofr/datasource/pubsub/redis/redis.go
--- a/pkg/gofr/datasource/pubsub/redis/redis.go
+++ b/pkg/gofr/datasource/pubsub/redis/redis.go
@@ -119,7 +119,7 @@
 	}
 
 	if r.logger != nil {
-		r.logger.Debugf("connecting to Redis at '%s'", r.cfg.Addr)
+		r.logger.Debugf("connecting to Redis")
 	}
 
 	options, err := createRedisOptions(r.cfg)
@@ -144,7 +144,7 @@
 
 	if err := r.testConnections(); err != nil {
 		if r.logger != nil {
-			r.logger.Errorf("failed to connect to Redis at '%s', error: %v", r.cfg.Addr, err)
+			r.logger.Errorf("failed to connect to Redis, error: %v", err)
 		}
 
 		go r.retryConnect()
@@ -158,12 +158,12 @@
 
 	if err := r.queryConn.Ping(ctx).Err(); err != nil {
 		if r.logger != nil {
-			r.logger.Errorf("failed to connect query connection to Redis at '%s', error: %v", r.cfg.Addr, err)
+			r.logger.Errorf("failed to connect query connection to Redis, error: %v", err)
 		}
 	}
 
 	if r.logger != nil {
-		r.logger.Logf("connected to Redis at '%s'", r.cfg.Addr)
+		r.logger.Logf("connected to Redis")
 	}
 }
 
EOF
@@ -119,7 +119,7 @@
}

if r.logger != nil {
r.logger.Debugf("connecting to Redis at '%s'", r.cfg.Addr)
r.logger.Debugf("connecting to Redis")
}

options, err := createRedisOptions(r.cfg)
@@ -144,7 +144,7 @@

if err := r.testConnections(); err != nil {
if r.logger != nil {
r.logger.Errorf("failed to connect to Redis at '%s', error: %v", r.cfg.Addr, err)
r.logger.Errorf("failed to connect to Redis, error: %v", err)
}

go r.retryConnect()
@@ -158,12 +158,12 @@

if err := r.queryConn.Ping(ctx).Err(); err != nil {
if r.logger != nil {
r.logger.Errorf("failed to connect query connection to Redis at '%s', error: %v", r.cfg.Addr, err)
r.logger.Errorf("failed to connect query connection to Redis, error: %v", err)
}
}

if r.logger != nil {
r.logger.Logf("connected to Redis at '%s'", r.cfg.Addr)
r.logger.Logf("connected to Redis")
}
}

Copilot is powered by AI and may make mistakes. Always verify output.

if err := r.queryConn.Ping(ctx).Err(); err != nil {
if r.logger != nil {
r.logger.Errorf("failed to connect query connection to Redis at '%s', error: %v", r.cfg.Addr, err)

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

Sensitive data returned by an access to password
flows to a logging call.

Copilot Autofix

AI 6 days ago

The best fix is to remove logging of the full address string in log messages and diagnostic errors, both in success and failure cases. Instead, only log non-sensitive details: for example, host and port (if it's certain they're not secret), or replace the address by a generic indication like "[REDACTED]" or "[address hidden]". This fix should apply to all places in pkg/gofr/datasource/pubsub/redis/redis.go where r.cfg.Addr is logged—in error, info, and debug messages. Specifically, lines in Connect() like 122, 147, 161, and 166 should be updated. It is best to avoid logging the address unless certain it cannot contain credentials, but since the taint flow is unclear and credentials can flow into the address, we must treat it as sensitive.

No new methods or imports are needed—replace usages with redacted text or rephrase messages. If there are places where only parts (e.g., host, port) are logged and are confirmed non-sensitive, you may safely log those, but since host/port may also be sensitive in some setups, it is safer to redact completely.

Suggested changeset 1
pkg/gofr/datasource/pubsub/redis/redis.go

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/pkg/gofr/datasource/pubsub/redis/redis.go b/pkg/gofr/datasource/pubsub/redis/redis.go
--- a/pkg/gofr/datasource/pubsub/redis/redis.go
+++ b/pkg/gofr/datasource/pubsub/redis/redis.go
@@ -119,7 +119,7 @@
 	}
 
 	if r.logger != nil {
-		r.logger.Debugf("connecting to Redis at '%s'", r.cfg.Addr)
+		r.logger.Debugf("connecting to Redis [address hidden]")
 	}
 
 	options, err := createRedisOptions(r.cfg)
@@ -144,7 +144,7 @@
 
 	if err := r.testConnections(); err != nil {
 		if r.logger != nil {
-			r.logger.Errorf("failed to connect to Redis at '%s', error: %v", r.cfg.Addr, err)
+			r.logger.Errorf("failed to connect to Redis [address hidden], error: %v", err)
 		}
 
 		go r.retryConnect()
@@ -158,12 +158,12 @@
 
 	if err := r.queryConn.Ping(ctx).Err(); err != nil {
 		if r.logger != nil {
-			r.logger.Errorf("failed to connect query connection to Redis at '%s', error: %v", r.cfg.Addr, err)
+			r.logger.Errorf("failed to connect query connection to Redis [address hidden], error: %v", err)
 		}
 	}
 
 	if r.logger != nil {
-		r.logger.Logf("connected to Redis at '%s'", r.cfg.Addr)
+		r.logger.Logf("connected to Redis [address hidden]")
 	}
 }
 
EOF
@@ -119,7 +119,7 @@
}

if r.logger != nil {
r.logger.Debugf("connecting to Redis at '%s'", r.cfg.Addr)
r.logger.Debugf("connecting to Redis [address hidden]")
}

options, err := createRedisOptions(r.cfg)
@@ -144,7 +144,7 @@

if err := r.testConnections(); err != nil {
if r.logger != nil {
r.logger.Errorf("failed to connect to Redis at '%s', error: %v", r.cfg.Addr, err)
r.logger.Errorf("failed to connect to Redis [address hidden], error: %v", err)
}

go r.retryConnect()
@@ -158,12 +158,12 @@

if err := r.queryConn.Ping(ctx).Err(); err != nil {
if r.logger != nil {
r.logger.Errorf("failed to connect query connection to Redis at '%s', error: %v", r.cfg.Addr, err)
r.logger.Errorf("failed to connect query connection to Redis [address hidden], error: %v", err)
}
}

if r.logger != nil {
r.logger.Logf("connected to Redis at '%s'", r.cfg.Addr)
r.logger.Logf("connected to Redis [address hidden]")
}
}

Copilot is powered by AI and may make mistakes. Always verify output.
}

if r.logger != nil {
r.logger.Logf("connected to Redis at '%s'", r.cfg.Addr)

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

Sensitive data returned by an access to password
flows to a logging call.

Copilot Autofix

AI 6 days ago

To safely fix the issue, avoid logging any potentially sensitive information such as host addresses or URIs that may contain embedded credentials. Instead, log only non-sensitive information or redact the sensitive parts before including them in logs.

Specific fix:

  • Edit only the logging call on line 166 (and by extension any other similar log calls if found) in pkg/gofr/datasource/pubsub/redis/redis.go.
  • Remove the actual address from being logged, or replace it with a redacted/placeholder string (e.g., [REDACTED] or log only the host/port after verifying no credentials are present).
  • No new imports or method definitions are needed for simply redacting or omitting the address.

Suggested changeset 1
pkg/gofr/datasource/pubsub/redis/redis.go

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/pkg/gofr/datasource/pubsub/redis/redis.go b/pkg/gofr/datasource/pubsub/redis/redis.go
--- a/pkg/gofr/datasource/pubsub/redis/redis.go
+++ b/pkg/gofr/datasource/pubsub/redis/redis.go
@@ -163,7 +163,7 @@
 	}
 
 	if r.logger != nil {
-		r.logger.Logf("connected to Redis at '%s'", r.cfg.Addr)
+		r.logger.Logf("connected to Redis") // Do not log address to avoid leaking sensitive information
 	}
 }
 
EOF
@@ -163,7 +163,7 @@
}

if r.logger != nil {
r.logger.Logf("connected to Redis at '%s'", r.cfg.Addr)
r.logger.Logf("connected to Redis") // Do not log address to avoid leaking sensitive information
}
}

Copilot is powered by AI and may make mistakes. Always verify output.
if pubErr != nil || subErr != nil || queryErr != nil {
if r.logger != nil {
r.logger.Errorf("could not connect to Redis at '%s', pub error: %v, sub error: %v, query error: %v",
r.cfg.Addr, pubErr, subErr, queryErr)

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

Sensitive data returned by an access to password
flows to a logging call.
}

if r.logger != nil {
r.logger.Logf("reconnected to Redis at '%s'", r.cfg.Addr)

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

Sensitive data returned by an access to password
flows to a logging call.

Copilot Autofix

AI 6 days ago

To safely address the vulnerability, we should ensure that any logging of connection addresses (r.cfg.Addr) omits any embedded credentials. The best way to do this is to sanitize the address before logging it. In practice, Redis connection addresses may be either bare host:port, or a URL containing potential credentials (e.g., redis://user:password@host:port/db). To fix, we should parse the address: if it's a URL, redact the password/user portion before logging; if it's host:port, log directly.

Where to change:
In pkg/gofr/datasource/pubsub/redis/redis.go, at the point of logging (lines like r.logger.Logf("reconnected to Redis at '%s'", r.cfg.Addr) and similar lines like debug/errors), always replace direct use of r.cfg.Addr with a sanitized form (e.g. a helper function such as redactRedisAddr(r.cfg.Addr)).

How to fix:

  • Add a helper (e.g., redactRedisAddr) in the file to parse addresses, redact password/user if present, and return a safe string for logging.
  • Replace all logging statements that reference r.cfg.Addr directly with calls using the helper.

What's required:
A new helper function in the file. No new external dependencies are needed, just use Go's standard net/url package to parse and redact credentials in URLs.

Suggested changeset 1
pkg/gofr/datasource/pubsub/redis/redis.go

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/pkg/gofr/datasource/pubsub/redis/redis.go b/pkg/gofr/datasource/pubsub/redis/redis.go
--- a/pkg/gofr/datasource/pubsub/redis/redis.go
+++ b/pkg/gofr/datasource/pubsub/redis/redis.go
@@ -9,6 +9,7 @@
 	"strings"
 	"sync"
 	"time"
+	"net/url"
 
 	"github.com/redis/go-redis/v9"
 	"go.opentelemetry.io/otel"
@@ -43,7 +44,9 @@
 	tracer  trace.Tracer
 }
 
-// New creates a new Redis PubSub client.
+
+
+// redactRedisAddr removes credentials from a Redis address string for safe logging.
 func New(cfg *Config) *Client {
 	if cfg == nil {
 		cfg = DefaultConfig()
@@ -119,7 +122,7 @@
 	}
 
 	if r.logger != nil {
-		r.logger.Debugf("connecting to Redis at '%s'", r.cfg.Addr)
+		r.logger.Debugf("connecting to Redis at '%s'", redactRedisAddr(r.cfg.Addr))
 	}
 
 	options, err := createRedisOptions(r.cfg)
@@ -144,7 +147,7 @@
 
 	if err := r.testConnections(); err != nil {
 		if r.logger != nil {
-			r.logger.Errorf("failed to connect to Redis at '%s', error: %v", r.cfg.Addr, err)
+			r.logger.Errorf("failed to connect to Redis at '%s', error: %v", redactRedisAddr(r.cfg.Addr), err)
 		}
 
 		go r.retryConnect()
@@ -234,14 +237,14 @@
 		if pubErr != nil || subErr != nil || queryErr != nil {
 			if r.logger != nil {
 				r.logger.Errorf("could not connect to Redis at '%s', pub error: %v, sub error: %v, query error: %v",
-					r.cfg.Addr, pubErr, subErr, queryErr)
+					redactRedisAddr(r.cfg.Addr), pubErr, subErr, queryErr)
 			}
 
 			continue
 		}
 
 		if r.logger != nil {
-			r.logger.Logf("reconnected to Redis at '%s'", r.cfg.Addr)
+			r.logger.Logf("reconnected to Redis at '%s'", redactRedisAddr(r.cfg.Addr))
 		}
 
 		// Restart subscriptions if they were active
EOF
@@ -9,6 +9,7 @@
"strings"
"sync"
"time"
"net/url"

"github.com/redis/go-redis/v9"
"go.opentelemetry.io/otel"
@@ -43,7 +44,9 @@
tracer trace.Tracer
}

// New creates a new Redis PubSub client.


// redactRedisAddr removes credentials from a Redis address string for safe logging.
func New(cfg *Config) *Client {
if cfg == nil {
cfg = DefaultConfig()
@@ -119,7 +122,7 @@
}

if r.logger != nil {
r.logger.Debugf("connecting to Redis at '%s'", r.cfg.Addr)
r.logger.Debugf("connecting to Redis at '%s'", redactRedisAddr(r.cfg.Addr))
}

options, err := createRedisOptions(r.cfg)
@@ -144,7 +147,7 @@

if err := r.testConnections(); err != nil {
if r.logger != nil {
r.logger.Errorf("failed to connect to Redis at '%s', error: %v", r.cfg.Addr, err)
r.logger.Errorf("failed to connect to Redis at '%s', error: %v", redactRedisAddr(r.cfg.Addr), err)
}

go r.retryConnect()
@@ -234,14 +237,14 @@
if pubErr != nil || subErr != nil || queryErr != nil {
if r.logger != nil {
r.logger.Errorf("could not connect to Redis at '%s', pub error: %v, sub error: %v, query error: %v",
r.cfg.Addr, pubErr, subErr, queryErr)
redactRedisAddr(r.cfg.Addr), pubErr, subErr, queryErr)
}

continue
}

if r.logger != nil {
r.logger.Logf("reconnected to Redis at '%s'", r.cfg.Addr)
r.logger.Logf("reconnected to Redis at '%s'", redactRedisAddr(r.cfg.Addr))
}

// Restart subscriptions if they were active
Copilot is powered by AI and may make mistakes. Always verify output.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Redis Pub Sub Support

2 participants