From fa7e9be701522695097c5c47d22ebf148c02b99e Mon Sep 17 00:00:00 2001 From: joel-rieke <53945260+joel-rieke@users.noreply.github.com> Date: Mon, 28 Jul 2025 12:51:31 -0700 Subject: [PATCH 1/4] Potential fix for code scanning alert no. 231: Incorrect conversion between integer types Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- sql/timetype.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sql/timetype.go b/sql/timetype.go index ad3cface2c..7e9f97d479 100644 --- a/sql/timetype.go +++ b/sql/timetype.go @@ -175,6 +175,9 @@ func (t timespanType) ConvertToTimespan(v interface{}) (Timespan, error) { case float32: return t.ConvertToTimespan(float64(value)) case float64: + if value < float64(math.MinInt64) || value > float64(math.MaxInt64) { + return Timespan(0), fmt.Errorf("float64 value %f exceeds int64 bounds", value) + } intValue := int64(value) microseconds := int64Abs(int64(math.Round((value - float64(intValue)) * float64(microsecondsPerSecond)))) absValue := int64Abs(intValue) From cdae0b7ddecaa9416ac555f468b3333433943ce6 Mon Sep 17 00:00:00 2001 From: joel-rieke <53945260+joel-rieke@users.noreply.github.com> Date: Mon, 28 Jul 2025 12:53:34 -0700 Subject: [PATCH 2/4] Potential fix for code scanning alert no. 276: Incorrect conversion between integer types Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- sql/system_settype.go | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/sql/system_settype.go b/sql/system_settype.go index 0fe57e599c..45e8fcf157 100644 --- a/sql/system_settype.go +++ b/sql/system_settype.go @@ -90,15 +90,13 @@ func (t systemSetType) Convert(v interface{}) (interface{}, error) { case float64: // Float values aren't truly accepted, but the engine will give them when it should give ints. // Therefore, if the float doesn't have a fractional portion, we treat it as an int. - if value >= float64(math.MinInt64) && value <= float64(math.MaxInt64) { - if math.Trunc(value) == value { // Ensure no fractional part exists - // Additional bounds check for out-of-range values - if value < float64(math.MinInt64) || value > float64(math.MaxInt64) { - return nil, ErrInvalidSystemVariableValue.New(t.varName, v) // Reject out-of-range values - } - intValue := int64(value) - return t.SetType.Convert(intValue) + if math.Trunc(value) == value { // Ensure no fractional part exists + // Explicit bounds check for int64 range + if value < float64(math.MinInt64) || value > float64(math.MaxInt64) { + return nil, ErrInvalidSystemVariableValue.New(t.varName, v) // Reject out-of-range values } + intValue := int64(value) + return t.SetType.Convert(intValue) } return nil, ErrInvalidSystemVariableValue.New(t.varName, v) // Reject out-of-range values case decimal.Decimal: From feacdecf182936f59d2ecab58e9d21e2db800216 Mon Sep 17 00:00:00 2001 From: joel-rieke <53945260+joel-rieke@users.noreply.github.com> Date: Mon, 28 Jul 2025 12:56:30 -0700 Subject: [PATCH 3/4] Potential fix for code scanning alert no. 411: Clear-text logging of sensitive information Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- sql/analyzer/analyzer.go | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/sql/analyzer/analyzer.go b/sql/analyzer/analyzer.go index 6c26d3a4a3..dcc788ad76 100644 --- a/sql/analyzer/analyzer.go +++ b/sql/analyzer/analyzer.go @@ -294,9 +294,19 @@ func (a *Analyzer) Log(msg string, args ...interface{}) { if a != nil && a.Debug { if len(a.contextStack) > 0 { ctx := strings.Join(a.contextStack, "/") - log.Infof("%s: "+msg, append([]interface{}{ctx}, sanitizeArguments(args)...)...) + sanitizedArgs := sanitizeArguments(args) + if containsSensitiveData(sanitizedArgs) { + log.Warnf("Sensitive data detected in log arguments. Logging suppressed.") + return + } + log.Infof("%s: "+msg, append([]interface{}{ctx}, sanitizedArgs...)...) } else { - log.Infof(msg, sanitizeArguments(args)...) + sanitizedArgs := sanitizeArguments(args) + if containsSensitiveData(sanitizedArgs) { + log.Warnf("Sensitive data detected in log arguments. Logging suppressed.") + return + } + log.Infof(msg, sanitizedArgs...) } } } @@ -346,7 +356,10 @@ func sanitizeArguments(args []interface{}) []interface{} { } args[i] = mapSanitized } else { - args[i] = "[REDACTED]" + // Catch-all for unhandled types + if isSensitive(fmt.Sprintf("%v", arg)) { + args[i] = "[REDACTED]" + } } } } From 4b396bb0d557a10e3a86dd20368cd7c22e22fcac Mon Sep 17 00:00:00 2001 From: Joel Rieke Date: Mon, 28 Jul 2025 13:05:06 -0700 Subject: [PATCH 4/4] More sanitizing --- sql/analyzer/analyzer.go | 76 ++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/sql/analyzer/analyzer.go b/sql/analyzer/analyzer.go index dcc788ad76..10a5f755a7 100644 --- a/sql/analyzer/analyzer.go +++ b/sql/analyzer/analyzer.go @@ -295,75 +295,73 @@ func (a *Analyzer) Log(msg string, args ...interface{}) { if len(a.contextStack) > 0 { ctx := strings.Join(a.contextStack, "/") sanitizedArgs := sanitizeArguments(args) - if containsSensitiveData(sanitizedArgs) { - log.Warnf("Sensitive data detected in log arguments. Logging suppressed.") - return - } log.Infof("%s: "+msg, append([]interface{}{ctx}, sanitizedArgs...)...) } else { sanitizedArgs := sanitizeArguments(args) - if containsSensitiveData(sanitizedArgs) { - log.Warnf("Sensitive data detected in log arguments. Logging suppressed.") - return - } log.Infof(msg, sanitizedArgs...) } } } func sanitizeArguments(args []interface{}) []interface{} { + sanitizedArgs := make([]interface{}, len(args)) for i, arg := range args { switch v := arg.(type) { case string: if isSensitiveString(v) { - args[i] = "[REDACTED]" + sanitizedArgs[i] = "[REDACTED]" + } else { + sanitizedArgs[i] = v } case map[string]interface{}: - args[i] = sanitizeMap(v) + sanitizedArgs[i] = sanitizeMap(v) case []interface{}: - args[i] = sanitizeArguments(v) + sanitizedArgs[i] = sanitizeArguments(v) case plan.AuthenticationMysqlNativePassword: - args[i] = "[PASSWORD_REDACTED]" + sanitizedArgs[i] = "[PASSWORD_REDACTED]" default: // Use reflection to handle structs and pointers to structs rv := reflect.ValueOf(arg) if rv.Kind() == reflect.Ptr { rv = rv.Elem() if rv.Kind() == reflect.Struct { - args[i] = sanitizeStruct(rv) + sanitizedArgs[i] = sanitizeStruct(rv) continue } } if rv.Kind() == reflect.Struct { - args[i] = sanitizeStruct(rv) + sanitizedArgs[i] = sanitizeStruct(rv) } else if rv.Kind() == reflect.Slice { // Recursively sanitize slice elements slice := make([]interface{}, rv.Len()) for j := 0; j < rv.Len(); j++ { slice[j] = sanitizeArguments([]interface{}{rv.Index(j).Interface()})[0] } - args[i] = slice + sanitizedArgs[i] = slice } else if rv.Kind() == reflect.Map { // Recursively sanitize map values mapSanitized := make(map[interface{}]interface{}) for _, key := range rv.MapKeys() { val := rv.MapIndex(key).Interface() - if isSensitiveString(fmt.Sprintf("%v", key.Interface())) || isSensitive(val) { + keyStr := fmt.Sprintf("%v", key.Interface()) + if isSensitiveString(keyStr) || isSensitive(val) { mapSanitized[key.Interface()] = "[REDACTED]" } else { mapSanitized[key.Interface()] = sanitizeArguments([]interface{}{val})[0] } } - args[i] = mapSanitized + sanitizedArgs[i] = mapSanitized } else { // Catch-all for unhandled types - if isSensitive(fmt.Sprintf("%v", arg)) { - args[i] = "[REDACTED]" + if strVal := fmt.Sprintf("%v", arg); isSensitiveString(strVal) { + sanitizedArgs[i] = "[REDACTED]" + } else { + sanitizedArgs[i] = arg } } } } - return args + return sanitizedArgs } func sanitizeStruct(rv reflect.Value) interface{} { @@ -393,7 +391,8 @@ func sanitizeStruct(rv reflect.Value) interface{} { mapSanitized := make(map[interface{}]interface{}) for _, key := range rv.Field(i).MapKeys() { val := rv.Field(i).MapIndex(key).Interface() - if isSensitiveString(fmt.Sprintf("%v", key.Interface())) || isSensitive(val) { + keyStr := fmt.Sprintf("%v", key.Interface()) + if isSensitiveString(keyStr) || isSensitive(val) { mapSanitized[key.Interface()] = "[REDACTED]" } else { mapSanitized[key.Interface()] = sanitizeArguments([]interface{}{val})[0] @@ -409,9 +408,10 @@ func sanitizeStruct(rv reflect.Value) interface{} { } func sanitizeMap(m map[string]interface{}) map[string]interface{} { + result := make(map[string]interface{}) for key, value := range m { if isSensitiveString(key) || isSensitive(value) { - m[key] = "[REDACTED]" + result[key] = "[REDACTED]" } else { rv := reflect.ValueOf(value) switch rv.Kind() { @@ -420,31 +420,33 @@ func sanitizeMap(m map[string]interface{}) map[string]interface{} { subMap := make(map[interface{}]interface{}) for _, subKey := range rv.MapKeys() { val := rv.MapIndex(subKey).Interface() - if isSensitiveString(fmt.Sprintf("%v", subKey.Interface())) || isSensitive(val) { + keyStr := fmt.Sprintf("%v", subKey.Interface()) + if isSensitiveString(keyStr) || isSensitive(val) { subMap[subKey.Interface()] = "[REDACTED]" } else { subMap[subKey.Interface()] = sanitizeArguments([]interface{}{val})[0] } } - m[key] = subMap + result[key] = subMap case reflect.Slice: slice := make([]interface{}, rv.Len()) for j := 0; j < rv.Len(); j++ { slice[j] = sanitizeArguments([]interface{}{rv.Index(j).Interface()})[0] } - m[key] = slice + result[key] = slice case reflect.Struct: - m[key] = sanitizeStruct(rv) + result[key] = sanitizeStruct(rv) default: - m[key] = value + result[key] = value } } } - return m + return result } +// isSensitiveString checks if a string contains sensitive information func isSensitiveString(str string) bool { - sensitiveKeywords := []string{"password", "secret", "token", "key"} + sensitiveKeywords := []string{"password", "secret", "token", "key", "auth", "credential", "private"} str = strings.ToLower(str) for _, keyword := range sensitiveKeywords { if strings.Contains(str, keyword) { @@ -454,13 +456,19 @@ func isSensitiveString(str string) bool { return false } +// isSensitive checks if a value contains sensitive information func isSensitive(arg interface{}) bool { - // Add logic to identify sensitive data (e.g., passwords) - // This may involve checking types or specific fields - if str, ok := arg.(string); ok && strings.Contains(strings.ToLower(str), "password") { - return true + if arg == nil { + return false } - return false + + // Check strings directly + if str, ok := arg.(string); ok { + return isSensitiveString(str) + } + + // Check string representation + return isSensitiveString(fmt.Sprintf("%v", arg)) } // LogNode prints the node given if Verbose logging is enabled.