Skip to content

Potential fix for code scanning alert no. 84: Clear-text logging of sensitive information#91

Merged
intel352 merged 1 commit into
mainfrom
alert-autofix-84
Mar 23, 2026
Merged

Potential fix for code scanning alert no. 84: Clear-text logging of sensitive information#91
intel352 merged 1 commit into
mainfrom
alert-autofix-84

Conversation

@intel352
Copy link
Copy Markdown
Contributor

Potential fix for https://github.com/GoCodeAlone/modular/security/code-scanning/84

In general, to fix clear-text logging of potentially sensitive data flowing through generic logging decorators, we should ensure that any untrusted or header-derived values are either omitted, masked, or sanitized before being passed to the underlying logger. Since LoggerDecorator and its implementations are generic and receive args ...any from many call sites (including DryRunHandler.logDryRunResult), the safest fix that does not change external behavior is to introduce a small sanitization step in the decorator layer that can scrub known-sensitive keys or values in the structured logging arguments.

The best targeted fix here is to add a helper in logger_decorator.go (within the shown code) that inspects args ...any as key/value pairs and masks values for keys that might contain sensitive data coming from HTTP headers (for example "tenant", "requestId", and any other we choose), or more generally redact any string values that look like they could hold secrets (optional). Then, we apply this sanitization in the single place where CodeQL points to the sink: PrefixLoggerDecorator.Debug (and, by symmetry and for consistency, we should apply the same sanitization in all PrefixLoggerDecorator methods so the decorator never forwards raw tainted args to the inner logger). This preserves existing message strings and keys while only altering logged values according to a deterministic masking rule.

Concretely:

  • In logger_decorator.go, add a private helper function, e.g. sanitizeLogArgs(args []any) []any, near the decorators, using only the standard library (strings is already imported).
  • This helper will:
    • Return early if len(args) == 0.
    • Assume structured logging with alternating key/value pairs (as used in logDryRunResult), iterate over the slice, and for every string key in positions 0,2,4,...:
      • If the key equals "tenant" or "requestId" (or both, matching the dry-run logger), replace the corresponding value (if present) with a masked form such as "***".
  • In each of PrefixLoggerDecorator.Info, .Error, .Warn, and .Debug, call sanitizeLogArgs(args) before passing them down to d.inner.*.
  • We keep the function signature the same and avoid touching other files; all changes are confined to logger_decorator.go within the shown regions.
  • No new external dependencies are needed; we can implement masking logic with basic Go operations.

Suggested fixes powered by Copilot Autofix. Review carefully before merging.

…ensitive information

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 12, 2026 10:53
@intel352 intel352 marked this pull request as ready for review March 12, 2026 10:53
@github-actions
Copy link
Copy Markdown
Contributor

📋 API Contract Changes Summary

No breaking changes detected - only additions and non-breaking modifications

Changed Components:

Core Framework

Contract diff saved to artifacts/diffs/core.json

Module: auth

Contract diff saved to artifacts/diffs/auth.json

Module: cache

Contract diff saved to artifacts/diffs/cache.json

Module: chimux

Contract diff saved to artifacts/diffs/chimux.json

Module: configwatcher

Contract diff saved to artifacts/diffs/configwatcher.json

Module: database

Contract diff saved to artifacts/diffs/database.json

Module: eventbus

Contract diff saved to artifacts/diffs/eventbus.json

Module: eventlogger

Contract diff saved to artifacts/diffs/eventlogger.json

Module: httpclient

Contract diff saved to artifacts/diffs/httpclient.json

Module: httpserver

Contract diff saved to artifacts/diffs/httpserver.json

Module: jsonschema

Contract diff saved to artifacts/diffs/jsonschema.json

Module: letsencrypt

Contract diff saved to artifacts/diffs/letsencrypt.json

Module: logmasker

Contract diff saved to artifacts/diffs/logmasker.json

Module: reverseproxy

Contract diff saved to artifacts/diffs/reverseproxy.json

Module: scheduler

Contract diff saved to artifacts/diffs/scheduler.json

Artifacts

📁 Full contract diffs and JSON artifacts are available in the workflow artifacts.

@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 12, 2026

Codecov Report

❌ Patch coverage is 63.63636% with 8 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
logger_decorator.go 63.63% 6 Missing and 2 partials ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a small sanitization layer in the logging decorator stack to mitigate CodeQL alert #84 (“clear-text logging of sensitive information”) by masking header-derived identifiers before they reach the underlying logger.

Changes:

  • Added sanitizeLogArgs(args []any) []any to mask values for specific structured-log keys (tenant, requestId).
  • Updated PrefixLoggerDecorator (Info, Error, Warn, Debug) to forward sanitized structured logging arguments to the inner logger.

Comment thread logger_decorator.go
Comment on lines +275 to +301
// sanitizeLogArgs masks potentially sensitive values in structured log arguments.
// It assumes key/value pairs (key at even index, value at odd index).
func sanitizeLogArgs(args []any) []any {
if len(args) == 0 {
return args
}

// Work on a shallow copy to avoid surprising callers that reuse the slice.
sanitized := make([]any, len(args))
copy(sanitized, args)

for i := 0; i < len(sanitized); i += 2 {
key, ok := sanitized[i].(string)
if !ok {
continue
}

// Mask values for known potentially sensitive keys.
if key == "tenant" || key == "requestId" {
valueIndex := i + 1
if valueIndex < len(sanitized) {
sanitized[valueIndex] = "***"
}
}
}

return sanitized
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sanitizeLogArgs currently allocates and copies the args slice on every log call (when args is non-empty), even when no sensitive keys are present. This adds avoidable per-log overhead for PrefixLoggerDecorator.

Consider scanning for matching keys first and only allocating/copying when a redaction is actually needed (e.g., copy-on-first-match), otherwise return the original args slice unchanged.

Copilot uses AI. Check for mistakes.
Comment thread logger_decorator.go
Comment on lines 331 to +348
func (d *PrefixLoggerDecorator) Info(msg string, args ...any) {
d.inner.Info(d.formatMessage(msg), args...)
safeArgs := sanitizeLogArgs(args)
d.inner.Info(d.formatMessage(msg), safeArgs...)
}

func (d *PrefixLoggerDecorator) Error(msg string, args ...any) {
d.inner.Error(d.formatMessage(msg), args...)
safeArgs := sanitizeLogArgs(args)
d.inner.Error(d.formatMessage(msg), safeArgs...)
}

func (d *PrefixLoggerDecorator) Warn(msg string, args ...any) {
d.inner.Warn(d.formatMessage(msg), args...)
safeArgs := sanitizeLogArgs(args)
d.inner.Warn(d.formatMessage(msg), safeArgs...)
}

func (d *PrefixLoggerDecorator) Debug(msg string, args ...any) {
d.inner.Debug(d.formatMessage(msg), args...)
safeArgs := sanitizeLogArgs(args)
d.inner.Debug(d.formatMessage(msg), safeArgs...)
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New redaction behavior is introduced (masking values for "tenant" and "requestId" keys), but there are existing tests for logger_decorator.go and none appear to assert this new behavior. Please add a focused unit test that verifies PrefixLoggerDecorator forwards masked values for these keys (and leaves other keys unchanged) to prevent regressions and to validate the intended security fix.

Copilot generated this review using guidance from repository custom instructions.
Comment thread logger_decorator.go Dismissed
Comment thread logger_decorator.go Dismissed
Comment thread logger_decorator.go Dismissed
Comment thread logger_decorator.go Dismissed
@intel352 intel352 merged commit 8d64091 into main Mar 23, 2026
30 of 31 checks passed
@intel352 intel352 deleted the alert-autofix-84 branch March 23, 2026 00:16
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.

3 participants