VYPR
Critical severity9.8NVD Advisory· Published May 11, 2026· Updated May 16, 2026

CVE-2026-7210

CVE-2026-7210

Description

xml.parsers.expat and xml.etree.ElementTree use insufficient entropy for Expat hash-flooding protection, which allows a crafted XML document to trigger hash flooding.\r\n\r\nFully mitigating this vulnerability requires both updating libexpat to 2.8.0 or later and applying this patch.

Affected products

1

Patches

1
24b8f1254446

gh-149018: Use `XML_SetHashSalt16Bytes` in `pyexpat`/`_elementtree` when possible (#149023)

https://github.com/python/cpythonStan UlbrychMay 10, 2026via nvd-ref
5 files changed · +26 6
  • Include/internal/pycore_pyhash.h+5 3 modified
    @@ -27,14 +27,14 @@ _Py_HashPointerRaw(const void *ptr)
      *   pppppppp ssssssss ........  fnv -- two Py_hash_t
      *   k0k0k0k0 k1k1k1k1 ........  siphash -- two uint64_t
      *   ........ ........ ssssssss  djbx33a -- 16 bytes padding + one Py_hash_t
    - *   ........ ........ eeeeeeee  pyexpat XML hash salt
    + *   eeeeeeee eeeeeeee eeeeeeee  pyexpat XML hash salt
      *
      * memory layout on 32 bit systems
      *   cccccccc cccccccc cccccccc  uc
      *   ppppssss ........ ........  fnv -- two Py_hash_t
      *   k0k0k0k0 k1k1k1k1 ........  siphash -- two uint64_t (*)
      *   ........ ........ ssss....  djbx33a -- 16 bytes padding + one Py_hash_t
    - *   ........ ........ eeee....  pyexpat XML hash salt
    + *   eeeeeeee eeeeeeee eeee....  pyexpat XML hash salt
      *
      * (*) The siphash member may not be available on 32 bit platforms without
      *     an unsigned int64 data type.
    @@ -58,7 +58,9 @@ typedef union {
             Py_hash_t suffix;
         } djbx33a;
         struct {
    -        unsigned char padding[16];
    +        /* 16 bytes for XML_SetHashSalt16Bytes */
    +        uint8_t hashsalt16[16];
    +        /* 4/8 bytes for legacy XML_SetHashSalt */
             Py_hash_t hashsalt;
         } expat;
     } _Py_HashSecret_t;
    
  • Include/pyexpat.h+3 0 modified
    @@ -62,6 +62,9 @@ struct PyExpat_CAPI
             XML_Parser parser, unsigned long long activationThresholdBytes);
         XML_Bool (*SetBillionLaughsAttackProtectionMaximumAmplification)(
             XML_Parser parser, float maxAmplificationFactor);
    +    /* might be NULL for expat < 2.8.0 */
    +    XML_Bool (*SetHashSalt16Bytes)(
    +        XML_Parser parser, const uint8_t entropy[16]);
         /* always add new stuff to the end! */
     };
     
    
  • Misc/NEWS.d/next/Security/2026-04-26-19-30-45.gh-issue-149018.a9SqWb.rst+3 0 added
    @@ -0,0 +1,3 @@
    +Improved protection against XML hash-flooding attacks in
    +:mod:`xml.parsers.expat` and :mod:`xml.etree.ElementTree` when Python is
    +compiled with libExpat 2.8.0 or later.
    
  • Modules/_elementtree.c+6 2 modified
    @@ -3735,8 +3735,12 @@ _elementtree_XMLParser___init___impl(XMLParserObject *self, PyObject *target,
             PyErr_NoMemory();
             return -1;
         }
    -    /* expat < 2.1.0 has no XML_SetHashSalt() */
    -    if (EXPAT(st, SetHashSalt) != NULL) {
    +    // Prefer 16-byte entropy, only expat >= 2.8.0. See gh-149018
    +    if (EXPAT(st, SetHashSalt16Bytes) != NULL) {
    +        EXPAT(st, SetHashSalt16Bytes)(self->parser,
    +                                      _Py_HashSecret.expat.hashsalt16);
    +    }
    +    else if (EXPAT(st, SetHashSalt) != NULL) {
             EXPAT(st, SetHashSalt)(self->parser,
                                (unsigned long)_Py_HashSecret.expat.hashsalt);
         }
    
  • Modules/pyexpat.c+9 1 modified
    @@ -1533,7 +1533,10 @@ newxmlparseobject(pyexpat_state *state, const char *encoding,
             Py_DECREF(self);
             return NULL;
         }
    -#if XML_COMBINED_VERSION >= 20100
    +#if XML_COMBINED_VERSION >= 20800
    +    /* This feature was added upstream in libexpat 2.8.0. */
    +    XML_SetHashSalt16Bytes(self->itself, _Py_HashSecret.expat.hashsalt16);
    +#elif XML_COMBINED_VERSION >= 20100
         /* This feature was added upstream in libexpat 2.1.0. */
         XML_SetHashSalt(self->itself,
                         (unsigned long)_Py_HashSecret.expat.hashsalt);
    @@ -2427,6 +2430,11 @@ pyexpat_exec(PyObject *mod)
     #else
         capi->SetHashSalt = NULL;
     #endif
    +#if XML_COMBINED_VERSION >= 20800
    +    capi->SetHashSalt16Bytes = XML_SetHashSalt16Bytes;
    +#else
    +    capi->SetHashSalt16Bytes = NULL;
    +#endif
     #if XML_COMBINED_VERSION >= 20600
         capi->SetReparseDeferralEnabled = XML_SetReparseDeferralEnabled;
     #else
    

Vulnerability mechanics

AI mechanics synthesis has not run for this CVE yet.

References

5

News mentions

1