CVE Patch Review

CVE-2026-5078 Root-Cause Fix for Morgan :remote-user Log Injection

CVE-2026-5078 · Updated 2026-07-10 Root-cause

Summary

Morgan 1.11.0 fixes unauthenticated log forging through the :remote-user token by escaping control characters and backslashes in the Basic Auth username before it is emitted into line-oriented logs. The patch addresses the direct sink used by the vulnerable token and adds regression tests for CRLF, NUL, tab, ESC, forged multi-line payloads, legitimate usernames, and backslashes.

Analysis

Vulnerability

CVE-2026-5078 affects Morgan versions 1.2.0 through 1.10.1 and enables unauthenticated log forging via the :remote-user token. The token derives its value from Basic Authentication credentials, and the vulnerable implementation emitted credentials.name directly into log output. Because line-oriented logs treat CR/LF as record delimiters, an attacker could supply a crafted username containing control characters and inject additional log lines or alter downstream log parsing. The issue is documented in the NVD record and the CVE record, with the remediation implemented in the upstream commit b3f5d9b.

// vulnerable behavior in :remote-user path
return credentials
  ? credentials.name
  : undefined

The exploitability is straightforward because the attacker only needs to send an Authorization: Basic ... header with a username containing CR, LF, NUL, tab, ESC, or similar control bytes. In practical terms, this is a log integrity vulnerability rather than direct code execution, but forged audit trails can materially affect incident response, alerting, and forensic trust.

Patch

The patch introduces a dedicated escapeLogField(value) helper in index.js and routes the :remote-user token through it before logging. The helper returns undefined for nullish values and otherwise converts the value to a string, escaping ASCII control characters U+0000-U+001F, U+007F, and backslashes. Named escapes are used for common characters such as \n, \r, \t, and \\; other control bytes are rendered as \uXXXX. This preserves a readable representation while preventing raw control bytes from reaching the log sink.

function escapeLogField (value) {
  if (value == null) return undefined

  return String(value).replace(/[\u0000-\u001f\u007f\\]/g, function (ch) {
    switch (ch) {
      case '\\': return '\\\\'
      case '\b': return '\\b'
      case '\f': return '\\f'
      case '\n': return '\\n'
      case '\r': return '\\r'
      case '\t': return '\\t'
      default:
        return '\\u' + ('0000' + ch.charCodeAt(0).toString(16)).slice(-4)
    }
  })
}

// patched use in :remote-user
return credentials
  ? escapeLogField(credentials.name)
  : undefined

The accompanying tests in test/morgan.js are strong and directly tied to the vulnerability. They verify that CR/LF do not create multiple log lines, that NUL bytes are escaped, that tab and ESC are neutralized, that a full advisory-style forged log payload remains a single escaped line, that normal usernames are unchanged, and that backslashes are escaped. These tests materially reduce regression risk for the specific sink fixed by the commit b3f5d9b.

Review

Pros

The patch addresses the actual root cause in the vulnerable code path: untrusted username data was written to a line-oriented log without output encoding. Escaping at the token emission point is an appropriate mitigation because the dangerous boundary is log serialization, not credential parsing. The helper covers the relevant control-byte range for log injection and also escapes backslashes, which avoids ambiguous sequences and makes the output representation stable. Test coverage is notably good: it includes both primitive control-character cases and an end-to-end forged-line payload, which demonstrates that the fix prevents record splitting rather than merely changing string contents.

Cons

The fix is scoped to the :remote-user token only. Based on the provided diff, it does not establish a generic log-field escaping policy across all Morgan tokens or custom token implementations. That is acceptable for this CVE, but it means other tokens remain dependent on their own data provenance and output safety. The patch also preserves potentially attacker-controlled content in escaped form, which is usually the right tradeoff for observability, but consumers that assume semantic trust in log fields still need to treat the value as untrusted input.

Verdict

Root-cause.

This is a well-targeted root-cause fix for CVE-2026-5078. The vulnerable sink now applies deterministic escaping before emitting :remote-user, and the regression tests prove that the original CRLF log-forging primitive no longer produces additional log records. For engineers upgrading Morgan, moving to 1.11.0 is the correct remediation per the upstream patch commit and the public vulnerability records at CVE and NVD.

Sources