Skip to content

[security disclosure] Unbounded Recursion in unpackValue() — Recoverable StackOverflow DoS #1015

Description

@waydeshi
Field Value
Project msgpack-java
Repository https://github.com/msgpack/msgpack-java
Affected Version 0.9.12 (and earlier)
Component msgpack-core
Class org.msgpack.core.MessageUnpacker
File msgpack-core/src/main/java/org/msgpack/core/MessageUnpacker.java
Vulnerable Line(s) 646–663
Severity Medium
CVSS 3.1 Score Base Score: 5.3 (MEDIUM) — CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L
CWE CWE-674 (Uncontrolled Recursion)

An unauthenticated remote attacker sends a small payload of deeply nested fixarray[1] structures to trigger a StackOverflowError in the deserializing thread. StackOverflowError extends Error, so catch (IOException) and catch (MessagePackException) do not intercept it and the request fails. Availability is Low: the error is recoverable, the worker thread stays alive, and a top-level catch (Throwable) survives it. No data is read or modified.


Impact

Denial of service via a recoverable per-request deserialization failure.

  • Escapes typed catch blocks: catch (IOException) / catch (MessagePackException) miss the StackOverflowError.
  • Recoverable: the worker thread survives, the stack unwinds cleanly, and frameworks with catch (Throwable) recover fully. Impact is a per-request failure, not thread-pool exhaustion.
  • Minimal payload: crash depth ≈1,500 with -Xss512k (1,501-byte payload) and ≈11,000 with the default stack (≈11 KB payload), both within typical HTTP body limits.

Remediation

Option 1 — Add maxNestingDepth to UnpackerConfig (recommended):

private int maxNestingDepth = 512; // UnpackerConfig field

public ImmutableValue unpackValue() throws IOException {
    return unpackValue(0);
}

private ImmutableValue unpackValue(int depth) throws IOException {
    if (depth > config.getMaxNestingDepth()) {
        throw new MessageSizeException("Nesting depth exceeds limit: " + depth, depth);
    }
    // ARRAY/MAP cases call unpackValue(depth + 1)
}

Option 2 — Convert to an iterative implementation using an explicit Deque stack, removing JVM-stack usage for nesting.


References

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions