[scan] Security attack vector mapping #4

Open
opened 2026-03-23 12:54:04 +00:00 by Virgil · 1 comment
Member

Map every external input entry point: function, file:line, input source, flows into, validation, attack vector.


Implementation Plan (Spark)

Security Attack Vector Mapping

  • CLAUDE.md reviewed.
  • CODEX.md was not present in this repository.
  • Scope: exported API entry points that accept caller-controlled data, plus direct OS/environment reads. Public field-based inputs (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.
  • Common sink: (*Logger).log in log.go:169-242 writes the final log line with fmt.Fprintf(output, "%s %s %s%s\n", ...) at log.go:242.
  • Existing controls in the common sink: string values in keyvals are %q-escaped at log.go:234-236, exact-match redaction is applied with slices.Contains(redactKeys, keyStr) at log.go:227-231, and Err-derived op / stack context is auto-added at log.go:178-211.
  • Gaps in the common sink: msg, key names, error values, and other non-string values are formatted without sanitisation at log.go:221-242.

Logger Configuration And Emission

Function File:Line Input source Flows into Current validation Potential attack vector
New(opts Options) log.go:111 Caller-controlled Options.Level, Options.Output, Options.Rotation, Options.RedactKeys; optional global RotationWriterFactory Initial Logger state; opts.Output or RotationWriterFactory(*opts.Rotation) becomes Logger.output; RedactKeys copied into Logger.redactKeys and later checked during logging Falls back to os.Stderr if output is nil; only uses rotation when Rotation != nil, Filename != "", and RotationWriterFactory != nil; RedactKeys slice is cloned Path-based write/exfiltration if untrusted Rotation.Filename reaches a permissive factory; arbitrary side effects or exfiltration through a caller-supplied writer; log suppression if an untrusted config sets LevelQuiet; redaction bypass if secret keys do not exactly match configured names
(*Logger).SetLevel(level Level) log.go:136 Caller-controlled log level Logger.level, then shouldLog() in all log methods None Audit bypass or loss of forensic detail if attacker-controlled config lowers the level or uses unexpected numeric values
(*Logger).SetOutput(w io.Writer) log.go:150 Caller-controlled writer Logger.output, then fmt.Fprintf in log.go:242 None Log exfiltration, unexpected side effects in custom writers, or panic/DoS if a nil or broken writer is installed
(*Logger).SetRedactKeys(keys ...string) log.go:157 Caller-controlled key names Logger.redactKeys, then slices.Contains(redactKeys, keyStr) during formatting Slice clone only Secret leakage when caller omits aliases, case variants, or confusable keys; CPU overhead grows linearly with large redact lists
(*Logger).Debug(msg string, keyvals ...any) log.go:246 Caller-controlled msg, keyvals, and mutable Logger.StyleDebug field StyleDebug("[DBG]") -> (*Logger).log -> fmt.Fprintf Level gate only; string keyvals values are quoted; exact-match redaction for configured keys; no nil check on StyleDebug Log forging or parser confusion via unsanitised msg, key names, error strings, or non-string fmt.Stringer values; secret leakage in msg or non-redacted fields; nil style function can panic
(*Logger).Info(msg string, keyvals ...any) log.go:253 Caller-controlled msg, keyvals, and mutable Logger.StyleInfo field StyleInfo("[INF]") -> (*Logger).log -> fmt.Fprintf Same controls as Debug Same attack surface as Debug: log injection, secret leakage outside exact-key redaction, and nil-style panic/DoS
(*Logger).Warn(msg string, keyvals ...any) log.go:260 Caller-controlled msg, keyvals, and mutable Logger.StyleWarn field StyleWarn("[WRN]") -> (*Logger).log -> fmt.Fprintf Same controls as Debug Same attack surface as Debug: log injection, secret leakage outside exact-key redaction, and nil-style panic/DoS
(*Logger).Error(msg string, keyvals ...any) log.go:267 Caller-controlled msg, keyvals, and mutable Logger.StyleError field StyleError("[ERR]") -> (*Logger).log -> fmt.Fprintf Same controls as Debug Same attack surface as Debug; higher impact because error logs are more likely to be consumed by SIEMs and incident tooling
(*Logger).Security(msg string, keyvals ...any) log.go:276 Caller-controlled msg, keyvals, and mutable Logger.StyleSecurity field StyleSecurity("[SEC]") -> (*Logger).log -> fmt.Fprintf Uses LevelError threshold so security events still emit when normal info logging is disabled; otherwise same controls as Debug Spoofed or injected security events if untrusted text reaches msg / keyvals; secret leakage in high-signal security logs; nil-style panic/DoS
Username() log.go:284 OS account lookup from user.Current() and environment variables USER / USERNAME Returned username string to caller Uses user.Current() first; falls back to USER, then USERNAME; no normalisation or escaping Username spoofing in untrusted/containerised environments where env vars are attacker-controlled; downstream log/UI injection if callers print the returned value without escaping
SetDefault(l *Logger) log.go:305 Caller-controlled logger pointer and its mutable fields (output, Style*, redact config, level) Global defaultLogger, then all package-level log functions plus LogError, LogWarn, and Must None Nil logger causes later panic/DoS; swapping the default logger can redirect logs, disable redaction, or install panicking style/output hooks globally
SetLevel(level Level) log.go:310 Caller-controlled log level defaultLogger.SetLevel(level) None beyond instance setter behaviour Same as (*Logger).SetLevel, but process-global
SetRedactKeys(keys ...string) log.go:315 Caller-controlled redact keys defaultLogger.SetRedactKeys(keys...) None beyond instance setter behaviour Same as (*Logger).SetRedactKeys, but process-global
Debug(msg string, keyvals ...any) log.go:320 Caller-controlled msg and keyvals routed through the global logger defaultLogger.Debug(...) -> (*Logger).log -> fmt.Fprintf Same controls as (*Logger).Debug; additionally depends on defaultLogger not being nil Same as (*Logger).Debug, plus global DoS if defaultLogger was set to nil
Info(msg string, keyvals ...any) log.go:325 Caller-controlled msg and keyvals routed through the global logger defaultLogger.Info(...) -> (*Logger).log -> fmt.Fprintf Same controls as (*Logger).Info; additionally depends on defaultLogger not being nil Same as (*Logger).Info, plus global DoS if defaultLogger was set to nil
Warn(msg string, keyvals ...any) log.go:330 Caller-controlled msg and keyvals routed through the global logger defaultLogger.Warn(...) -> (*Logger).log -> fmt.Fprintf Same controls as (*Logger).Warn; additionally depends on defaultLogger not being nil Same as (*Logger).Warn, plus global DoS if defaultLogger was set to nil
Error(msg string, keyvals ...any) log.go:335 Caller-controlled msg and keyvals routed through the global logger defaultLogger.Error(...) -> (*Logger).log -> fmt.Fprintf Same controls as (*Logger).Error; additionally depends on defaultLogger not being nil Same as (*Logger).Error, plus global DoS if defaultLogger was set to nil
Security(msg string, keyvals ...any) log.go:340 Caller-controlled msg and keyvals routed through the global logger defaultLogger.Security(...) -> (*Logger).log -> fmt.Fprintf Same controls as (*Logger).Security; additionally depends on defaultLogger not being nil Same as (*Logger).Security, plus global DoS if defaultLogger was set to nil

Error Construction And Emission

Function File:Line Input source Flows into Current validation Potential attack vector
(*Err).Error() errors.go:25 Public Err.Op, Err.Msg, Err.Err, and Err.Code fields, including direct struct literal construction by callers Returned error string via fmt.Sprintf; if the error is later logged as a non-string value, the text reaches (*Logger).log -> fmt.Fprintf None Log injection or response spoofing via attacker-controlled op/message/code text; secret disclosure via underlying error text; machine-readable code spoofing
E(op, msg string, err error) errors.go:56 Caller-controlled op, msg, err New Err instance, then (*Err).Error() when rendered None Same as (*Err).Error(): attacker-controlled context and underlying error text can be surfaced in logs or responses
Wrap(err error, op, msg string) errors.go:67 Caller-controlled err, op, msg New Err wrapper; preserves existing Code from wrapped *Err if present Returns nil when err == nil; preserves code if wrapped error is an *Err Untrusted wrapped errors can carry misleading Code / Op context forward; op/msg text is not sanitised before later logging or presentation
WrapCode(err error, code, op, msg string) errors.go:86 Caller-controlled err, code, op, msg New Err with explicit code, then (*Err).Error() when rendered Returns nil only when both err == nil and code == "" Error-code spoofing; untrusted message/op text can be pushed into logs or external error responses
NewCode(code, msg string) errors.go:99 Caller-controlled code, msg New Err with no underlying error None Same as WrapCode without an underlying cause: spoofed codes and unsanitised user-facing text
NewError(text string) errors.go:119 Caller-controlled text errors.New(text) return value, then any downstream logging or response handling None Log / response injection or sensitive text disclosure when callers pass untrusted strings through as raw errors
Join(errs ...error) errors.go:125 Caller-controlled error list errors.Join(errs...), then downstream Error() / logging Standard library behaviour only Size amplification and multi-message disclosure if attacker-controlled errors are aggregated and later surfaced verbatim
LogError(err error, op, msg string) errors.go:235 Caller-controlled err, op, msg; global defaultLogger state Wrap(err, op, msg) return value plus defaultLogger.Error(msg, "op", op, "err", err) -> fmt.Fprintf Returns nil when err == nil; otherwise inherits logger controls (quoted string values, exact-key redaction) Log injection through msg, op, or err.Error(); sensitive error disclosure; global DoS/exfiltration if defaultLogger was replaced or nil
LogWarn(err error, op, msg string) errors.go:250 Caller-controlled err, op, msg; global defaultLogger state Wrap(err, op, msg) return value plus defaultLogger.Warn(msg, "op", op, "err", err) -> fmt.Fprintf Returns nil when err == nil; otherwise inherits logger controls Same as LogError, with the additional risk that warnings may be treated as non-critical and reviewed less carefully
Must(err error, op, msg string) errors.go:265 Caller-controlled err, op, msg; global defaultLogger state defaultLogger.Error(msg, "op", op, "err", err) -> fmt.Fprintf, then panic(Wrap(err, op, msg)) Only executes when err != nil; otherwise same logger controls as LogError Attacker-triggerable panic/DoS if external input can force the error path; same log injection and disclosure risks as LogError before the panic

Error Inspection Helpers

Function File:Line Input source Flows into Current validation Potential attack vector
(*Err).Unwrap() errors.go:43 Public Err.Err field Returned underlying error None No direct sink in this package; risk comes from whatever the wrapped error does when callers continue processing it
Is(err, target error) errors.go:107 Caller-controlled err, target errors.Is(err, target) return value Standard library behaviour only Minimal direct attack surface here; any custom Is semantics come from attacker-supplied error implementations
As(err error, target any) errors.go:113 Caller-controlled err, target errors.As(err, target) return value No wrapper-side validation of target Invalid target values can panic through errors.As, creating an application-level DoS if misuse is reachable
Op(err error) errors.go:133 Caller-controlled error chain Extracted Err.Op string Type-check via errors.As; otherwise none Spoofed operation names if callers trust attacker-controlled *Err values for audit, metrics, or access decisions
ErrCode(err error) errors.go:143 Caller-controlled error chain Extracted Err.Code string Type-check via errors.As; otherwise none Spoofed machine-readable error codes if callers trust attacker-controlled wrapped errors
Message(err error) errors.go:153 Caller-controlled error chain Extracted Err.Msg or err.Error() string Returns "" for nil; otherwise none Unsanitised attacker-controlled message text can be re-used in logs, UIs, or API responses
Root(err error) errors.go:166 Caller-controlled error chain Returned deepest unwrapped error Returns nil for nil; otherwise none Minimal direct sink, but can expose a sensitive root error that callers later surface verbatim
AllOps(err error) errors.go:181 Caller-controlled error chain Iterator over all Err.Op values Traverses errors.Unwrap chain; ignores non-*Err nodes Long attacker-controlled wrap chains can increase CPU work; extracted op strings remain unsanitised
StackTrace(err error) errors.go:198 Caller-controlled error chain []string of operation names None beyond AllOps traversal Memory growth proportional to chain length; untrusted op strings may later be logged or displayed
FormatStackTrace(err error) errors.go:207 Caller-controlled error chain Joined stack string via strings.Join(ops, " -> ") Returns "" when no ops are found; otherwise none Log / UI injection if untrusted op names are later rendered without escaping; size amplification for deep chains
Map every external input entry point: function, file:line, input source, flows into, validation, attack vector. --- ## Implementation Plan (Spark) # Security Attack Vector Mapping - `CLAUDE.md` reviewed. - `CODEX.md` was not present in this repository. - Scope: exported API entry points that accept caller-controlled data, plus direct OS/environment reads. Public field-based inputs (`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. - Common sink: `(*Logger).log` in `log.go:169`-`242` writes the final log line with `fmt.Fprintf(output, "%s %s %s%s\n", ...)` at `log.go:242`. - Existing controls in the common sink: string values in `keyvals` are `%q`-escaped at `log.go:234`-`236`, exact-match redaction is applied with `slices.Contains(redactKeys, keyStr)` at `log.go:227`-`231`, and `Err`-derived `op` / `stack` context is auto-added at `log.go:178`-`211`. - Gaps in the common sink: `msg`, key names, `error` values, and other non-string values are formatted without sanitisation at `log.go:221`-`242`. ## Logger Configuration And Emission | Function | File:Line | Input source | Flows into | Current validation | Potential attack vector | | --- | --- | --- | --- | --- | --- | | `New(opts Options)` | `log.go:111` | Caller-controlled `Options.Level`, `Options.Output`, `Options.Rotation`, `Options.RedactKeys`; optional global `RotationWriterFactory` | Initial `Logger` state; `opts.Output` or `RotationWriterFactory(*opts.Rotation)` becomes `Logger.output`; `RedactKeys` copied into `Logger.redactKeys` and later checked during logging | Falls back to `os.Stderr` if output is `nil`; only uses rotation when `Rotation != nil`, `Filename != ""`, and `RotationWriterFactory != nil`; `RedactKeys` slice is cloned | Path-based write/exfiltration if untrusted `Rotation.Filename` reaches a permissive factory; arbitrary side effects or exfiltration through a caller-supplied writer; log suppression if an untrusted config sets `LevelQuiet`; redaction bypass if secret keys do not exactly match configured names | | `(*Logger).SetLevel(level Level)` | `log.go:136` | Caller-controlled log level | `Logger.level`, then `shouldLog()` in all log methods | None | Audit bypass or loss of forensic detail if attacker-controlled config lowers the level or uses unexpected numeric values | | `(*Logger).SetOutput(w io.Writer)` | `log.go:150` | Caller-controlled writer | `Logger.output`, then `fmt.Fprintf` in `log.go:242` | None | Log exfiltration, unexpected side effects in custom writers, or panic/DoS if a nil or broken writer is installed | | `(*Logger).SetRedactKeys(keys ...string)` | `log.go:157` | Caller-controlled key names | `Logger.redactKeys`, then `slices.Contains(redactKeys, keyStr)` during formatting | Slice clone only | Secret leakage when caller omits aliases, case variants, or confusable keys; CPU overhead grows linearly with large redact lists | | `(*Logger).Debug(msg string, keyvals ...any)` | `log.go:246` | Caller-controlled `msg`, `keyvals`, and mutable `Logger.StyleDebug` field | `StyleDebug("[DBG]")` -> `(*Logger).log` -> `fmt.Fprintf` | Level gate only; string `keyvals` values are quoted; exact-match redaction for configured keys; no nil check on `StyleDebug` | Log forging or parser confusion via unsanitised `msg`, key names, `error` strings, or non-string `fmt.Stringer` values; secret leakage in `msg` or non-redacted fields; nil style function can panic | | `(*Logger).Info(msg string, keyvals ...any)` | `log.go:253` | Caller-controlled `msg`, `keyvals`, and mutable `Logger.StyleInfo` field | `StyleInfo("[INF]")` -> `(*Logger).log` -> `fmt.Fprintf` | Same controls as `Debug` | Same attack surface as `Debug`: log injection, secret leakage outside exact-key redaction, and nil-style panic/DoS | | `(*Logger).Warn(msg string, keyvals ...any)` | `log.go:260` | Caller-controlled `msg`, `keyvals`, and mutable `Logger.StyleWarn` field | `StyleWarn("[WRN]")` -> `(*Logger).log` -> `fmt.Fprintf` | Same controls as `Debug` | Same attack surface as `Debug`: log injection, secret leakage outside exact-key redaction, and nil-style panic/DoS | | `(*Logger).Error(msg string, keyvals ...any)` | `log.go:267` | Caller-controlled `msg`, `keyvals`, and mutable `Logger.StyleError` field | `StyleError("[ERR]")` -> `(*Logger).log` -> `fmt.Fprintf` | Same controls as `Debug` | Same attack surface as `Debug`; higher impact because error logs are more likely to be consumed by SIEMs and incident tooling | | `(*Logger).Security(msg string, keyvals ...any)` | `log.go:276` | Caller-controlled `msg`, `keyvals`, and mutable `Logger.StyleSecurity` field | `StyleSecurity("[SEC]")` -> `(*Logger).log` -> `fmt.Fprintf` | Uses `LevelError` threshold so security events still emit when normal info logging is disabled; otherwise same controls as `Debug` | Spoofed or injected security events if untrusted text reaches `msg` / `keyvals`; secret leakage in high-signal security logs; nil-style panic/DoS | | `Username()` | `log.go:284` | OS account lookup from `user.Current()` and environment variables `USER` / `USERNAME` | Returned username string to caller | Uses `user.Current()` first; falls back to `USER`, then `USERNAME`; no normalisation or escaping | Username spoofing in untrusted/containerised environments where env vars are attacker-controlled; downstream log/UI injection if callers print the returned value without escaping | | `SetDefault(l *Logger)` | `log.go:305` | Caller-controlled logger pointer and its mutable fields (`output`, `Style*`, redact config, level) | Global `defaultLogger`, then all package-level log functions plus `LogError`, `LogWarn`, and `Must` | None | Nil logger causes later panic/DoS; swapping the default logger can redirect logs, disable redaction, or install panicking style/output hooks globally | | `SetLevel(level Level)` | `log.go:310` | Caller-controlled log level | `defaultLogger.SetLevel(level)` | None beyond instance setter behaviour | Same as `(*Logger).SetLevel`, but process-global | | `SetRedactKeys(keys ...string)` | `log.go:315` | Caller-controlled redact keys | `defaultLogger.SetRedactKeys(keys...)` | None beyond instance setter behaviour | Same as `(*Logger).SetRedactKeys`, but process-global | | `Debug(msg string, keyvals ...any)` | `log.go:320` | Caller-controlled `msg` and `keyvals` routed through the global logger | `defaultLogger.Debug(...)` -> `(*Logger).log` -> `fmt.Fprintf` | Same controls as `(*Logger).Debug`; additionally depends on `defaultLogger` not being nil | Same as `(*Logger).Debug`, plus global DoS if `defaultLogger` was set to nil | | `Info(msg string, keyvals ...any)` | `log.go:325` | Caller-controlled `msg` and `keyvals` routed through the global logger | `defaultLogger.Info(...)` -> `(*Logger).log` -> `fmt.Fprintf` | Same controls as `(*Logger).Info`; additionally depends on `defaultLogger` not being nil | Same as `(*Logger).Info`, plus global DoS if `defaultLogger` was set to nil | | `Warn(msg string, keyvals ...any)` | `log.go:330` | Caller-controlled `msg` and `keyvals` routed through the global logger | `defaultLogger.Warn(...)` -> `(*Logger).log` -> `fmt.Fprintf` | Same controls as `(*Logger).Warn`; additionally depends on `defaultLogger` not being nil | Same as `(*Logger).Warn`, plus global DoS if `defaultLogger` was set to nil | | `Error(msg string, keyvals ...any)` | `log.go:335` | Caller-controlled `msg` and `keyvals` routed through the global logger | `defaultLogger.Error(...)` -> `(*Logger).log` -> `fmt.Fprintf` | Same controls as `(*Logger).Error`; additionally depends on `defaultLogger` not being nil | Same as `(*Logger).Error`, plus global DoS if `defaultLogger` was set to nil | | `Security(msg string, keyvals ...any)` | `log.go:340` | Caller-controlled `msg` and `keyvals` routed through the global logger | `defaultLogger.Security(...)` -> `(*Logger).log` -> `fmt.Fprintf` | Same controls as `(*Logger).Security`; additionally depends on `defaultLogger` not being nil | Same as `(*Logger).Security`, plus global DoS if `defaultLogger` was set to nil | ## Error Construction And Emission | Function | File:Line | Input source | Flows into | Current validation | Potential attack vector | | --- | --- | --- | --- | --- | --- | | `(*Err).Error()` | `errors.go:25` | Public `Err.Op`, `Err.Msg`, `Err.Err`, and `Err.Code` fields, including direct struct literal construction by callers | Returned error string via `fmt.Sprintf`; if the error is later logged as a non-string value, the text reaches `(*Logger).log` -> `fmt.Fprintf` | None | Log injection or response spoofing via attacker-controlled op/message/code text; secret disclosure via underlying error text; machine-readable code spoofing | | `E(op, msg string, err error)` | `errors.go:56` | Caller-controlled `op`, `msg`, `err` | New `Err` instance, then `(*Err).Error()` when rendered | None | Same as `(*Err).Error()`: attacker-controlled context and underlying error text can be surfaced in logs or responses | | `Wrap(err error, op, msg string)` | `errors.go:67` | Caller-controlled `err`, `op`, `msg` | New `Err` wrapper; preserves existing `Code` from wrapped `*Err` if present | Returns `nil` when `err == nil`; preserves code if wrapped error is an `*Err` | Untrusted wrapped errors can carry misleading `Code` / `Op` context forward; op/msg text is not sanitised before later logging or presentation | | `WrapCode(err error, code, op, msg string)` | `errors.go:86` | Caller-controlled `err`, `code`, `op`, `msg` | New `Err` with explicit code, then `(*Err).Error()` when rendered | Returns `nil` only when both `err == nil` and `code == ""` | Error-code spoofing; untrusted message/op text can be pushed into logs or external error responses | | `NewCode(code, msg string)` | `errors.go:99` | Caller-controlled `code`, `msg` | New `Err` with no underlying error | None | Same as `WrapCode` without an underlying cause: spoofed codes and unsanitised user-facing text | | `NewError(text string)` | `errors.go:119` | Caller-controlled text | `errors.New(text)` return value, then any downstream logging or response handling | None | Log / response injection or sensitive text disclosure when callers pass untrusted strings through as raw errors | | `Join(errs ...error)` | `errors.go:125` | Caller-controlled error list | `errors.Join(errs...)`, then downstream `Error()` / logging | Standard library behaviour only | Size amplification and multi-message disclosure if attacker-controlled errors are aggregated and later surfaced verbatim | | `LogError(err error, op, msg string)` | `errors.go:235` | Caller-controlled `err`, `op`, `msg`; global `defaultLogger` state | `Wrap(err, op, msg)` return value plus `defaultLogger.Error(msg, "op", op, "err", err)` -> `fmt.Fprintf` | Returns `nil` when `err == nil`; otherwise inherits logger controls (quoted string values, exact-key redaction) | Log injection through `msg`, `op`, or `err.Error()`; sensitive error disclosure; global DoS/exfiltration if `defaultLogger` was replaced or nil | | `LogWarn(err error, op, msg string)` | `errors.go:250` | Caller-controlled `err`, `op`, `msg`; global `defaultLogger` state | `Wrap(err, op, msg)` return value plus `defaultLogger.Warn(msg, "op", op, "err", err)` -> `fmt.Fprintf` | Returns `nil` when `err == nil`; otherwise inherits logger controls | Same as `LogError`, with the additional risk that warnings may be treated as non-critical and reviewed less carefully | | `Must(err error, op, msg string)` | `errors.go:265` | Caller-controlled `err`, `op`, `msg`; global `defaultLogger` state | `defaultLogger.Error(msg, "op", op, "err", err)` -> `fmt.Fprintf`, then `panic(Wrap(err, op, msg))` | Only executes when `err != nil`; otherwise same logger controls as `LogError` | Attacker-triggerable panic/DoS if external input can force the error path; same log injection and disclosure risks as `LogError` before the panic | ## Error Inspection Helpers | Function | File:Line | Input source | Flows into | Current validation | Potential attack vector | | --- | --- | --- | --- | --- | --- | | `(*Err).Unwrap()` | `errors.go:43` | Public `Err.Err` field | Returned underlying error | None | No direct sink in this package; risk comes from whatever the wrapped error does when callers continue processing it | | `Is(err, target error)` | `errors.go:107` | Caller-controlled `err`, `target` | `errors.Is(err, target)` return value | Standard library behaviour only | Minimal direct attack surface here; any custom `Is` semantics come from attacker-supplied error implementations | | `As(err error, target any)` | `errors.go:113` | Caller-controlled `err`, `target` | `errors.As(err, target)` return value | No wrapper-side validation of `target` | Invalid `target` values can panic through `errors.As`, creating an application-level DoS if misuse is reachable | | `Op(err error)` | `errors.go:133` | Caller-controlled error chain | Extracted `Err.Op` string | Type-check via `errors.As`; otherwise none | Spoofed operation names if callers trust attacker-controlled `*Err` values for audit, metrics, or access decisions | | `ErrCode(err error)` | `errors.go:143` | Caller-controlled error chain | Extracted `Err.Code` string | Type-check via `errors.As`; otherwise none | Spoofed machine-readable error codes if callers trust attacker-controlled wrapped errors | | `Message(err error)` | `errors.go:153` | Caller-controlled error chain | Extracted `Err.Msg` or `err.Error()` string | Returns `""` for `nil`; otherwise none | Unsanitised attacker-controlled message text can be re-used in logs, UIs, or API responses | | `Root(err error)` | `errors.go:166` | Caller-controlled error chain | Returned deepest unwrapped error | Returns `nil` for `nil`; otherwise none | Minimal direct sink, but can expose a sensitive root error that callers later surface verbatim | | `AllOps(err error)` | `errors.go:181` | Caller-controlled error chain | Iterator over all `Err.Op` values | Traverses `errors.Unwrap` chain; ignores non-`*Err` nodes | Long attacker-controlled wrap chains can increase CPU work; extracted op strings remain unsanitised | | `StackTrace(err error)` | `errors.go:198` | Caller-controlled error chain | `[]string` of operation names | None beyond `AllOps` traversal | Memory growth proportional to chain length; untrusted op strings may later be logged or displayed | | `FormatStackTrace(err error)` | `errors.go:207` | Caller-controlled error chain | Joined stack string via `strings.Join(ops, " -> ")` | Returns `""` when no ops are found; otherwise none | Log / UI injection if untrusted op names are later rendered without escaping; size amplification for deep chains |
Author
Member

Security Scan: Attack Vector Map completed. Details in agent log.

## Security Scan: Attack Vector Map completed. Details in agent log.
Sign in to join this conversation.
No description provided.