GHSA-3J69-69WJ-XQX2

Vulnerability from github – Published: 2026-06-19 20:47 – Updated: 2026-06-19 20:47
VLAI
Summary
UltraJSON: Malformed/Truncated UTF-8 Accepted and Silently Rewritten in ujson.dumps()
Details

Summary

ujson.dumps() (or ujson.dump() or ujson.encode()) have a reject_bytes=False option. When set, they may accept malformed or truncated UTF-8 byte sequences, silently rewriting them into different Unicode characters instead of rejecting them. This leads to input validation bypass and data integrity issues.

Details

The expected behavior is that for x being any bytes string, x == ujson.loads(ujson.dumps(x, reject_bytes=False)).encode(errors="surrogatepass") should always either be true or ujson.dumps() will throw an exception. In reality, some strings which should've been errors are silently rewritten as other strings:

  • Invalid continuation bytes are replaced with valid ones: b'\xcf\x13' -> b'\xcf\x93'
  • Unterminated sequence completes the sequence: b'\xc3' -> b'\xc3\x80'
  • ... or leads to reading past the end of string: b'\xf0\x90\x94' -> b"\xf0\x90\x94\x80inxcontrib'"

Impact

An application relying on reject_bytes=False for UTF-8 handling may experience:

  • Data integrity issues
  • Experience validation bypass if said validation occurs before serialisation

Remediation

The missing/broken UTF-8 validation checks were added/fixed in https://github.com/ultrajson/ultrajson/commit/169eaf36b1116fece5034ee79a7a0ef3f6deedcf. We recommend upgrading to UltraJSON 5.13.0.

Workarounds

Decoding bytes to strings in Python before passing them to ujson.dumps() avoids this issue.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 5.12.1"
      },
      "package": {
        "ecosystem": "PyPI",
        "name": "ujson"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "5.13.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-54911"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-20"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-06-19T20:47:43Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "### Summary\n`ujson.dumps()` (or `ujson.dump()` or `ujson.encode()`) have a `reject_bytes=False` option. When set, they may accept malformed or truncated UTF-8 byte sequences, silently rewriting them into different Unicode characters instead of rejecting them. This leads to input validation bypass and data integrity issues.\n\n### Details\n\nThe expected behavior is that for `x` being any bytes string, `x == ujson.loads(ujson.dumps(x, reject_bytes=False)).encode(errors=\"surrogatepass\")` should always either be true or `ujson.dumps()` will throw an exception. In reality, some strings which should\u0027ve been errors are silently rewritten as other strings:\n\n* Invalid continuation bytes are replaced with valid ones: `b\u0027\\xcf\\x13\u0027` -\u003e `b\u0027\\xcf\\x93\u0027`\n* Unterminated sequence completes the sequence: `b\u0027\\xc3\u0027` -\u003e `b\u0027\\xc3\\x80\u0027`\n* ... or leads to reading past the end of string: `b\u0027\\xf0\\x90\\x94\u0027` -\u003e `b\"\\xf0\\x90\\x94\\x80inxcontrib\u0027\"`\n\n### Impact\n\nAn application relying on reject_bytes=False for UTF-8 handling may experience:\n\n- Data integrity issues\n- Experience validation bypass if said validation occurs before serialisation\n\n### Remediation\n\nThe missing/broken UTF-8 validation checks were added/fixed in https://github.com/ultrajson/ultrajson/commit/169eaf36b1116fece5034ee79a7a0ef3f6deedcf. We recommend upgrading to [UltraJSON 5.13.0](https://github.com/ultrajson/ultrajson/releases/tag/5.13.0).\n\n### Workarounds\n\nDecoding bytes to strings in Python before passing them to `ujson.dumps()` avoids this issue.",
  "id": "GHSA-3j69-69wj-xqx2",
  "modified": "2026-06-19T20:47:43Z",
  "published": "2026-06-19T20:47:43Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/ultrajson/ultrajson/security/advisories/GHSA-3j69-69wj-xqx2"
    },
    {
      "type": "WEB",
      "url": "https://github.com/ultrajson/ultrajson/commit/169eaf36b1116fece5034ee79a7a0ef3f6deedcf"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/ultrajson/ultrajson"
    },
    {
      "type": "WEB",
      "url": "https://github.com/ultrajson/ultrajson/releases/tag/5.13.0"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "UltraJSON: Malformed/Truncated UTF-8 Accepted and Silently Rewritten in ujson.dumps()"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…