diff --git a/meta/recipes-core/expat/expat/CVE-2026-41080-1.patch b/meta/recipes-core/expat/expat/CVE-2026-41080-1.patch
new file mode 100644
index 0000000000..d2a957a5e8
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2026-41080-1.patch
@@ -0,0 +1,251 @@
+From 944f825b0119257fee3aed0841e44a6d1c674f80 Mon Sep 17 00:00:00 2001
+From: Amaury Couderc <amaury.couderc@est.tech>
+Date: Thu, 2 Jul 2026 09:10:07 +0000
+Subject: [PATCH 1/3] expat: fix CVE-2026-41080 use 16 bytes of entropy for hash salt
+
+The existing hash flooding protection in libexpat (based on SipHash)
+only used 4 to 8 bytes of entropy for a salt, when 16 bytes are
+supported by the SipHash implementation. This allows attackers to more
+feasibly guess the hash salt and craft inputs that cause hash
+collisions, leading to denial of service.
+
+Backport upstream changes that:
+- Drop unused parameter from generate_hash_secret_salt
+- Migrate hash salt storage to larger struct sipkey (128-bit)
+- Drop unneeded void * casts in generate_hash_secret_salt
+- Extract 16 bytes of entropy for hash flooding protection
+- Introduce internal flag m_hash_secret_salt_set
+- Update get_hash_secret_salt to return from the new 128-bit struct
+
+Squashed backport of upstream commits 909201a8, bc193afc, 08697a9b,
+f5eacefb, and fa1ebd60.
+
+Based on upstream PR: https://github.com/libexpat/libexpat/pull/1183
+
+CVE: CVE-2026-41080
+Upstream-Status: Backport [https://github.com/libexpat/libexpat/pull/1183/commits/fa1ebd60bfcc6d32f329803e5e837251e2387ed1]
+
+Signed-off-by: Sebastian Pipping <sebastian@pipping.org>
+Signed-off-by: Amaury Couderc <amaury.couderc@est.tech>
+---
+ lib/internal.h |  2 ++
+ lib/xmlparse.c | 80 +++++++++++++++++++++++++++++++-------------------
+ 2 files changed, 52 insertions(+), 30 deletions(-)
+
+diff --git a/lib/internal.h b/lib/internal.h
+index 61266ebb..1995c17b 100644
+--- a/lib/internal.h
++++ b/lib/internal.h
+@@ -113,6 +113,7 @@
+ #if defined(_WIN32)                                                            \
+     && (! defined(__USE_MINGW_ANSI_STDIO)                                      \
+         || (1 - __USE_MINGW_ANSI_STDIO - 1 == 0))
++#  define EXPAT_FMT_LLX(midpart) "%" midpart "I64x"
+ #  define EXPAT_FMT_ULL(midpart) "%" midpart "I64u"
+ #  if defined(_WIN64) // Note: modifiers "td" and "zu" do not work for MinGW
+ #    define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "I64d"
+@@ -122,6 +123,7 @@
+ #    define EXPAT_FMT_SIZE_T(midpart) "%" midpart "u"
+ #  endif
+ #else
++#  define EXPAT_FMT_LLX(midpart) "%" midpart "llx"
+ #  define EXPAT_FMT_ULL(midpart) "%" midpart "llu"
+ #  if ! defined(ULONG_MAX)
+ #    error Compiler did not define ULONG_MAX for us
+diff --git a/lib/xmlparse.c b/lib/xmlparse.c
+index 0248b665..59235c85 100644
+--- a/lib/xmlparse.c
++++ b/lib/xmlparse.c
+@@ -604,7 +604,7 @@ static ELEMENT_TYPE *getElementType(XML_Parser parser, const ENCODING *enc,
+ 
+ static XML_Char *copyString(const XML_Char *s, XML_Parser parser);
+ 
+-static unsigned long generate_hash_secret_salt(XML_Parser parser);
++static struct sipkey generate_hash_secret_salt(void);
+ static XML_Bool startParsing(XML_Parser parser);
+ 
+ static XML_Parser parserCreate(const XML_Char *encodingName,
+@@ -777,7 +777,8 @@ struct XML_ParserStruct {
+   XML_Bool m_useForeignDTD;
+   enum XML_ParamEntityParsing m_paramEntityParsing;
+ #endif
+-  unsigned long m_hash_secret_salt;
++  struct sipkey m_hash_secret_salt_128;
++  XML_Bool m_hash_secret_salt_set;
+ #if XML_GE == 1
+   ACCOUNTING m_accounting;
+   MALLOC_TRACKER m_alloc_tracker;
+@@ -1192,57 +1193,61 @@ gather_time_entropy(void) {
+ 
+ #endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
+ 
+-static unsigned long
+-ENTROPY_DEBUG(const char *label, unsigned long entropy) {
++static struct sipkey
++ENTROPY_DEBUG(const char *label, struct sipkey entropy_128) {
+   if (getDebugLevel("EXPAT_ENTROPY_DEBUG", 0) >= 1u) {
+-    fprintf(stderr, "expat: Entropy: %s --> 0x%0*lx (%lu bytes)\n", label,
+-            (int)sizeof(entropy) * 2, entropy, (unsigned long)sizeof(entropy));
++    fprintf(stderr,
++            "expat: Entropy: %s --> [0x" EXPAT_FMT_LLX(
++                "016") ", 0x" EXPAT_FMT_LLX("016") "] (16 bytes)\n",
++            label, (unsigned long long)entropy_128.k[0],
++            (unsigned long long)entropy_128.k[1]);
+   }
+-  return entropy;
++  return entropy_128;
+ }
+ 
+-static unsigned long
+-generate_hash_secret_salt(XML_Parser parser) {
+-  unsigned long entropy;
+-  (void)parser;
++static struct sipkey
++generate_hash_secret_salt(void) {
++  struct sipkey entropy;
+ 
+   /* "Failproof" high quality providers: */
+ #if defined(HAVE_ARC4RANDOM_BUF)
+   arc4random_buf(&entropy, sizeof(entropy));
+   return ENTROPY_DEBUG("arc4random_buf", entropy);
+ #elif defined(HAVE_ARC4RANDOM)
+-  writeRandomBytes_arc4random((void *)&entropy, sizeof(entropy));
++  writeRandomBytes_arc4random(&entropy, sizeof(entropy));
+   return ENTROPY_DEBUG("arc4random", entropy);
+ #else
+   /* Try high quality providers first .. */
+ #  ifdef _WIN32
+-  if (writeRandomBytes_rand_s((void *)&entropy, sizeof(entropy))) {
++  if (writeRandomBytes_rand_s(&entropy, sizeof(entropy))) {
+     return ENTROPY_DEBUG("rand_s", entropy);
+   }
+ #  elif defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
+-  if (writeRandomBytes_getrandom_nonblock((void *)&entropy, sizeof(entropy))) {
++  if (writeRandomBytes_getrandom_nonblock(&entropy, sizeof(entropy))) {
+     return ENTROPY_DEBUG("getrandom", entropy);
+   }
+ #  endif
+ #  if ! defined(_WIN32) && defined(XML_DEV_URANDOM)
+-  if (writeRandomBytes_dev_urandom((void *)&entropy, sizeof(entropy))) {
++  if (writeRandomBytes_dev_urandom(&entropy, sizeof(entropy))) {
+     return ENTROPY_DEBUG("/dev/urandom", entropy);
+   }
+ #  endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
+   /* .. and self-made low quality for backup: */
+ 
+-  entropy = gather_time_entropy();
++  entropy.k[0] = 0;
++  entropy.k[1] = gather_time_entropy();
+ #  if ! defined(__wasi__)
+   /* Process ID is 0 bits entropy if attacker has local access */
+-  entropy ^= getpid();
++  entropy.k[1] ^= getpid();
+ #  endif
+ 
+   /* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */
+   if (sizeof(unsigned long) == 4) {
+-    return ENTROPY_DEBUG("fallback(4)", entropy * 2147483647);
++    entropy.k[1] *= 2147483647;
++    return ENTROPY_DEBUG("fallback(4)", entropy);
+   } else {
+-    return ENTROPY_DEBUG("fallback(8)",
+-                         entropy * (unsigned long)2305843009213693951ULL);
++    entropy.k[1] *= 2305843009213693951ULL;
++    return ENTROPY_DEBUG("fallback(8)", entropy);
+   }
+ #endif
+ }
+@@ -1252,7 +1257,7 @@ get_hash_secret_salt(XML_Parser parser) {
+   const XML_Parser rootParser = getRootParserOf(parser, NULL);
+   assert(! rootParser->m_parentParser);
+ 
+-  return rootParser->m_hash_secret_salt;
++  return rootParser->m_hash_secret_salt_128.k[1];
+ }
+ 
+ static enum XML_Error
+@@ -1323,8 +1328,10 @@ callProcessor(XML_Parser parser, const char *start, const char *end,
+ static XML_Bool /* only valid for root parser */
+ startParsing(XML_Parser parser) {
+   /* hash functions must be initialized before setContext() is called */
+-  if (parser->m_hash_secret_salt == 0)
+-    parser->m_hash_secret_salt = generate_hash_secret_salt(parser);
++  if (parser->m_hash_secret_salt_set != XML_TRUE) {
++    parser->m_hash_secret_salt_128 = generate_hash_secret_salt();
++    parser->m_hash_secret_salt_set = XML_TRUE;
++  }
+   if (parser->m_ns) {
+     /* implicit context only set for root parser, since child
+        parsers (i.e. external entity parsers) will inherit it
+@@ -1612,7 +1619,9 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) {
+   parser->m_useForeignDTD = XML_FALSE;
+   parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
+ #endif
+-  parser->m_hash_secret_salt = 0;
++  parser->m_hash_secret_salt_128.k[0] = 0;
++  parser->m_hash_secret_salt_128.k[1] = 0;
++  parser->m_hash_secret_salt_set = XML_FALSE;
+ 
+ #if XML_GE == 1
+   memset(&parser->m_accounting, 0, sizeof(ACCOUNTING));
+@@ -1779,7 +1788,8 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context,
+      from hash tables associated with either parser without us having
+      to worry which hash secrets each table has.
+   */
+-  unsigned long oldhash_secret_salt;
++  struct sipkey oldhash_secret_salt_128;
++  XML_Bool oldhash_secret_salt_set;
+   XML_Bool oldReparseDeferralEnabled;
+ 
+   /* Validate the oldParser parameter before we pull everything out of it */
+@@ -1825,7 +1835,8 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context,
+      from hash tables associated with either parser without us having
+      to worry which hash secrets each table has.
+   */
+-  oldhash_secret_salt = parser->m_hash_secret_salt;
++  oldhash_secret_salt_128 = parser->m_hash_secret_salt_128;
++  oldhash_secret_salt_set = parser->m_hash_secret_salt_set;
+   oldReparseDeferralEnabled = parser->m_reparseDeferralEnabled;
+ 
+ #ifdef XML_DTD
+@@ -1880,7 +1891,8 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context,
+     parser->m_externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
+   parser->m_defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
+   parser->m_ns_triplets = oldns_triplets;
+-  parser->m_hash_secret_salt = oldhash_secret_salt;
++  parser->m_hash_secret_salt_128 = oldhash_secret_salt_128;
++  parser->m_hash_secret_salt_set = oldhash_secret_salt_set;
+   parser->m_reparseDeferralEnabled = oldReparseDeferralEnabled;
+   parser->m_parentParser = oldParser;
+ #ifdef XML_DTD
+@@ -2335,7 +2347,13 @@ XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt) {
+   /* block after XML_Parse()/XML_ParseBuffer() has been called */
+   if (parserBusy(rootParser))
+     return 0;
+-  rootParser->m_hash_secret_salt = hash_salt;
++
++  rootParser->m_hash_secret_salt_128.k[0] = 0;
++  rootParser->m_hash_secret_salt_128.k[1] = hash_salt;
++
++  if (hash_salt != 0) // to remain backwards compatible
++    rootParser->m_hash_secret_salt_set = XML_TRUE;
++
+   return 1;
+ }
+ 
+@@ -7842,8 +7860,10 @@ keylen(KEY s) {
+ 
+ static void
+ copy_salt_to_sipkey(XML_Parser parser, struct sipkey *key) {
+-  key->k[0] = 0;
+-  key->k[1] = get_hash_secret_salt(parser);
++  const XML_Parser rootParser = getRootParserOf(parser, NULL);
++  assert(! rootParser->m_parentParser);
++
++  *key = rootParser->m_hash_secret_salt_128;
+ }
+ 
+ static unsigned long FASTCALL
+-- 
+2.34.1
+
diff --git a/meta/recipes-core/expat/expat/CVE-2026-41080-2.patch b/meta/recipes-core/expat/expat/CVE-2026-41080-2.patch
new file mode 100644
index 0000000000..a52d61e611
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2026-41080-2.patch
@@ -0,0 +1,310 @@
+From 969472a6d33e994c234ab2ed34f1a01348351b28 Mon Sep 17 00:00:00 2001
+From: Amaury Couderc <amaury.couderc@est.tech>
+Date: Thu, 2 Jul 2026 09:23:00 +0000
+Subject: [PATCH 2/3] expat: add XML_SetHashSalt16Bytes API for CVE-2026-41080
+
+Add the new XML_SetHashSalt16Bytes API function which accepts a full
+16 bytes of entropy for the hash salt, matching the capacity of the
+SipHash implementation used by Expat. The existing XML_SetHashSalt
+function is marked as deprecated since it only provides 4 to 8 bytes
+of entropy depending on the size of unsigned long.
+
+Changes include:
+- Add XML_SetHashSalt16Bytes to public API (expat.h)
+- Add symbol export in libexpat.map.in (LIBEXPAT_2.7.6)
+- Mark XML_SetHashSalt as deprecated
+- Document that XML_SetHashSalt needs a non-NULL parser
+- Include XML_SetHashSalt* with entropy debugging
+- Add test_hash_salt_setter unit test
+- Update documentation and Changes file
+
+Squashed backport of upstream commits f76124e7, e3349d85, c8c5caf4,
+592d5fa3, 8ad3ef57, ec9fcd2e, and 8017e11e.
+
+CVE: CVE-2026-41080
+Upstream-Status: Backport [https://github.com/libexpat/libexpat/pull/1183/commits/4ba09dc471b39a78d77e5179d0243186c0c4ff7a]
+
+Signed-off-by: Sebastian Pipping <sebastian@pipping.org>
+Signed-off-by: Amaury Couderc <amaury.couderc@est.tech>
+---
+ Changes             | 17 ++++++++++++++
+ doc/reference.html  | 55 ++++++++++++++++++++++++++++++++++++++++-----
+ lib/expat.h         | 15 +++++++++++++++
+ lib/libexpat.map.in |  5 +++++
+ lib/xmlparse.c      | 33 ++++++++++++++++++++++++++-
+ tests/basic_tests.c | 25 +++++++++++++++++++++
+ 6 files changed, 144 insertions(+), 6 deletions(-)
+
+diff --git a/Changes b/Changes
+index 2b3704a6..1d8227ec 100644
+--- a/Changes
++++ b/Changes
+@@ -29,6 +29,23 @@
+ !! THANK YOU!                        Sebastian Pipping -- Berlin, 2026-03-17 !!
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ 
++Patches
++        Security fixes:
++       #47 #1183  CVE-2026-41080 -- The existing hash flooding protection
++                    (based on SipHash) only used 4 to 8 bytes of entropy for
++                    a salt, when 16 bytes of salt are supported by the
++                    implementation of SipHash used by Expat. Now full 16 bytes
++                    of entropy are used to improve protection against hash
++                    flooding attacks.
++                      Existing API function XML_SetHashSalt is now deprecated
++                    because of its limitations, and its use should be
++                    considered a vulnerability. Please either use the new API
++                    function XML_SetHashSalt16Bytes (with known-high-quality
++                    entropy input only!) instead, or leave the derivation of
++                    a 16-bytes hash salt from high quality entropy to Expat's
++                    internal machinery (by *not* calling either of the two
++                    XML_SetHashSalt* functions).
++
+ Release 2.7.5 Tue March 17 2026
+         Security fixes:
+            #1158  CVE-2026-32776 -- Fix NULL function pointer dereference for
+diff --git a/doc/reference.html b/doc/reference.html
+index 5faa8d65..64b9fd67 100644
+--- a/doc/reference.html
++++ b/doc/reference.html
+@@ -404,7 +404,11 @@
+                 </li>
+ 
+                 <li>
+-                  <a href="#XML_SetHashSalt">XML_SetHashSalt</a>
++                  <a href="#XML_SetHashSalt">XML_SetHashSalt</a> (deprecated)
++                </li>
++
++                <li>
++                  <a href="#XML_SetHashSalt16Bytes">XML_SetHashSalt16Bytes</a>
+                 </li>
+ 
+                 <li>
+@@ -3449,22 +3453,35 @@ XML_SetParamEntityParsing(XML_Parser p,
+       </div>
+ 
+       <h4 id="XML_SetHashSalt">
+-        XML_SetHashSalt
++        XML_SetHashSalt (deprecated)
+       </h4>
+ 
+       <pre class="fcndec">
+ int XMLCALL
+-XML_SetHashSalt(XML_Parser p,
++XML_SetHashSalt(XML_Parser parser,
+                 unsigned long hash_salt);
+ </pre>
+       <div class="fcndef">
+         Sets the hash salt to use for internal hash calculations. Helps in preventing DoS
+         attacks based on predicting hash function behavior. In order to have an effect
+         this must be called before parsing has started. Returns 1 if successful, 0 when
+-        called after <code>XML_Parse</code> or <code>XML_ParseBuffer</code>.
++        called after <code>XML_Parse</code> or <code>XML_ParseBuffer</code> or when
++        <code>parser</code> is <code>NULL</code>.
++        <p>
++          <b>Note:</b> Function <code>XML_SetHashSalt</code> is
++          <strong>deprecated</strong>. Please use function <code><a href=
++          "#XML_SetHashSalt16Bytes">XML_SetHashSalt16Bytes</a></code> instead for better
++          security. <code>XML_SetHashSalt</code> only provides 4 to 8 bytes of entropy
++          (depending on the size of type <code>unsigned long</code>) while the SipHash
++          implementation used by Expat can leverage up to 16 bytes of entropy — at least
++          twice as much. Function <code><a href=
++          "#XML_SetHashSalt16Bytes">XML_SetHashSalt16Bytes</a></code> of Expat &gt;=2.7.6
++          (and where backported) matches the amount of entropy supported by SipHash.
++        </p>
++
+         <p>
+           <b>Note:</b> This call is optional, as the parser will auto-generate a new
+-          random salt value if no value has been set at the start of parsing.
++          random salt value internally if no value has been set by the start of parsing.
+         </p>
+ 
+         <p>
+@@ -3475,6 +3492,34 @@ XML_SetHashSalt(XML_Parser p,
+         </p>
+       </div>
+ 
++      <h4 id="XML_SetHashSalt16Bytes">
++        XML_SetHashSalt16Bytes
++      </h4>
++
++      <pre class="fcndec">
++/* Added in Expat 2.7.6. */
++XML_Bool XMLCALL
++XML_SetHashSalt16Bytes(XML_Parser parser,
++                       const uint8_t entropy[16]);
++</pre>
++      <div class="fcndef">
++        Sets the hash salt to use for internal hash calculations. Helps in preventing DoS
++        attacks based on predicting hash function behavior. In order to have an effect
++        this must be called before parsing has started. Returns <code>XML_TRUE</code> if
++        successful, <code>XML_FALSE</code> when called after <code>XML_Parse</code> or
++        <code>XML_ParseBuffer</code> or when <code>parser</code> is <code>NULL</code>.
++        <p>
++          <b>Note:</b> Setting a salt that is <em>not</em> from a source of high quality
++          entropy (like <code>getentropy(3)</code>) will make the parser vulnerable to
++          hash flooding attacks.
++        </p>
++
++        <p>
++          <b>Note:</b> This call is optional, as the parser will auto-generate a new
++          random salt value internally if no value has been set by the start of parsing.
++        </p>
++      </div>
++
+       <h4 id="XML_UseForeignDTD">
+         XML_UseForeignDTD
+       </h4>
+diff --git a/lib/expat.h b/lib/expat.h
+index 18dbaebd..7693f62c 100644
+--- a/lib/expat.h
++++ b/lib/expat.h
+@@ -45,6 +45,7 @@
+ #ifndef Expat_INCLUDED
+ #  define Expat_INCLUDED 1
+ 
++#  include <stdint.h> // for uint8_t
+ #  include <stdlib.h>
+ #  include "expat_external.h"
+ 
+@@ -917,10 +918,25 @@ XML_SetParamEntityParsing(XML_Parser parser,
+    function behavior. This must be called before parsing is started.
+    Returns 1 if successful, 0 when called after parsing has started.
+    Note: If parser == NULL, the function will do nothing and return 0.
++   DEPRECATED since Expat 2.7.6.
+ */
+ XMLPARSEAPI(int)
+ XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt);
+ 
++/* Sets the hash salt to use for internal hash calculations.
++   Helps in preventing DoS attacks based on predicting hash function behavior.
++   This must be called before parsing is started.
++   Returns XML_TRUE if successful, XML_FALSE when called after parsing has
++   started or when parser is NULL.
++   Added in Expat 2.7.6.
++*/
++XMLPARSEAPI(XML_Bool)
++XML_SetHashSalt16Bytes(XML_Parser parser, const uint8_t entropy[16]);
++
++/* Backport feature macro: signals that XML_SetHashSalt16Bytes is available
++   even though XML_COMBINED_VERSION < 20800. */
++#  define XML_BACKPORT_SET_HASH_SALT_16_BYTES 1
++
+ /* If XML_Parse or XML_ParseBuffer have returned XML_STATUS_ERROR, then
+    XML_GetErrorCode returns information about the error.
+ */
+diff --git a/lib/libexpat.map.in b/lib/libexpat.map.in
+index 52e59ed3..8527eb54 100644
+--- a/lib/libexpat.map.in
++++ b/lib/libexpat.map.in
+@@ -117,3 +117,8 @@ LIBEXPAT_2.7.2 {
+ @_EXPAT_COMMENT_DTD_OR_GE@ XML_SetAllocTrackerActivationThreshold;
+ @_EXPAT_COMMENT_DTD_OR_GE@ XML_SetAllocTrackerMaximumAmplification;
+ } LIBEXPAT_2.6.0;
++
++LIBEXPAT_2.7.6 {
++ global:
++  XML_SetHashSalt16Bytes;
++} LIBEXPAT_2.7.2;
+diff --git a/lib/xmlparse.c b/lib/xmlparse.c
+index 59235c85..09ae4f92 100644
+--- a/lib/xmlparse.c
++++ b/lib/xmlparse.c
+@@ -2336,6 +2336,7 @@ XML_SetParamEntityParsing(XML_Parser parser,
+ #endif
+ }
+ 
++// DEPRECATED since Expat 2.7.6.
+ int XMLCALL
+ XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt) {
+   if (parser == NULL)
+@@ -2351,12 +2352,42 @@ XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt) {
+   rootParser->m_hash_secret_salt_128.k[0] = 0;
+   rootParser->m_hash_secret_salt_128.k[1] = hash_salt;
+ 
+-  if (hash_salt != 0) // to remain backwards compatible
++  if (hash_salt != 0) { // to remain backwards compatible
+     rootParser->m_hash_secret_salt_set = XML_TRUE;
+ 
++    if (sizeof(unsigned long) == 4)
++      ENTROPY_DEBUG("explicit(4)", rootParser->m_hash_secret_salt_128);
++    else
++      ENTROPY_DEBUG("explicit(8)", rootParser->m_hash_secret_salt_128);
++  }
++
+   return 1;
+ }
+ 
++XML_Bool XMLCALL
++XML_SetHashSalt16Bytes(XML_Parser parser, const uint8_t entropy[16]) {
++  if (parser == NULL)
++    return XML_FALSE;
++
++  if (entropy == NULL)
++    return XML_FALSE;
++
++  const XML_Parser rootParser = getRootParserOf(parser, NULL);
++  assert(! rootParser->m_parentParser);
++
++  /* block after XML_Parse()/XML_ParseBuffer() has been called */
++  if (parserBusy(rootParser))
++    return XML_FALSE;
++
++  sip_tokey(&(rootParser->m_hash_secret_salt_128), entropy);
++
++  rootParser->m_hash_secret_salt_set = XML_TRUE;
++
++  ENTROPY_DEBUG("explicit(16)", rootParser->m_hash_secret_salt_128);
++
++  return XML_TRUE;
++}
++
+ enum XML_Status XMLCALL
+ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) {
+   if ((parser == NULL) || (len < 0) || ((s == NULL) && (len != 0))) {
+diff --git a/tests/basic_tests.c b/tests/basic_tests.c
+index 02d1d5fd..26662fee 100644
+--- a/tests/basic_tests.c
++++ b/tests/basic_tests.c
+@@ -204,6 +204,30 @@ START_TEST(test_hash_collision) {
+ END_TEST
+ #undef COLLIDING_HASH_SALT
+ 
++START_TEST(test_hash_salt_setter) {
++  const uint8_t entropy[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
++                               '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
++  XML_Parser parser = XML_ParserCreate(NULL);
++
++  // NULL parser should be rejected
++  assert_true(XML_SetHashSalt16Bytes(NULL, entropy) == XML_FALSE);
++
++  // NULL entropy should be rejected
++  assert_true(XML_SetHashSalt16Bytes(parser, NULL) == XML_FALSE);
++
++  // Setting should be allowed more than once
++  assert_true(XML_SetHashSalt16Bytes(parser, entropy) == XML_TRUE);
++  assert_true(XML_SetHashSalt16Bytes(parser, entropy) == XML_TRUE);
++
++  // But not after parsing has started
++  assert_true(XML_Parse(parser, "", 0, XML_FALSE /* isFinal */)
++              == XML_STATUS_OK);
++  assert_true(XML_SetHashSalt16Bytes(parser, entropy) == XML_FALSE);
++
++  XML_ParserFree(parser);
++}
++END_TEST
++
+ /* Regression test for SF bug #491986. */
+ START_TEST(test_danish_latin1) {
+   const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
+@@ -6292,6 +6316,7 @@ make_basic_test_case(Suite *s) {
+   tcase_add_test(tc_basic, test_bom_utf16_le);
+   tcase_add_test(tc_basic, test_nobom_utf16_le);
+   tcase_add_test(tc_basic, test_hash_collision);
++  tcase_add_test(tc_basic, test_hash_salt_setter);
+   tcase_add_test(tc_basic, test_illegal_utf8);
+   tcase_add_test(tc_basic, test_utf8_auto_align);
+   tcase_add_test(tc_basic, test_utf16);
+-- 
+2.34.1
+
diff --git a/meta/recipes-core/expat/expat/CVE-2026-41080-3.patch b/meta/recipes-core/expat/expat/CVE-2026-41080-3.patch
new file mode 100644
index 0000000000..69a1c99fcc
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2026-41080-3.patch
@@ -0,0 +1,32 @@
+From cfc4475518cd38890071b280e8619e74dd9e8722 Mon Sep 17 00:00:00 2001
+From: Christoph Reiter <reiter.christoph@gmail.com>
+Date: Wed, 10 Jun 2026 21:27:51 +0200
+Subject: [PATCH 3/3] cmake|windows: add missing export for new XML_SetHashSalt16Bytes
+
+A new XML_SetHashSalt16Bytes symbol was added in #1183, but it
+wasn't added to the def file, so the export is missing when building
+libexpat on Windows with cmake.
+
+Add the new symbol to the .def template.
+
+CVE: CVE-2026-41080
+Upstream-Status: Backport [https://github.com/libexpat/libexpat/pull/1270/commits/3cdd1df2644388aff25dd0ed7128c7bb1de1a7d8]
+
+Signed-off-by: Amaury Couderc <amaury.couderc@est.tech>
+---
+ lib/libexpat.def.cmake | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/lib/libexpat.def.cmake b/lib/libexpat.def.cmake
+index 9b9e22cb..948135a5 100644
+--- a/lib/libexpat.def.cmake
++++ b/lib/libexpat.def.cmake
+@@ -83,3 +83,5 @@ EXPORTS
+ ; added with version 2.7.2
+ @_EXPAT_COMMENT_DTD_OR_GE@ XML_SetAllocTrackerMaximumAmplification @72
+ @_EXPAT_COMMENT_DTD_OR_GE@ XML_SetAllocTrackerActivationThreshold @73
++; added with version 2.7.6
++  XML_SetHashSalt16Bytes @74
+-- 
+2.34.1
+
diff --git a/meta/recipes-core/expat/expat_2.7.5.bb b/meta/recipes-core/expat/expat_2.7.5.bb
index 4f2578292d..1191d9a943 100644
--- a/meta/recipes-core/expat/expat_2.7.5.bb
+++ b/meta/recipes-core/expat/expat_2.7.5.bb
@@ -10,6 +10,9 @@ VERSION_TAG = "${@d.getVar('PV').replace('.', '_')}"
 
 SRC_URI = "${GITHUB_BASE_URI}/download/R_${VERSION_TAG}/expat-${PV}.tar.bz2  \
            file://run-ptest \
+           file://CVE-2026-41080-1.patch \
+           file://CVE-2026-41080-2.patch \
+           file://CVE-2026-41080-3.patch \
            "
 
 GITHUB_BASE_URI = "https://github.com/libexpat/libexpat/releases/"
