diff --git a/meta/recipes-core/expat/expat/CVE-2026-56131.patch b/meta/recipes-core/expat/expat/CVE-2026-56131.patch
new file mode 100644
index 0000000000..8691f98f89
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2026-56131.patch
@@ -0,0 +1,124 @@
+From 29dfca6ad4d2a9dfd5ce72efd72e1b67d598ab4c Mon Sep 17 00:00:00 2001
+From: netliomax25-code <netliomax25@gmail.com>
+Date: Sat, 6 Jun 2026 20:03:53 +0530
+Subject: [PATCH] lib: protect XML_ResumeParser from being called from a
+ handler
+
+The handler-reentrancy guards from CVE-2026-50219 cover XML_Parse, XML_ParseBuffer, XML_GetBuffer, XML_ParserFree and XML_ParserReset but not XML_ResumeParser, which drives the parser through callProcessor in the same way.
+
+(cherry picked from commit d5a654b4881f450827af5b3b7b72370a3bbf9a8f)
+
+CVE: CVE-2026-56131
+Upstream-Status: Backport [https://github.com/libexpat/libexpat/pull/1267/commits/d5a654b4881f450827af5b3b7b72370a3bbf9a8f]
+Signed-off-by: Jakub Szczudlo <jakub.szczudlo@nokia.com>
+---
+ lib/xmlparse.c     |  2 +-
+ tests/handlers.c   | 24 ++++++++++++++++++++++++
+ tests/handlers.h   |  9 +++++++++
+ tests/misc_tests.c | 20 ++++++++++++++++++++
+ 4 files changed, 54 insertions(+), 1 deletion(-)
+
+diff --git a/lib/xmlparse.c b/lib/xmlparse.c
+index cc1d550..a5fa256 100644
+--- a/lib/xmlparse.c
++++ b/lib/xmlparse.c
+@@ -2778,7 +2778,7 @@ enum XML_Status XMLCALL
+ XML_ResumeParser(XML_Parser parser) {
+   enum XML_Status result = XML_STATUS_OK;
+ 
+-  if (parser == NULL)
++  if ((parser == NULL) || isCalledFromInsideHandler(parser))
+     return XML_STATUS_ERROR;
+   if (parser->m_parsingStatus.parsing != XML_SUSPENDED) {
+     parser->m_errorCode = XML_ERROR_NOT_SUSPENDED;
+diff --git a/tests/handlers.c b/tests/handlers.c
+index c7d6578..5a85f6d 100644
+--- a/tests/handlers.c
++++ b/tests/handlers.c
+@@ -2015,3 +2015,27 @@ forbidden_calls_character_handler(void *userData, const XML_Char *s, int len) {
+ 
+   assert_true(XML_GetErrorCode(parser) == XML_ERROR_NONE);
+ }
++
++void XMLCALL
++suspend_then_resume_character_handler(void *userData, const XML_Char *s,
++                                      int len) {
++  UNUSED_P(s);
++  UNUSED_P(len);
++  ResumeFromHandlerData *const data = (ResumeFromHandlerData *)userData;
++
++  data->callCount++;
++  if (data->callCount > 1) {
++    // Reached only if the guard under test is missing: XML_ResumeParser would
++    // then have driven the parser re-entrantly and called us again.  Bail out
++    // so the test fails by assertion below rather than recursing without bound.
++    return;
++  }
++
++  // Put the parser into XML_SUSPENDED so that, without the guard,
++  // XML_ResumeParser would proceed into a re-entrant parse.
++  assert_true(XML_StopParser(data->parser, /*resumable=*/XML_TRUE)
++              == XML_STATUS_OK);
++
++  // Resuming the parser from inside a handler must be rejected.
++  assert_true(XML_ResumeParser(data->parser) == XML_STATUS_ERROR);
++}
+diff --git a/tests/handlers.h b/tests/handlers.h
+index de28392..507ad8b 100644
+--- a/tests/handlers.h
++++ b/tests/handlers.h
+@@ -616,6 +616,15 @@ extern void XMLCALL forbidden_calls_character_handler(void *userData,
+                                                       const XML_Char *s,
+                                                       int len);
+ 
++typedef struct {
++  XML_Parser parser;
++  int callCount;
++} ResumeFromHandlerData;
++
++extern void XMLCALL suspend_then_resume_character_handler(void *userData,
++                                                          const XML_Char *s,
++                                                          int len);
++
+ #endif /* XML_HANDLERS_H */
+ 
+ #ifdef __cplusplus
+diff --git a/tests/misc_tests.c b/tests/misc_tests.c
+index b9053fe..265e7cb 100644
+--- a/tests/misc_tests.c
++++ b/tests/misc_tests.c
+@@ -815,6 +815,25 @@ START_TEST(test_misc_calls_forbidden_from_handlers) {
+ }
+ END_TEST
+ 
++START_TEST(test_misc_resume_parser_forbidden_from_handler) {
++  const char *const doc = "<doc>Hello world!</doc>";
++
++  XML_Parser parser = XML_ParserCreate(NULL);
++  ResumeFromHandlerData data = {parser, 0};
++  XML_SetUserData(parser, &data);
++  XML_SetCharacterDataHandler(parser, suspend_then_resume_character_handler);
++
++  // The handler suspends the parser, so the top-level parse reports suspension
++  // rather than completion.  The handler also asserts that resuming from inside
++  // itself is rejected.
++  assert_true(XML_Parse(parser, doc, (int)strlen(doc), /*isFinal=*/XML_TRUE)
++              == XML_STATUS_SUSPENDED);
++  assert_true(data.callCount == 1);
++
++  XML_ParserFree(parser);
++}
++END_TEST
++
+ void
+ make_miscellaneous_test_case(Suite *s) {
+   TCase *tc_misc = tcase_create("miscellaneous tests");
+@@ -847,4 +866,5 @@ make_miscellaneous_test_case(Suite *s) {
+   tcase_add_test(tc_misc, test_misc_async_entity_rejected);
+   tcase_add_test(tc_misc, test_misc_no_infinite_loop_issue_1161);
+   tcase_add_test(tc_misc, test_misc_calls_forbidden_from_handlers);
++  tcase_add_test(tc_misc, test_misc_resume_parser_forbidden_from_handler);
+ }
+-- 
+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 7f00c6f90b..78e35243c5 100644
--- a/meta/recipes-core/expat/expat_2.7.5.bb
+++ b/meta/recipes-core/expat/expat_2.7.5.bb
@@ -68,6 +68,7 @@ SRC_URI = "${GITHUB_BASE_URI}/download/R_${VERSION_TAG}/expat-${PV}.tar.bz2  \
            file://CVE-2026-50219-30.patch \
            file://CVE-2026-50219-31.patch \
            file://CVE-2026-50219-32.patch \
+           file://CVE-2026-56131.patch \
            "
 
 GITHUB_BASE_URI = "https://github.com/libexpat/libexpat/releases/"
