Someone moved the column dividers on your spreadsheet, but every row is still on its own line
CVE-2026-87859 affects morgan, the popular Node.js HTTP request logger (~13 million weekly npm downloads). In versions prior to 1.12.1, the escapeLogField() helper does not escape the double-quote character ("). Because morgan's built-in Apache combined log format uses double quotes to delimit fields like User-Agent and Referer, an unauthenticated remote attacker can inject a " into a header value they control. A downstream log parser that splits by field position will then read attacker-supplied text as a different field — for example, a crafted User-Agent could make the recorded HTTP status appear to be something it wasn't. Crucially, no newline injection is possible, so log-record boundaries remain intact.
The vendor scored this MEDIUM 5.3 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N). That score is generous. The integrity impact is real but extremely narrow: it affects only log *parsing accuracy*, not application behaviour, data confidentiality, or availability. The attack cannot execute code, escalate privileges, or exfiltrate data. It is the third in a rapid-fire sequence of morgan log-injection CVEs (CVE-2026-5078 for CR/LF, CVE-2026-15603 for Unicode line separators, now this for double quotes), which suggests the escape function was simply incomplete rather than evidence of a deep architectural flaw. Downgrading to LOW is appropriate.
3 steps from start to impact.
Craft a malicious HTTP header
User-Agent, Referer, or another attacker-controlled header is set to a value containing a literal double-quote character ("). No authentication or special network position is required — any client that can reach the application can do this.- Target application uses morgan < 1.12.1
- Target application logs a quoted, attacker-controlled token (e.g.,
User-Agentin combined format)
- Application must actually be using morgan and writing logs that are parsed by a field-position-aware consumer
Double-quote closes the quoted field early
escapeLogField() passes the double-quote through unescaped. In the emitted log line, the injected " terminates the current quoted field prematurely. All subsequent fields shift by one position. A log parser (Splunk, ELK, custom regex) that splits on field position now reads attacker text in the wrong column.- Downstream log consumer parses by positional field splitting rather than by content-aware or schema-based parsing
- Many modern SIEM ingest pipelines use Grok patterns, JSON-structured logging, or key-value extraction — not naive positional splitting
- If the app uses morgan's
jsonor a structured-logging library (pino, winston) alongside or instead of morgan, this has zero effect
Log record shows forged field values
- Someone or something is consuming the positional log output and making decisions based on it
- Impact is limited to misleading log consumers — it does not affect application state, user data, or system integrity
- Even the misleading data is confined to a single log line; no record injection is possible
The supporting signals.
| In-the-wild exploitation | None observed. Not listed in CISA KEV. No reports of active campaigns. |
|---|---|
| Proof-of-concept | Trivially reproducible with curl -A '"injected' http://target/ — no weaponized PoC repo identified. |
| EPSS | 0.00309 (~bottom 30th percentile). Reflects the negligible real-world risk. |
| KEV status | Not listed. No indication of addition. |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N — Network-reachable, low complexity, but only Integrity-Low. No Confidentiality or Availability impact. |
| Affected versions | morgan < 1.12.1 (npm). Note: versions before 1.2.0 used a different code path; the escapeLogField function was introduced in the 1.10.x series as a fix for CVE-2026-5078. |
| Fixed version | morgan 1.12.1 (npm). Published 2026-09-11. |
| Related CVEs | CVE-2026-5078 (CR/LF in :remote-user, fixed 1.10.1 → 1.12.0), CVE-2026-15603 (Unicode line separators, fixed 1.12.0). This CVE is the third incomplete-fix iteration. |
| Exposure / install base | ~13.1 million weekly npm downloads; dependency of 9,600+ packages. However, morgan runs server-side in Node.js apps — it is not directly internet-exposed as infrastructure. |
| Disclosure date | 2026-09-11 |
noisgate verdict.
The single most decisive factor is blast radius limited to log-field accuracy — no code execution, no data access, no availability impact, and no newline injection means record boundaries stay intact. The vulnerability is constrained to misleading positional log parsers, which is an integrity nuisance, not a security-critical outcome.
Why this verdict
- Impact ceiling is log cosmetics, not security: The worst-case outcome is a shifted column in a parsed log line. No code execution, no privilege escalation, no confidentiality breach, no availability degradation. This is categorically less severe than I:L typically implies.
- No record injection: Unlike CVE-2026-5078 (CR/LF) or CVE-2026-15603 (Unicode line separators), this CVE cannot create *new* log records. The attacker can only confuse field boundaries within a single existing line. This dramatically limits the ability to hide malicious activity or trigger false-positive alerts.
- Friction from structured logging adoption: A large fraction of production Node.js deployments have moved to structured/JSON logging (pino, winston, Datadog/OpenTelemetry exporters). Morgan is often used only in development or alongside structured loggers. Positional Apache-format parsing at the SIEM layer is increasingly uncommon, further narrowing real-world impact.
- Role multiplier: Morgan is an *application-layer logging middleware*, not infrastructure software. Even if a Node.js app runs in a high-value role (e.g., an API gateway, a CI webhook handler, an IdP frontend), exploiting this CVE in that context still only affects log accuracy — it does not grant the attacker any access to the application's data, identity store, or control plane. The blast radius is log-consumer-local regardless of deployment role, so no high-value-role floor applies.
- EPSS confirms low real-world priority: At 0.00309, this sits in the bottom third of all scored CVEs, consistent with a nuisance-grade finding.
Why not higher?
To reach MEDIUM the vulnerability would need to enable at least one of: new-record injection (enabling log-based evasion), downstream code execution via log parsing, or a path to data access. None of these apply. The double-quote escape gap cannot create new log lines, cannot trigger downstream injection in any known SIEM, and grants no application-level access. The attack is also fully mitigated by the increasingly common practice of structured JSON logging.
Why not lower?
IGNORE would be appropriate if the vulnerability had no security relevance at all. While the impact is marginal, log integrity does matter for forensic investigation and compliance audit trails. A determined attacker *could* use field-shifting to obscure indicators during an incident, making post-breach analysis harder. That residual investigative-integrity risk keeps it above IGNORE.
What to do — in priority order.
- Switch to structured/JSON logging — If your Node.js apps use morgan's Apache-format output and feed it to a SIEM via positional parsing, switch to a JSON-structured logger (pino, winston, or morgan's custom format emitting JSON). This eliminates the entire class of field-delimiter injection. No mitigation SLA applies at LOW severity — treat as backlog hygiene.
- Sanitize inbound headers at the reverse proxy — Strip or encode double-quote characters in
User-Agent,Referer, and other logged headers at your edge proxy (nginxproxy_set_header, Envoy Lua filter, or AWS ALB request header rule). This neutralises the injection before it reaches morgan. - Upgrade morgan to 1.12.1 — The definitive fix. Run
npm audit fixornpm install morgan@1.12.1across affected repos. At LOW severity the noisgate remediation SLA is backlog-priority (no hard deadline), but since it is a one-line dependency bump with no breaking changes, there is little reason to delay.
- WAF rules blocking double-quotes in headers — most WAFs do not inspect or modify
User-Agent/Referercontent by default, and adding such a rule risks breaking legitimate traffic containing quotes. - Log-level reduction (e.g., disabling morgan) — removing logging entirely to avoid log injection is a cure worse than the disease; you lose operational visibility.
Crowdsourced verification payload.
Run on any host with node and npm installed. From the project root of a Node.js application that depends on morgan, execute: bash check_morgan_cve_2026_87859.sh. No special privileges required.
#!/usr/bin/env bash
# check_morgan_cve_2026_87859.sh
# Checks whether the installed morgan version is vulnerable to CVE-2026-87859
# (double-quote log field injection, fixed in 1.12.1)
# Exit codes: 0 = PATCHED, 1 = VULNERABLE, 2 = UNKNOWN
set -euo pipefail
REQUIRED="1.12.1"
# Try to get installed morgan version
if command -v npm &>/dev/null; then
INSTALLED=$(npm ls morgan --json 2>/dev/null | node -e "
const fs = require('fs');
const d = JSON.parse(fs.readFileSync('/dev/stdin','utf8'));
function find(obj) {
if (!obj || !obj.dependencies) return null;
if (obj.dependencies.morgan) return obj.dependencies.morgan.version;
for (const k of Object.keys(obj.dependencies)) {
const r = find(obj.dependencies[k]);
if (r) return r;
}
return null;
}
const v = find(d);
if (v) process.stdout.write(v);
else process.exit(1);
" 2>/dev/null) || true
fi
if [ -z "${INSTALLED:-}" ]; then
echo "UNKNOWN — morgan not found in this project's dependency tree."
exit 2
fi
# Compare versions using node semver logic
RESULT=$(node -e "
const inst = '${INSTALLED}'.split('.').map(Number);
const req = '${REQUIRED}'.split('.').map(Number);
for (let i = 0; i < 3; i++) {
if (inst[i] < req[i]) { console.log('VULNERABLE'); process.exit(0); }
if (inst[i] > req[i]) { console.log('PATCHED'); process.exit(0); }
}
console.log('PATCHED');
")
echo "${RESULT} — morgan ${INSTALLED} installed (fix is ${REQUIRED}+)"
if [ "$RESULT" = "VULNERABLE" ]; then exit 1; fi
exit 0If you remember one thing.
npm install morgan@1.12.1), so roll it into your next scheduled dependency update cycle. No noisgate mitigation SLA applies at this severity level. If your organization relies on positional Apache-format log parsing in a SIEM, consider migrating to structured JSON logging as a broader hardening measure — this eliminates the entire CWE-117 attack surface for morgan and similar middleware. Do not lose sleep over this one.Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.