Skip to content

Commit 7237c7a

Browse files
authored
Merge pull request #38 from trimble-oss/security_updates_2.3
Potential fix for code scanning alert no. 395: Clear-text logging of sensitive information
2 parents 85c67e9 + e2addbb commit 7237c7a

3 files changed

Lines changed: 780 additions & 106 deletions

File tree

sql/analyzer/analyzer.go

Lines changed: 98 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,36 @@ func sanitizeArguments(args []interface{}) []interface{} {
316316
case plan.AuthenticationMysqlNativePassword:
317317
args[i] = "[PASSWORD_REDACTED]"
318318
default:
319-
if reflect.TypeOf(arg).Kind() == reflect.Struct {
320-
args[i] = "[STRUCT_REDACTED]"
319+
// Use reflection to handle structs and pointers to structs
320+
rv := reflect.ValueOf(arg)
321+
if rv.Kind() == reflect.Ptr {
322+
rv = rv.Elem()
323+
if rv.Kind() == reflect.Struct {
324+
args[i] = sanitizeStruct(rv)
325+
continue
326+
}
327+
}
328+
if rv.Kind() == reflect.Struct {
329+
args[i] = sanitizeStruct(rv)
330+
} else if rv.Kind() == reflect.Slice {
331+
// Recursively sanitize slice elements
332+
slice := make([]interface{}, rv.Len())
333+
for j := 0; j < rv.Len(); j++ {
334+
slice[j] = sanitizeArguments([]interface{}{rv.Index(j).Interface()})[0]
335+
}
336+
args[i] = slice
337+
} else if rv.Kind() == reflect.Map {
338+
// Recursively sanitize map values
339+
mapSanitized := make(map[interface{}]interface{})
340+
for _, key := range rv.MapKeys() {
341+
val := rv.MapIndex(key).Interface()
342+
if isSensitiveString(fmt.Sprintf("%v", key.Interface())) || isSensitive(val) {
343+
mapSanitized[key.Interface()] = "[REDACTED]"
344+
} else {
345+
mapSanitized[key.Interface()] = sanitizeArguments([]interface{}{val})[0]
346+
}
347+
}
348+
args[i] = mapSanitized
321349
} else {
322350
args[i] = "[REDACTED]"
323351
}
@@ -326,14 +354,78 @@ func sanitizeArguments(args []interface{}) []interface{} {
326354
return args
327355
}
328356

357+
func sanitizeStruct(rv reflect.Value) interface{} {
358+
if !rv.IsValid() || rv.Kind() != reflect.Struct {
359+
return "[STRUCT_REDACTED]"
360+
}
361+
rt := rv.Type()
362+
result := make(map[string]interface{})
363+
for i := 0; i < rv.NumField(); i++ {
364+
field := rt.Field(i)
365+
fieldName := field.Name
366+
fieldValue := rv.Field(i).Interface()
367+
if isSensitiveString(fieldName) || isSensitive(fieldValue) {
368+
result[fieldName] = "[REDACTED]"
369+
} else {
370+
// Recursively sanitize nested structs, slices, and maps
371+
switch rv.Field(i).Kind() {
372+
case reflect.Struct:
373+
result[fieldName] = sanitizeStruct(rv.Field(i))
374+
case reflect.Slice:
375+
slice := make([]interface{}, rv.Field(i).Len())
376+
for j := 0; j < rv.Field(i).Len(); j++ {
377+
slice[j] = sanitizeArguments([]interface{}{rv.Field(i).Index(j).Interface()})[0]
378+
}
379+
result[fieldName] = slice
380+
case reflect.Map:
381+
mapSanitized := make(map[interface{}]interface{})
382+
for _, key := range rv.Field(i).MapKeys() {
383+
val := rv.Field(i).MapIndex(key).Interface()
384+
if isSensitiveString(fmt.Sprintf("%v", key.Interface())) || isSensitive(val) {
385+
mapSanitized[key.Interface()] = "[REDACTED]"
386+
} else {
387+
mapSanitized[key.Interface()] = sanitizeArguments([]interface{}{val})[0]
388+
}
389+
}
390+
result[fieldName] = mapSanitized
391+
default:
392+
result[fieldName] = fieldValue
393+
}
394+
}
395+
}
396+
return result
397+
}
398+
329399
func sanitizeMap(m map[string]interface{}) map[string]interface{} {
330400
for key, value := range m {
331401
if isSensitiveString(key) || isSensitive(value) {
332402
m[key] = "[REDACTED]"
333-
} else if subMap, ok := value.(map[string]interface{}); ok {
334-
m[key] = sanitizeMap(subMap)
335-
} else if subSlice, ok := value.([]interface{}); ok {
336-
m[key] = sanitizeArguments(subSlice)
403+
} else {
404+
rv := reflect.ValueOf(value)
405+
switch rv.Kind() {
406+
case reflect.Map:
407+
// Recursively sanitize map values
408+
subMap := make(map[interface{}]interface{})
409+
for _, subKey := range rv.MapKeys() {
410+
val := rv.MapIndex(subKey).Interface()
411+
if isSensitiveString(fmt.Sprintf("%v", subKey.Interface())) || isSensitive(val) {
412+
subMap[subKey.Interface()] = "[REDACTED]"
413+
} else {
414+
subMap[subKey.Interface()] = sanitizeArguments([]interface{}{val})[0]
415+
}
416+
}
417+
m[key] = subMap
418+
case reflect.Slice:
419+
slice := make([]interface{}, rv.Len())
420+
for j := 0; j < rv.Len(); j++ {
421+
slice[j] = sanitizeArguments([]interface{}{rv.Index(j).Interface()})[0]
422+
}
423+
m[key] = slice
424+
case reflect.Struct:
425+
m[key] = sanitizeStruct(rv)
426+
default:
427+
m[key] = value
428+
}
337429
}
338430
}
339431
return m

sql/mysql_db/user.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ func (u *User) ToRow(ctx *sql.Context) sql.Row {
9090
for i, col := range userTblSchema {
9191
row[i], err = col.Default.Eval(ctx, nil)
9292
if err != nil {
93-
panic(err) // Should never happen, schema is static
93+
row[i] = nil
9494
}
9595
}
9696
//TODO: once the remaining fields are added, fill those in as well

0 commit comments

Comments
 (0)