CVE-2026-49844: Verified Reproduction
CVE-2026-49844: Log4j MapMessage emits invalid JSON for non-finite values
CVE-2026-49844 is verified against org.apache.logging.log4j:log4j-api · maven. Affected versions: >=2.13.1,<2.25.5; >=2.26.0,<2.26.1; >=3.0.0-alpha1,<=3.0.0-beta2. Fixed in 2.25.5; 2.26.1. This medium reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00286.
What Is CVE-2026-49844?
CVE-2026-49844 is a medium-severity improper-encoding flaw (CWE-116, CVSS 6.3) in Apache Log4j API. When a MapMessage containing non-finite floating-point values is serialized to JSON, Log4j emits invalid JSON that downstream parsers reject. Pruva reproduced it (reproduction REPRO-2026-00286).
CVE-2026-49844 Severity & CVSS Score
CVE-2026-49844 is rated medium severity, with a CVSS base score of 6.3 out of 10.
Medium — meaningful risk under specific conditions. Schedule a fix in the normal cycle.
Affected org.apache.logging.log4j:log4j-api Versions
org.apache.logging.log4j:log4j-api · maven versions >=2.13.1,<2.25.5; >=2.26.0,<2.26.1; >=3.0.0-alpha1,<=3.0.0-beta2 are affected.
How to Reproduce CVE-2026-49844
pruva-verify REPRO-2026-00286 curl -O https://www.pruva.dev/api/v1/reproductions/REPRO-2026-00286/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh Proof of Reproduction for CVE-2026-49844
- reached the target end-to-end
- on the real production code path
- high confidence
- the upstream fix blocks the same trigger
non-finite floating-point values (NaN, Infinity, -Infinity) placed in a logged MapMessage, serialized via getFormattedMessage(["JSON"]) or asJson()
- MapMessage.getFormattedMessage(["JSON"])
- MapMessage.format(JSON)
- MapMessage.asJson(sb)
- MapMessageJsonFormatter.format(sb, data)
- formatNumber/formatDoubleArray/formatFloatArray
- sb.append(doubleNumber/floatNumber) emits bare NaN/Infinity tokens
reproduction_steps.sh How the agent worked
Root Cause and Exploit Chain for CVE-2026-49844
CVE-2026-49844 is an improper encoding/serialization flaw in Apache Log4j API's MapMessage JSON output. When a MapMessage containing non-finite floating-point values (NaN, Infinity, -Infinity) is serialized to JSON via MapMessage.asJson() or MapMessage.getFormattedMessage(new String[]{"JSON"}), the MapMessageJsonFormatter emits the bare tokens NaN, Infinity, and -Infinity instead of an RFC 8259-compliant representation. These bare tokens are not valid JSON values, so any conformant downstream JSON parser or log-ingestion system will reject or fail to process the affected log records. This is a bypass of the earlier CVE-2026-34481 fix (which addressed JsonTemplateLayout but did not cover the MapMessage.asJson() code path in log4j-api).
- Package/component affected:
org.apache.logging.log4j:log4j-api— classorg.apache.logging.log4j.message.MapMessageJsonFormatter, reached viaMapMessage.asJson(StringBuilder)andMapMessage.getFormattedMessage(String[])with the"JSON"format. - Affected versions:
log4j-api2.13.1 through 2.25.4, and 2.26.0. (Also3.0.0-alpha1+ per the Snyk advisory.) - Fixed versions: 2.25.5 and 2.26.1.
- Risk level: Medium (CWE-116: Improper Encoding or Escaping of Output).
- Consequences: Malformed JSON in log output. Downstream JSON parsers and log-ingestion/indexing pipelines that enforce RFC 8259 will reject or fail on affected records. An attacker who can influence a floating-point value logged in a
MapMessage(e.g., viaJsonTemplateLayout's message resolver or any layout relying onMapMessage.asJson()) can inject non-finite values to corrupt log records or disrupt log processing. This is not a remote code execution issue.
Impact Parity
- Disclosed/claimed maximum impact: Improper encoding of non-finite floating-point values during
MapMessageJSON serialization producing output that is not valid JSON (serialization/encoding flaw,other). Explicitly stated as not an RCE issue. - Reproduced impact from this run: All 13 test cases (NaN, +Infinity, -Infinity as scalar
Double,double[], scalarFloat,float[], plus a combinedasJson()direct call) produce bareNaN/Infinity/-Infinitytokens in the vulnerable version. A strict RFC 8259 JSON parser (GsonJsonReaderwithlenient=false) rejects all 13 outputs. The fixed version quotes all values as JSON strings ("NaN","Infinity","-Infinity") and all 13 parse successfully. - Parity:
full— the reproduced behavior exactly matches the disclosed impact (invalid JSON from non-finite values; fix quotes them). - Not demonstrated: N/A — no code execution was claimed or expected.
Root Cause
In the vulnerable MapMessageJsonFormatter.java (log4j-api ≤ 2.25.4 / 2.26.0), the formatNumber() method handles Double and Float values by directly appending the primitive to the StringBuilder:
// VULNERABLE (rel/2.25.4)
} else if (number instanceof Double) {
final double doubleNumber = (Double) number;
sb.append(doubleNumber); // <-- produces "NaN", "Infinity", "-Infinity"
} else if (number instanceof Float) {
final float floatNumber = (float) number;
sb.append(floatNumber); // <-- produces "NaN", "Infinity", "-Infinity"
}
Java's StringBuilder.append(double) delegates to Double.toString(double), which returns the strings "NaN", "Infinity", and "-Infinity" for non-finite values. These are bare literals in the JSON output — they are not enclosed in quotes and are not valid JSON number syntax per RFC 8259 §6 (which only permits finite numbers). The same issue exists in formatDoubleArray() and formatFloatArray(), which also call sb.append(item) directly for array elements.
The call chain is:
MapMessage.getFormattedMessage(new String[]{"JSON"})
→ MapMessage.format(MapFormat.JSON, sb)
→ MapMessage.asJson(sb) [protected]
→ MapMessageJsonFormatter.format(sb, data)
→ formatNumber(sb, number) / formatDoubleArray(...) / formatFloatArray(...)
Fix (PR #4163, merged as commit 19edb23/squash c7103d5 on 2.x; feadf8eb on 2.25.x; 1352b987 on 2.26.x):
The fix adds two private helper methods that check Double.isFinite() / Float.isFinite() and, for non-finite values, call formatString() to wrap the value in JSON string quotes:
// FIXED (rel/2.25.5)
private static void formatDouble(StringBuilder sb, double doubleNumber) {
if (!Double.isFinite(doubleNumber)) {
formatString(sb, Double.toString(doubleNumber)); // quotes: "NaN", "Infinity", etc.
} else {
sb.append(doubleNumber);
}
}
All sb.append(doubleNumber) / sb.append(floatNumber) / sb.append(item) call sites in formatNumber(), formatDoubleArray(), and formatFloatArray() are replaced with calls to formatDouble() / formatFloat().
Reproduction Steps
- Script:
bundle/repro/reproduction_steps.sh(self-contained, idempotent). - What the script does:
- Installs OpenJDK 17 if not present.
- Downloads the official Apache-published
log4j-apiartifacts from Maven Central:log4j-api-2.25.4.jar(vulnerable, built from tagrel/2.25.4) andlog4j-api-2.25.5.jar(fixed, built from tagrel/2.25.5). Also downloadsgson-2.11.0.jarfor strict JSON validation. - Verifies via
javapthat the vulnerable jar lacksformatDouble()/formatFloat()helper methods and the fixed jar has them. - Compiles
bundle/repro/NonFiniteJsonTest.java— a Java harness that creates a concreteMapMessagesubclass and exercises bothgetFormattedMessage(new String[]{"JSON"})(public API) andasJson(StringBuilder)(protected, via subclass) withNaN,+Infinity,-Infinityas scalardouble/floatand asdouble[]/float[]array elements (13 total cases). - Runs the harness against each jar. The harness detects bare (unquoted) non-finite tokens via a character-level scanner and validates each output with a strict RFC 8259 JSON parser (Gson
JsonReaderwithsetLenient(false)+skipValue()). - Emits a machine-readable
VERDICT|...line and writesbundle/repro/runtime_manifest.json.
- Expected evidence of reproduction:
- Vulnerable 2.25.4:
bare=13 quoted=0 parseFail=13— all outputs contain bareNaN/Infinity/-Infinityand fail strict JSON parsing. - Fixed 2.25.5:
bare=0 quoted=13 parseFail=0— all outputs quote the values as JSON strings and parse successfully.
- Vulnerable 2.25.4:
Evidence
- Log files:
bundle/logs/vulnerable_output.log— full harness output for vulnerable log4j-api 2.25.4bundle/logs/fixed_output.log— full harness output for fixed log4j-api 2.25.5bundle/logs/compile.log— javac compilation output
- Key excerpts (vulnerable 2.25.4):
JSON output: {"number":NaN} >> BARE non-finite token detected (invalid JSON per RFC 8259) >> strict JSON parse FAILED (invalid per RFC 8259) JSON output: {"numbers":[-Infinity]} >> BARE non-finite token detected (invalid JSON per RFC 8259) >> strict JSON parse FAILED (invalid per RFC 8259) SUMMARY: bare=13, quoted=0, parseFail=13 VERDICT|2.25.4-vulnerable|VULNERABLE|bare=13|quoted=0|parseFail=13 - Key excerpts (fixed 2.25.5):
JSON output: {"number":"NaN"} >> non-finite value is QUOTED (valid JSON string) >> strict JSON parse OK (valid RFC 8259 JSON) JSON output: {"numbers":["-Infinity"]} >> non-finite value is QUOTED (valid JSON string) >> strict JSON parse OK (valid RFC 8259 JSON) SUMMARY: bare=0, quoted=13, parseFail=0 VERDICT|2.25.5-fixed|FIXED|bare=0|quoted=13|parseFail=0 - javap verification:
- Vulnerable 2.25.4
MapMessageJsonFormattermethods: noformatDouble(, noformatFloat(. - Fixed 2.25.5
MapMessageJsonFormattermethods: hasformatDouble(StringBuilder, double)andformatFloat(StringBuilder, float).
- Vulnerable 2.25.4
- Environment: OpenJDK 17.0.19, Gson 2.11.0 (strict JSON validator), official Apache log4j-api jars from Maven Central (verified identical to source-built jar from
rel/2.25.4tag — same file size 351127 bytes). - Runtime manifest:
bundle/repro/runtime_manifest.json
Recommendations / Next Steps
- Upgrade guidance: Upgrade
log4j-apito version 2.25.5+ (2.25.x line) or 2.26.1+ (2.26.x line). If on 3.0.0-alpha, monitor for a fix. - Suggested fix approach: Already implemented in PR #4163 — gate non-finite
Double/Floatvalues throughformatString()so they are emitted as JSON strings. This mirrors Jackson'sJsonWriteFeature#WRITE_NAN_AS_STRINGSbehavior. - Testing recommendations: The fix includes regression tests (
MapMessageTest.testJsonFormatterDoubleNonFiniteSupportandtestJsonFormatterFloatNonFiniteSupport) that parameterize overNaN,+Infinity,-Infinityfor bothdoubleandfloat. Any future changes toMapMessageJsonFormattershould ensure these tests continue to pass. Consider adding strict-JSON-parser validation to CI for allMapMessageJSON output. - Downstream mitigation: Log-ingestion systems that use lenient JSON parsers (e.g., Gson default mode, some JavaScript engines) may silently accept bare
NaN/Infinity, but strict parsers (RFC 8259) will reject them. Validate log JSON output with a strict parser.
Additional Notes
- Idempotency confirmation: The script was run twice consecutively; both runs produced identical results (exit code 0,
bare=13for vulnerable,bare=0for fixed). The script skips re-downloading jars if they already exist. - Source build verification: In addition to the Maven Central artifacts, the
log4j-apimodule was built from source at tagrel/2.25.4using Maven (mvn -pl log4j-api-java9,log4j-api -am install -DskipTests). The source-built jar (log4j-api-2.25.4.jar, 351127 bytes) is byte-size-identical to the Maven Central artifact, confirming the published jar matches the repository source. - Edge cases covered: The harness tests both scalar and array forms for both
DoubleandFloat, covering all code paths informatNumber(),formatDoubleArray(), andformatFloatArray(). TheBigDecimalpath is unaffected (it already usestoString()which never produces non-finite tokens). - Scope: This is a
library_apiclaim (claimed_surface=library_api,required_entrypoint_kind=function_call). The reproduction exercises the realMapMessage.getFormattedMessage(["JSON"])andMapMessage.asJson()functions from the official Apachelog4j-apiartifacts. No service/network boundary is involved.
CVE-2026-49844 Reproduction Transcript
The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.
Full session Replay every step — scrub the timeline or play it back.
Artifacts and Evidence for CVE-2026-49844
Scripts, logs, diffs, and output captured during the reproduction.
How to Fix CVE-2026-49844
Upgrade org.apache.logging.log4j:log4j-api · maven to 2.25.5; 2.26.1 or later.
FAQ: CVE-2026-49844
Is CVE-2026-49844 a bypass of an earlier fix?
Which Log4j versions are affected by CVE-2026-49844, and where is it fixed?
How severe is CVE-2026-49844?
How can I reproduce CVE-2026-49844?
References for CVE-2026-49844
Authoritative sources for CVE-2026-49844 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.