{
  "parent_cve": "CVE-2026-49844",
  "parent_root_cause": "MapMessageJsonFormatter appends primitive double/float values directly to the JSON StringBuilder via sb.append(<double>/<float>); StringBuilder.append(double) delegates to Double.toString(double), which emits the bare literals \"NaN\", \"Infinity\", \"-Infinity\" for non-finite values — invalid JSON tokens per RFC 8259 section 6.",
  "parent_sink": "log4j-api/src/main/java/org/apache/logging/log4j/message/MapMessageJsonFormatter.java :: formatNumber (Double/Float instanceof branches and else-branch), formatDoubleArray, formatFloatArray",
  "variant_root_cause": "Identical root cause. The alternate data paths (nested Map, List, Object[], non-List Collection, custom Number, BigInteger overflow) are different dispatcher branches in MapMessageJsonFormatter.format() that all recurse/converge on the SAME sink (formatNumber / formatDoubleArray / formatFloatArray). On vulnerable versions they hit the same raw sb.append(<double>/<float>) call sites and emit the same bare non-finite tokens.",
  "variant_sink": "Same as parent: MapMessageJsonFormatter.formatNumber / formatDoubleArray / formatFloatArray (reached via formatMap/formatList/formatCollection/formatObjectArray/formatNumber-else-branch).",
  "same_root_cause_confidence": "high",
  "same_sink_confidence": "high",
  "same_surface_confidence": "high",
  "equivalence_reasoning": "The variant does not introduce a new sink or a new encoding flaw. It only varies the VALUE TYPE placed in the MapMessage (container vs scalar, custom Number vs boxed Double), which selects a different branch of the format() dispatcher. All those branches ultimately call format(sb, value, depth) -> formatNumber / formatDoubleArray / formatFloatArray, which is exactly the parent sink. The bare-token emission mechanism (StringBuilder.append(double) -> Double.toString) is identical. Therefore the variant is the same underlying bug reachable from additional data-path entry points, not a distinct bug.",
  "fix_completeness_for_variant": "complete",
  "fix_completeness_reasoning": "PR #4163 gates the SINK (formatNumber incl. its else-branch, formatDoubleArray, formatFloatArray) via formatDouble/formatFloat isFinite checks, not individual entry paths. Because every Number-bearing dispatcher branch recurses to that sink, the fix transitively covers all alternate data paths. Verified empirically: fixed 2.25.5 and 2.26.1 emit 0 bare tokens across all 18 alternate-path cases. No bypass.",
  "is_bypass": false,
  "is_alternate_trigger_on_vulnerable": true
}
