Skip to content

Honor maxErrorTokenLength in UTF8DataInputJsonParser [CVE-2026-89425] - #1698

Merged
cowtowncoder merged 6 commits into
FasterXML:2.18from
pjfanning:2.21-1687-datainput-error-token-length
Sep 11, 2026
Merged

cowtowncoder merged 6 commits into
FasterXML:2.18from
pjfanning:2.21-1687-datainput-error-token-length

Conversation

@pjfanning

@pjfanning pjfanning commented Sep 10, 2026 •

Copy link
Copy Markdown
Member

UTF8DataInputJsonParser._reportInvalidToken() is the only one of the four JSON parser
implementations that does not bound the token it accumulates for the Unrecognized token
message. The other three all cap it at maxErrorTokenLength and append ...:

  • UTF8StreamJsonParser (~L3766)
  • ReaderBasedJsonParser (~L3140)
  • NonBlockingUtf8JsonParserBase (~L1250)

So a long run of Java-identifier characters after a token that fails to match
true/false/null is copied into the exception message in full. Feeding the same
malformed document through both backends on 2.21:

source message length
createParser(InputStream) 367
createParser(DataInput) 20,000,109

maxDocumentLength is not available as a backstop here either, since it is rejected outright
for DataInput sources ([#1570], JsonFactory L456), and the accumulation does not go through
ReadConstrainedTextBuffer, so maxStringLength does not apply.

Fix

Mirror the existing bound from UTF8StreamJsonParser into the DataInput variant. Four lines,
no behaviour change for tokens under the limit.

Why it went unnoticed

ErrorReportConfigurationTest only ever built parsers via factory.createParser(String), so it
exercised ReaderBasedJsonParser alone and never reached the DataInput path. This PR adds
errorTokenLengthBoundedInAllModes(), which loops ALL_MODES and asserts the reported token is
truncated to maxErrorTokenLength plus the ... marker. Without the main-code change it fails
on MODE_DATA_INPUT only (Expected size: 259 but was: 12801) and passes the other four.

There is prior form for this specific parser missing a constraint the others honour — see
[#1553], max depth validation not working for DataInput-backed parsers.

I left the shared-helper refactor alone: the four implementations read their input too
differently for the scan loop to hoist cleanly into ParserMinimalBase.

Full suite green on this branch: 1552 tests, 0 failures.

🤖 Generated with Claude Code

@pjfanning pjfanning changed the title Honor maxErrorTokenLength in UTF8DataInputJsonParser (#1687) Honor maxErrorTokenLength in UTF8DataInputJsonParser Sep 10, 2026
pjfanning added a commit to pjfanning/jackson-core that referenced this pull request Sep 10, 2026
The DataInput-backed parser was the only one of the four JSON parser
implementations that did not bound the token it accumulates for the
"Unrecognized token" message, so a long run of identifier characters was
copied into the message in full.

Mirror the existing check from UTF8StreamJsonParser/ReaderBasedJsonParser
and extend the ErrorReportConfigurationTest coverage over ALL_MODES; the
existing test only exercised the Reader-backed parser, which is why the
drift went unnoticed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@pjfanning
pjfanning force-pushed the 2.21-1687-datainput-error-token-length branch from 9302442 to c944376 Compare September 10, 2026 08:29
The DataInput-backed parser was the only one of the four JSON parser
implementations that did not bound the token it accumulates for the
"Unrecognized token" message, so a long run of identifier characters was
copied into the message in full.

Mirror the existing check from UTF8StreamJsonParser/ReaderBasedJsonParser
and extend the ErrorReportConfigurationTest coverage over ALL_MODES; the
existing test only exercised the Reader-backed parser, which is why the
drift went unnoticed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@pjfanning
pjfanning force-pushed the 2.21-1687-datainput-error-token-length branch from c944376 to 86cac1e Compare September 10, 2026 19:11
@pjfanning
pjfanning changed the base branch from 2.21 to 2.18 September 10, 2026 19:11
@cowtowncoder cowtowncoder changed the title Honor maxErrorTokenLength in UTF8DataInputJsonParser Honor maxErrorTokenLength in UTF8DataInputJsonParser [GHSA-7hhh-6rmp-j9qf] Sep 11, 2026
@cowtowncoder cowtowncoder added this to the 2.8.11 milestone Sep 11, 2026
@cowtowncoder
cowtowncoder merged commit 211cf2c into FasterXML:2.18 Sep 11, 2026
9 checks passed
@cowtowncoder cowtowncoder changed the title Honor maxErrorTokenLength in UTF8DataInputJsonParser [GHSA-7hhh-6rmp-j9qf] Honor maxErrorTokenLength in UTF8DataInputJsonParser [GHSA-7hhh-6rmp-j9qf] Sep 11, 2026
cowtowncoder added a commit that referenced this pull request Sep 11, 2026
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qqdq57uPQx3jxcg3WsoUiq
cowtowncoder added a commit that referenced this pull request Sep 11, 2026
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qqdq57uPQx3jxcg3WsoUiq
@cowtowncoder cowtowncoder added the security Issue possibly related to security aspects label Sep 11, 2026
cowtowncoder added a commit that referenced this pull request Sep 11, 2026
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qqdq57uPQx3jxcg3WsoUiq
cowtowncoder added a commit that referenced this pull request Sep 11, 2026
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qqdq57uPQx3jxcg3WsoUiq
@cowtowncoder cowtowncoder changed the title Honor maxErrorTokenLength in UTF8DataInputJsonParser [GHSA-7hhh-6rmp-j9qf] Honor maxErrorTokenLength in UTF8DataInputJsonParser [CVE-2026-89425] Sep 12, 2026
@cowtowncoder cowtowncoder added the cve Issues related to public CVEs (security vuln reports) label Sep 12, 2026
cowtowncoder added a commit that referenced this pull request Sep 12, 2026
cowtowncoder added a commit to pjfanning/jackson-core that referenced this pull request Sep 12, 2026
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Suc7MhDUb8AtZVA66XM8CY
cowtowncoder added a commit to pjfanning/jackson-core that referenced this pull request Sep 12, 2026
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Suc7MhDUb8AtZVA66XM8CY
cowtowncoder added a commit to pjfanning/jackson-core that referenced this pull request Sep 12, 2026
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Suc7MhDUb8AtZVA66XM8CY
cowtowncoder added a commit to pjfanning/jackson-core that referenced this pull request Sep 12, 2026
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Suc7MhDUb8AtZVA66XM8CY
dongjoon-hyun added a commit to apache/spark-kubernetes-operator that referenced this pull request Sep 28, 2026
### What changes were proposed in this pull request?

This PR aims to upgrade `Jackson` to 2.22.3.

`jackson-annotations` stays at 2.22 because it has no 2.22.3 release (2.22 is the version paired with 2.22.3 by `jackson-bom`).

`jackson-module-scala_2.13` is upgraded to 2.22.3, the version paired by `jackson-bom` 2.22.3, instead of 2.22.3.1. The only change of 2.22.3.1 ([#899](FasterXML/jackson-module-scala#899)) fixes a 2.22.3 regression in the deserialization of a Scala `object` with a `JsonTypeInfo.As.PROPERTY` type id, which is irrelevant to this project.

`gradle/verification-metadata.xml` was regenerated from scratch.

### Why are the changes needed?

To bring the latest bug fixes and security fixes.

- [Jackson 2.22.3](https://github.com/FasterXML/jackson/wiki/Jackson-Release-2.22.3) (2026-09-21, [jackson-databind-2.22.3](https://github.com/FasterXML/jackson-databind/releases/tag/jackson-databind-2.22.3))
  - [CVE-2026-89407](FasterXML/jackson-core#1649): Optimize `NumberInput.looksLikeValidNumber`
  - [CVE-2026-89425](FasterXML/jackson-core#1698): Honor `maxErrorTokenLength` in `UTF8DataInputJsonParser`
  - [CVE-2026-91776](FasterXML/jackson-databind#6203): Prevent unbounded growth of type id cache in `TypeDeserializer`
  - [CVE-2026-91777](FasterXML/jackson-databind#6204): Avoid quadratic forward-reference resolution in Collection/Map deserializers
  - `WriterBasedJsonGenerator` throws `ArrayIndexOutOfBoundsException` when a zero-length custom escape ends exactly at the output buffer boundary ([#1668](FasterXML/jackson-core#1668))
  - `UTF32Reader` corrupts or drops the low surrogate when a supplementary character splits across a `read()` boundary ([#1713](FasterXML/jackson-core#1713))
  - Unresolved IPv6 `InetSocketAddress` serialized without brackets, losing port on round-trip ([#6185](FasterXML/jackson-databind#6185))
  - Avoid quadratic forward-reference resolution in `ObjectArrayDeserializer` ([#6205](FasterXML/jackson-databind#6205))
  - Support `StreamReadConstraints.maxDocumentLength()` in YAML parser ([#737](FasterXML/jackson-dataformats-text#737))

### Does this PR introduce _any_ user-facing change?

No.

### How was this patch tested?

Pass the CIs.

### Was this patch authored or co-authored using generative AI tooling?

Generated-by: Claude Opus 5.5

Closes #900 from dongjoon-hyun/SPARK-59833.

Authored-by: Dongjoon Hyun <dongjoon@apache.org>
Signed-off-by: Dongjoon Hyun <dongjoon@apache.org>
pstreef added a commit to moderne-backpatch-alliance/backpatch-jackson-core that referenced this pull request Oct 15, 2026
…AX_ERROR_TOKEN_LENGTH

Port of upstream 211cf2c ("Honor maxErrorTokenLength in
UTF8DataInputJsonParser [GHSA-7hhh-6rmp-j9qf]", FasterXML#1698), shipped in 2.18.11,
onto the 2.13.5 baseline.

UTF8DataInputJsonParser._reportInvalidToken() kept appending to the error
message for as long as the input looked like an identifier. Every other
parser stops at MAX_ERROR_TOKEN_LENGTH (256) and appends "..."; this one did
not, so a long unquoted token became an exception message of the same size,
and the parser read the whole of it to build that message. 1,000,000 chars
of input gave a 1,000,109-char message. The fix is upstream's four lines:
stop at the cap and append "...", exactly as UTF8StreamJsonParser does at
2.13.5. 2.13 has no ErrorReportConfiguration, so the cap is the existing
ParserMinimalBase.MAX_ERROR_TOKEN_LENGTH constant rather than
getMaxErrorTokenLength().

NOT PORTED: the rest of FasterXML#1698. Its multi-byte UTF-8 hunks in
_handleUnexpectedValue and _checkMatchEnd, and its UTF8StreamJsonParser
changes, decode a non-ASCII character before reporting it, which fixes the
text of the error message, not its length. The ReaderBasedJsonParser and
async parser hunks only hoist the configured length into a local. The
DataInput parser still repeats a token's first character in its message at
this baseline; that is cosmetic and outside this advisory.

Binary compatibility: no signature change. javap -protected of
UTF8DataInputJsonParser is identical to 2.13.5.1-backpatch-00007.

BEHAVIOUR CHANGE: a DataInput parser's "Unrecognized token" message is now
truncated at 256 characters plus "...", and the parser stops reading the
token at the cap instead of consuming the rest of it. The exception is
thrown either way.

Regression gate: ParserErrorHandlingTest.testErrorTokenLengthBounded, over
every parser mode. A 10,000-character unrecognized token must give a
message under 600 characters that contains "...". Upstream asserts its
exact text, which differs here because of the repeated first character.

Upstream-Commit: 211cf2c
pstreef added a commit to finos-osera-forks/patch-jackson-core that referenced this pull request Oct 15, 2026
…AX_ERROR_TOKEN_LENGTH

Port of upstream 211cf2c ("Honor maxErrorTokenLength in
UTF8DataInputJsonParser [GHSA-7hhh-6rmp-j9qf]", FasterXML#1698), shipped in 2.18.11,
onto the 2.13.5 baseline.

UTF8DataInputJsonParser._reportInvalidToken() kept appending to the error
message for as long as the input looked like an identifier. Every other
parser stops at MAX_ERROR_TOKEN_LENGTH (256) and appends "..."; this one did
not, so a long unquoted token became an exception message of the same size,
and the parser read the whole of it to build that message. 1,000,000 chars
of input gave a 1,000,109-char message. The fix is upstream's four lines:
stop at the cap and append "...", exactly as UTF8StreamJsonParser does at
2.13.5. 2.13 has no ErrorReportConfiguration, so the cap is the existing
ParserMinimalBase.MAX_ERROR_TOKEN_LENGTH constant rather than
getMaxErrorTokenLength().

NOT PORTED: the rest of FasterXML#1698. Its multi-byte UTF-8 hunks in
_handleUnexpectedValue and _checkMatchEnd, and its UTF8StreamJsonParser
changes, decode a non-ASCII character before reporting it, which fixes the
text of the error message, not its length. The ReaderBasedJsonParser and
async parser hunks only hoist the configured length into a local. The
DataInput parser still repeats a token's first character in its message at
this baseline; that is cosmetic and outside this advisory.

Binary compatibility: no signature change. javap -protected of
UTF8DataInputJsonParser is identical to 2.13.5.1-backpatch-00007.

BEHAVIOUR CHANGE: a DataInput parser's "Unrecognized token" message is now
truncated at 256 characters plus "...", and the parser stops reading the
token at the cap instead of consuming the rest of it. The exception is
thrown either way.

Regression gate: ParserErrorHandlingTest.testErrorTokenLengthBounded, over
every parser mode. A 10,000-character unrecognized token must give a
message under 600 characters that contains "...". Upstream asserts its
exact text, which differs here because of the repeated first character.

Upstream-Commit: 211cf2c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cve Issues related to public CVEs (security vuln reports) security Issue possibly related to security aspects

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants