[scan] Security attack vector mapping #4
Labels
No labels
needs-review
needs-review
needs-review
athena
athena-gemini
audit
clotho
clotho-gemini
codex
darbs-claude
security
wiki
No milestone
No project
No assignees
1 participant
Notifications
Due date
-
Dependencies
No dependencies set.
Reference: core/go-log#4
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Map every external input entry point: function, file:line, input source, flows into, validation, attack vector.
Implementation Plan (Spark)
Security Attack Vector Mapping
CLAUDE.mdreviewed.CODEX.mdwas not present in this repository.Logger.Style*,Err.Op,Err.Msg,Err.Err,Err.Code) are called out in the relevant rows because they are consumed by methods rather than setter functions.(*Logger).loginlog.go:169-242writes the final log line withfmt.Fprintf(output, "%s %s %s%s\n", ...)atlog.go:242.keyvalsare%q-escaped atlog.go:234-236, exact-match redaction is applied withslices.Contains(redactKeys, keyStr)atlog.go:227-231, andErr-derivedop/stackcontext is auto-added atlog.go:178-211.msg, key names,errorvalues, and other non-string values are formatted without sanitisation atlog.go:221-242.Logger Configuration And Emission
New(opts Options)log.go:111Options.Level,Options.Output,Options.Rotation,Options.RedactKeys; optional globalRotationWriterFactoryLoggerstate;opts.OutputorRotationWriterFactory(*opts.Rotation)becomesLogger.output;RedactKeyscopied intoLogger.redactKeysand later checked during loggingos.Stderrif output isnil; only uses rotation whenRotation != nil,Filename != "", andRotationWriterFactory != nil;RedactKeysslice is clonedRotation.Filenamereaches a permissive factory; arbitrary side effects or exfiltration through a caller-supplied writer; log suppression if an untrusted config setsLevelQuiet; redaction bypass if secret keys do not exactly match configured names(*Logger).SetLevel(level Level)log.go:136Logger.level, thenshouldLog()in all log methods(*Logger).SetOutput(w io.Writer)log.go:150Logger.output, thenfmt.Fprintfinlog.go:242(*Logger).SetRedactKeys(keys ...string)log.go:157Logger.redactKeys, thenslices.Contains(redactKeys, keyStr)during formatting(*Logger).Debug(msg string, keyvals ...any)log.go:246msg,keyvals, and mutableLogger.StyleDebugfieldStyleDebug("[DBG]")->(*Logger).log->fmt.Fprintfkeyvalsvalues are quoted; exact-match redaction for configured keys; no nil check onStyleDebugmsg, key names,errorstrings, or non-stringfmt.Stringervalues; secret leakage inmsgor non-redacted fields; nil style function can panic(*Logger).Info(msg string, keyvals ...any)log.go:253msg,keyvals, and mutableLogger.StyleInfofieldStyleInfo("[INF]")->(*Logger).log->fmt.FprintfDebugDebug: log injection, secret leakage outside exact-key redaction, and nil-style panic/DoS(*Logger).Warn(msg string, keyvals ...any)log.go:260msg,keyvals, and mutableLogger.StyleWarnfieldStyleWarn("[WRN]")->(*Logger).log->fmt.FprintfDebugDebug: log injection, secret leakage outside exact-key redaction, and nil-style panic/DoS(*Logger).Error(msg string, keyvals ...any)log.go:267msg,keyvals, and mutableLogger.StyleErrorfieldStyleError("[ERR]")->(*Logger).log->fmt.FprintfDebugDebug; higher impact because error logs are more likely to be consumed by SIEMs and incident tooling(*Logger).Security(msg string, keyvals ...any)log.go:276msg,keyvals, and mutableLogger.StyleSecurityfieldStyleSecurity("[SEC]")->(*Logger).log->fmt.FprintfLevelErrorthreshold so security events still emit when normal info logging is disabled; otherwise same controls asDebugmsg/keyvals; secret leakage in high-signal security logs; nil-style panic/DoSUsername()log.go:284user.Current()and environment variablesUSER/USERNAMEuser.Current()first; falls back toUSER, thenUSERNAME; no normalisation or escapingSetDefault(l *Logger)log.go:305output,Style*, redact config, level)defaultLogger, then all package-level log functions plusLogError,LogWarn, andMustSetLevel(level Level)log.go:310defaultLogger.SetLevel(level)(*Logger).SetLevel, but process-globalSetRedactKeys(keys ...string)log.go:315defaultLogger.SetRedactKeys(keys...)(*Logger).SetRedactKeys, but process-globalDebug(msg string, keyvals ...any)log.go:320msgandkeyvalsrouted through the global loggerdefaultLogger.Debug(...)->(*Logger).log->fmt.Fprintf(*Logger).Debug; additionally depends ondefaultLoggernot being nil(*Logger).Debug, plus global DoS ifdefaultLoggerwas set to nilInfo(msg string, keyvals ...any)log.go:325msgandkeyvalsrouted through the global loggerdefaultLogger.Info(...)->(*Logger).log->fmt.Fprintf(*Logger).Info; additionally depends ondefaultLoggernot being nil(*Logger).Info, plus global DoS ifdefaultLoggerwas set to nilWarn(msg string, keyvals ...any)log.go:330msgandkeyvalsrouted through the global loggerdefaultLogger.Warn(...)->(*Logger).log->fmt.Fprintf(*Logger).Warn; additionally depends ondefaultLoggernot being nil(*Logger).Warn, plus global DoS ifdefaultLoggerwas set to nilError(msg string, keyvals ...any)log.go:335msgandkeyvalsrouted through the global loggerdefaultLogger.Error(...)->(*Logger).log->fmt.Fprintf(*Logger).Error; additionally depends ondefaultLoggernot being nil(*Logger).Error, plus global DoS ifdefaultLoggerwas set to nilSecurity(msg string, keyvals ...any)log.go:340msgandkeyvalsrouted through the global loggerdefaultLogger.Security(...)->(*Logger).log->fmt.Fprintf(*Logger).Security; additionally depends ondefaultLoggernot being nil(*Logger).Security, plus global DoS ifdefaultLoggerwas set to nilError Construction And Emission
(*Err).Error()errors.go:25Err.Op,Err.Msg,Err.Err, andErr.Codefields, including direct struct literal construction by callersfmt.Sprintf; if the error is later logged as a non-string value, the text reaches(*Logger).log->fmt.FprintfE(op, msg string, err error)errors.go:56op,msg,errErrinstance, then(*Err).Error()when rendered(*Err).Error(): attacker-controlled context and underlying error text can be surfaced in logs or responsesWrap(err error, op, msg string)errors.go:67err,op,msgErrwrapper; preserves existingCodefrom wrapped*Errif presentnilwhenerr == nil; preserves code if wrapped error is an*ErrCode/Opcontext forward; op/msg text is not sanitised before later logging or presentationWrapCode(err error, code, op, msg string)errors.go:86err,code,op,msgErrwith explicit code, then(*Err).Error()when renderednilonly when botherr == nilandcode == ""NewCode(code, msg string)errors.go:99code,msgErrwith no underlying errorWrapCodewithout an underlying cause: spoofed codes and unsanitised user-facing textNewError(text string)errors.go:119errors.New(text)return value, then any downstream logging or response handlingJoin(errs ...error)errors.go:125errors.Join(errs...), then downstreamError()/ loggingLogError(err error, op, msg string)errors.go:235err,op,msg; globaldefaultLoggerstateWrap(err, op, msg)return value plusdefaultLogger.Error(msg, "op", op, "err", err)->fmt.Fprintfnilwhenerr == nil; otherwise inherits logger controls (quoted string values, exact-key redaction)msg,op, orerr.Error(); sensitive error disclosure; global DoS/exfiltration ifdefaultLoggerwas replaced or nilLogWarn(err error, op, msg string)errors.go:250err,op,msg; globaldefaultLoggerstateWrap(err, op, msg)return value plusdefaultLogger.Warn(msg, "op", op, "err", err)->fmt.Fprintfnilwhenerr == nil; otherwise inherits logger controlsLogError, with the additional risk that warnings may be treated as non-critical and reviewed less carefullyMust(err error, op, msg string)errors.go:265err,op,msg; globaldefaultLoggerstatedefaultLogger.Error(msg, "op", op, "err", err)->fmt.Fprintf, thenpanic(Wrap(err, op, msg))err != nil; otherwise same logger controls asLogErrorLogErrorbefore the panicError Inspection Helpers
(*Err).Unwrap()errors.go:43Err.ErrfieldIs(err, target error)errors.go:107err,targeterrors.Is(err, target)return valueIssemantics come from attacker-supplied error implementationsAs(err error, target any)errors.go:113err,targeterrors.As(err, target)return valuetargettargetvalues can panic througherrors.As, creating an application-level DoS if misuse is reachableOp(err error)errors.go:133Err.Opstringerrors.As; otherwise none*Errvalues for audit, metrics, or access decisionsErrCode(err error)errors.go:143Err.Codestringerrors.As; otherwise noneMessage(err error)errors.go:153Err.Msgorerr.Error()string""fornil; otherwise noneRoot(err error)errors.go:166nilfornil; otherwise noneAllOps(err error)errors.go:181Err.Opvalueserrors.Unwrapchain; ignores non-*ErrnodesStackTrace(err error)errors.go:198[]stringof operation namesAllOpstraversalFormatStackTrace(err error)errors.go:207strings.Join(ops, " -> ")""when no ops are found; otherwise noneSecurity Scan: Attack Vector Map completed. Details in agent log.