diff --git a/meta/recipes-support/curl/curl/CVE-2026-87866.patch b/meta/recipes-support/curl/curl/CVE-2026-87866.patch
new file mode 100644
index 0000000000..c42aee1f0f
--- /dev/null
+++ b/meta/recipes-support/curl/curl/CVE-2026-87866.patch
@@ -0,0 +1,750 @@
+From ed131747c1a3dc7f816d26724c44537ac8acba44 Mon Sep 17 00:00:00 2001
+From: Stefan Eissing <stefan@eissing.org>
+Date: Wed, 2 Sep 2026 12:25:50 +0200
+Subject: [PATCH] x509: stricter parsing
+
+Check that the "validity" ASN.1 field has a length matching the
+contained date elements and fail the parsing otherwise.
+
+This is a precaution against malformed cert data that should have been
+caught by the TLS backend already. A bit added defense.
+
+Closes #22799
+
+CVE: CVE-2026-87866
+Upstream-Status: Backport [https://github.com/curl/curl/commit/ed131747c1a3dc7f816d26724c44537ac8acba44]
+
+Backport Changes:
+- Apply the byte-pointer updates to curl 8.19.0's older ASN.1 helpers.
+  Retain its Boolean, bit-string, integer and OID conversion logic,
+  including OID2str()'s symbolic argument in its updated signature.
+- Keep getASN1Element_()'s older flat length branches while applying
+  the byte reads and bounds comparison.
+- Expose getASN1Element() with UNITTEST and remove the older
+  Curl_x509_getASN1Element() wrapper. Add the private test prototype
+  to x509asn1.h: the old generator extracts only single-line prototypes.
+  Guard the production forward declaration to avoid a duplicate in
+  unit-test builds; retain WARN_UNUSED_RESULT on both declarations.
+- Adapt test1657 from the old CURLcode wrapper to the parser's pointer
+  result with the same success/error expectations. Rename its
+  inactive-build message to match the parser name.
+- Omit the type-only updates to unit1666, unit1667 and unit1676. These
+  tests are absent in 8.19.0; [1], [2] and [3] introduced them for OID
+  conversion, ASN.1-to-string conversion and DH public-key extraction.
+
+[1] https://github.com/curl/curl/commit/673e14cd33ef720b8c2b7e3485084e6e41a2c9dd
+[2] https://github.com/curl/curl/commit/14782b36fea2a5f69029b2b898302b6ba5aef838
+[3] https://github.com/curl/curl/commit/61d59c9e39b451b30feb431b780a5cc325757921
+
+Signed-off-by: Darsh Kelaiya <dkelaiya@cisco.com>
+---
+ lib/vtls/gtls.c       |   4 +-
+ lib/vtls/mbedtls.c    |   5 +-
+ lib/vtls/rustls.c     |  13 ++---
+ lib/vtls/schannel.c   |  10 ++--
+ lib/vtls/wolfssl.c    |   4 +-
+ lib/vtls/x509asn1.c   | 124 +++++++++++++++++++++---------------------
+ lib/vtls/x509asn1.h   |  22 ++++----
+ tests/unit/unit1651.c |   6 +-
+ tests/unit/unit1657.c |  79 ++++++++++++++++++++++++---
+ 9 files changed, 163 insertions(+), 104 deletions(-)
+
+diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c
+index b87b27d864..02a8147520 100644
+--- a/lib/vtls/gtls.c
++++ b/lib/vtls/gtls.c
+@@ -1626,8 +1626,8 @@ CURLcode Curl_gtls_verifyserver(struct Curl_cfilter *cf,
+         goto out;
+ 
+       for(i = 0; i < chain.num_certs; i++) {
+-        const char *beg = (const char *)chain.certs[i].data;
+-        const char *end = beg + chain.certs[i].size;
++        const uint8_t *beg = chain.certs[i].data;
++        const uint8_t *end = beg + chain.certs[i].size;
+ 
+         result = Curl_extract_certinfo(data, (int)i, beg, end);
+         if(result)
+diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c
+index d2199df884..cf7ac29594 100644
+--- a/lib/vtls/mbedtls.c
++++ b/lib/vtls/mbedtls.c
+@@ -431,9 +431,8 @@ static void mbed_extract_certinfo(struct Curl_easy *data,
+   result = Curl_ssl_init_certinfo(data, cert_count);
+ 
+   for(i = 0, cur = crt; result == CURLE_OK && cur; ++i, cur = cur->next) {
+-    const char *beg = (const char *)cur->raw.p;
+-    const char *end = beg + cur->raw.len;
+-    result = Curl_extract_certinfo(data, i, beg, end);
++    result = Curl_extract_certinfo(data, i, cur->raw.p,
++                                   cur->raw.p + cur->raw.len);
+   }
+ }
+ 
+diff --git a/lib/vtls/rustls.c b/lib/vtls/rustls.c
+index 89619432b8..017e7ddcd8 100644
+--- a/lib/vtls/rustls.c
++++ b/lib/vtls/rustls.c
+@@ -1225,15 +1225,10 @@ static CURLcode cr_connect(struct Curl_cfilter *cf, struct Curl_easy *data,
+                   (int)errorlen, errorbuf);
+             return map_error(rresult);
+           }
+-          {
+-            const char *beg;
+-            const char *end;
+-            beg = (const char *)der_data;
+-            end = (const char *)(der_data + der_len);
+-            result = Curl_extract_certinfo(data, (int)i, beg, end);
+-            if(result)
+-              return result;
+-          }
++          result = Curl_extract_certinfo(data, (int)i,
++                                         der_data, der_data + der_len);
++          if(result)
++            return result;
+         }
+       }
+ 
+diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
+index a4f57c7c0a..643b6d510c 100644
+--- a/lib/vtls/schannel.c
++++ b/lib/vtls/schannel.c
+@@ -1108,7 +1108,7 @@ static CURLcode schannel_pkp_pin_peer_pubkey(struct Curl_cfilter *cf,
+ 
+   do {
+     SECURITY_STATUS sspi_status;
+-    const char *x509_der;
++    uint8_t *x509_der;
+     DWORD x509_der_len;
+     struct Curl_X509certificate x509_parsed;
+     struct Curl_asn1Element *pubkey;
+@@ -1129,7 +1129,7 @@ static CURLcode schannel_pkp_pin_peer_pubkey(struct Curl_cfilter *cf,
+          (pCertContextServer->cbCertEncoded > 0)))
+       break;
+ 
+-    x509_der = (const char *)pCertContextServer->pbCertEncoded;
++    x509_der = (uint8_t *)pCertContextServer->pbCertEncoded;
+     x509_der_len = pCertContextServer->cbCertEncoded;
+     memset(&x509_parsed, 0, sizeof(x509_parsed));
+     if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len))
+@@ -1543,12 +1543,12 @@ static bool add_cert_to_certinfo(const CERT_CONTEXT *ccert_context,
+   struct Adder_args *args = (struct Adder_args *)raw_arg;
+   args->result = CURLE_OK;
+   if(valid_cert_encoding(ccert_context)) {
+-    const char *beg = (const char *)ccert_context->pbCertEncoded;
+-    const char *end = beg + ccert_context->cbCertEncoded;
+     int insert_index = reverse_order ? (args->certs_count - 1) - args->idx :
+                        args->idx;
+     args->result = Curl_extract_certinfo(args->data, insert_index,
+-                                         beg, end);
++                                         ccert_context->pbCertEncoded,
++                                         ccert_context->pbCertEncoded +
++                                         ccert_context->cbCertEncoded);
+     args->idx++;
+   }
+   return args->result == CURLE_OK;
+diff --git a/lib/vtls/wolfssl.c b/lib/vtls/wolfssl.c
+index c901ebfe1e..5a2967d275 100644
+--- a/lib/vtls/wolfssl.c
++++ b/lib/vtls/wolfssl.c
+@@ -1545,7 +1545,7 @@ CURLcode Curl_wssl_verify_pinned(struct Curl_cfilter *cf,
+ 
+   if(pinnedpubkey) {
+ #ifdef KEEP_PEER_CERT
+-    const char *x509_der;
++    const uint8_t *x509_der;
+     int x509_der_len;
+     struct Curl_X509certificate x509_parsed;
+     struct Curl_asn1Element *pubkey;
+@@ -1558,7 +1558,7 @@ CURLcode Curl_wssl_verify_pinned(struct Curl_cfilter *cf,
+       goto end;
+     }
+ 
+-    x509_der = (const char *)wolfSSL_X509_get_der(x509, &x509_der_len);
++    x509_der = wolfSSL_X509_get_der(x509, &x509_der_len);
+     if(!x509_der) {
+       failf(data, "SSL: failed retrieving ASN.1 server certificate");
+       goto end;
+diff --git a/lib/vtls/x509asn1.c b/lib/vtls/x509asn1.c
+index b687a60193..65f2d9229d 100644
+--- a/lib/vtls/x509asn1.c
++++ b/lib/vtls/x509asn1.c
+@@ -160,17 +160,19 @@ static const struct Curl_OID OIDtable[] = {
+  * Please note there is no pretension here to rewrite a full SSL library.
+  */
+ 
+-static const char *getASN1Element(struct Curl_asn1Element *elem,
+-                                  const char *beg, const char *end)
++#ifndef UNITTESTS
++static const uint8_t *getASN1Element(struct Curl_asn1Element *elem,
++                                     const uint8_t *beg, const uint8_t *end)
+   WARN_UNUSED_RESULT;
++#endif
+ 
+ #define CURL_ASN1_MAX_RECURSIONS    16
+ 
+-static const char *getASN1Element_(struct Curl_asn1Element *elem,
+-                                   const char *beg, const char *end,
++static const uint8_t *getASN1Element_(struct Curl_asn1Element *elem,
++                                      const uint8_t *beg, const uint8_t *end,
+                                    size_t lvl)
+ {
+-  unsigned char b;
++  uint8_t b;
+   size_t len;
+   struct Curl_asn1Element lelem;
+ 
+@@ -185,7 +187,7 @@ static const char *getASN1Element_(struct Curl_asn1Element *elem,
+ 
+   /* Process header byte. */
+   elem->header = beg;
+-  b = (unsigned char)*beg++;
++  b = *beg++;
+   elem->constructed = (b & 0x20) != 0;
+   elem->eclass = (b >> 6) & 3;
+   b &= 0x1F;
+@@ -196,7 +198,7 @@ static const char *getASN1Element_(struct Curl_asn1Element *elem,
+   /* Process length. */
+   if(beg >= end)
+     return NULL;
+-  b = (unsigned char)*beg++;
++  b = *beg++;
+   if(!(b & 0x80))
+     len = b;
+   else if(!(b &= 0x7F)) {
+@@ -215,7 +217,7 @@ static const char *getASN1Element_(struct Curl_asn1Element *elem,
+     elem->end = beg;
+     return beg + 1;
+   }
+-  else if((unsigned)b > (size_t)(end - beg))
++  else if(b > (size_t)(end - beg))
+     return NULL; /* Does not fit in source. */
+   else {
+     /* Get long length. */
+@@ -223,7 +225,7 @@ static const char *getASN1Element_(struct Curl_asn1Element *elem,
+     do {
+       if(len & 0xFF000000L)
+         return NULL;  /* Lengths > 32 bits are not supported. */
+-      len = (len << 8) | (unsigned char) *beg++;
++      len = (len << 8) | *beg++;
+     } while(--b);
+   }
+   if(len > (size_t)(end - beg))
+@@ -233,8 +235,11 @@ static const char *getASN1Element_(struct Curl_asn1Element *elem,
+   return elem->end;
+ }
+ 
+-static const char *getASN1Element(struct Curl_asn1Element *elem,
+-                                  const char *beg, const char *end)
++/*
++ * @unittest 1657
++ */
++UNITTEST const uint8_t *getASN1Element(struct Curl_asn1Element *elem,
++                                       const uint8_t *beg, const uint8_t *end)
+ {
+   return getASN1Element_(elem, beg, end, 0);
+ }
+@@ -255,17 +260,6 @@ static const struct Curl_OID *searchOID(const char *oid)
+   return NULL;
+ }
+ 
+-#ifdef UNITTESTS
+-/* used by unit1657.c */
+-CURLcode Curl_x509_getASN1Element(struct Curl_asn1Element *elem,
+-                                  const char *beg, const char *end)
+-{
+-  if(getASN1Element(elem, beg, end))
+-    return CURLE_OK;
+-  return CURLE_BAD_FUNCTION_ARGUMENT;
+-}
+-#endif
+-
+ /*
+  * Convert an ASN.1 Boolean value into its string representation.
+  *
+@@ -273,7 +267,7 @@ CURLcode Curl_x509_getASN1Element(struct Curl_asn1Element *elem,
+  */
+ 
+ static CURLcode bool2str(struct dynbuf *store,
+-                         const char *beg, const char *end)
++                         const uint8_t *beg, const uint8_t *end)
+ {
+   if(end - beg != 1)
+     return CURLE_BAD_FUNCTION_ARGUMENT;
+@@ -286,17 +280,18 @@ static CURLcode bool2str(struct dynbuf *store,
+  * Return error code.
+  */
+ static CURLcode octet2str(struct dynbuf *store,
+-                          const char *beg, const char *end)
++                          const uint8_t *beg, const uint8_t *end)
+ {
+   CURLcode result = CURLE_OK;
+ 
+   while(!result && beg < end)
+-    result = curlx_dyn_addf(store, "%02x:", (unsigned char)*beg++);
++    result = curlx_dyn_addf(store, "%02x:", *beg++);
+ 
+   return result;
+ }
+ 
+-static CURLcode bit2str(struct dynbuf *store, const char *beg, const char *end)
++static CURLcode bit2str(struct dynbuf *store,
++                        const uint8_t *beg, const uint8_t *end)
+ {
+   /* Convert an ASN.1 bit string to a printable string. */
+ 
+@@ -310,7 +305,8 @@ static CURLcode bit2str(struct dynbuf *store, const char *beg, const char *end)
+  *
+  * Returns error.
+  */
+-static CURLcode int2str(struct dynbuf *store, const char *beg, const char *end)
++static CURLcode int2str(struct dynbuf *store,
++                        const uint8_t *beg, const uint8_t *end)
+ {
+   unsigned int val = 0;
+   size_t n = end - beg;
+@@ -326,7 +322,7 @@ static CURLcode int2str(struct dynbuf *store, const char *beg, const char *end)
+     val = ~val;
+ 
+   do
+-    val = (val << 8) | *(const unsigned char *)beg++;
++    val = (val << 8) | *beg++;
+   while(beg < end);
+   return curlx_dyn_addf(store, "%s%x", val >= 10 ? "0x" : "", val);
+ }
+@@ -339,8 +335,8 @@ static CURLcode int2str(struct dynbuf *store, const char *beg, const char *end)
+  *
+  * Returns error.
+  */
+-static CURLcode utf8asn1str(struct dynbuf *to, int type, const char *from,
+-                            const char *end)
++static CURLcode utf8asn1str(struct dynbuf *to, int type,
++                            const uint8_t *from, const uint8_t *end)
+ {
+   size_t inlength = end - from;
+   int size = 1;
+@@ -381,14 +377,14 @@ static CURLcode utf8asn1str(struct dynbuf *to, int type, const char *from,
+ 
+       switch(size) {
+       case 4:
+-        wc = (wc << 8) | *(const unsigned char *)from++;
+-        wc = (wc << 8) | *(const unsigned char *)from++;
++        wc = (wc << 8) | *from++;
++        wc = (wc << 8) | *from++;
+         FALLTHROUGH();
+       case 2:
+-        wc = (wc << 8) | *(const unsigned char *)from++;
++        wc = (wc << 8) | *from++;
+         FALLTHROUGH();
+       default: /* case 1: */
+-        wc = (wc << 8) | *(const unsigned char *)from++;
++        wc = (wc << 8) | *from++;
+       }
+       if(wc >= 0x00000080) {
+         if(wc >= 0x00000800) {
+@@ -422,14 +418,14 @@ static CURLcode utf8asn1str(struct dynbuf *to, int type, const char *from,
+  * Return error code.
+  */
+ static CURLcode encodeOID(struct dynbuf *store,
+-                          const char *beg, const char *end)
++                          const uint8_t *beg, const uint8_t *end)
+ {
+   unsigned int x;
+   unsigned int y;
+   CURLcode result = CURLE_OK;
+ 
+   /* Process the first two numbers. */
+-  y = *(const unsigned char *)beg++;
++  y = *beg++;
+   x = y / 40;
+   y -= x * 40;
+ 
+@@ -445,7 +441,7 @@ static CURLcode encodeOID(struct dynbuf *store,
+         return CURLE_OK;
+       else if(beg == end)
+         return CURLE_BAD_FUNCTION_ARGUMENT;
+-      y = *(const unsigned char *)beg++;
++      y = *beg++;
+       x = (x << 7) | (y & 0x7F);
+     } while(y & 0x80);
+     result = curlx_dyn_addf(store, ".%u", x);
+@@ -460,7 +456,7 @@ static CURLcode encodeOID(struct dynbuf *store,
+  */
+ 
+ static CURLcode OID2str(struct dynbuf *store,
+-                        const char *beg, const char *end, bool symbolic)
++                        const uint8_t *beg, const uint8_t *end, bool symbolic)
+ {
+   CURLcode result = CURLE_OK;
+   if(beg < end) {
+@@ -650,10 +646,12 @@ static CURLcode ASN1tostr(struct dynbuf *store,
+     result = OID2str(store, elem->beg, elem->end, TRUE);
+     break;
+   case CURL_ASN1_UTC_TIME:
+-    result = UTime2str(store, elem->beg, elem->end);
++    result = UTime2str(store, (const char *)elem->beg,
++                       (const char *)elem->end);
+     break;
+   case CURL_ASN1_GENERALIZED_TIME:
+-    result = GTime2str(store, elem->beg, elem->end);
++    result = GTime2str(store, (const char *)elem->beg,
++                       (const char *)elem->end);
+     break;
+   case CURL_ASN1_UTF8_STRING:
+   case CURL_ASN1_NUMERIC_STRING:
+@@ -681,10 +679,10 @@ static CURLcode encodeDN(struct dynbuf *store, struct Curl_asn1Element *dn)
+   struct Curl_asn1Element atv;
+   struct Curl_asn1Element oid;
+   struct Curl_asn1Element value;
+-  const char *p1;
+-  const char *p2;
+-  const char *p3;
+-  const char *str;
++  const uint8_t *p1;
++  const uint8_t *p2;
++  const uint8_t *p3;
++  const uint8_t *str;
+   CURLcode result = CURLE_OK;
+   bool added = FALSE;
+   struct dynbuf temp;
+@@ -716,7 +714,7 @@ static CURLcode encodeDN(struct dynbuf *store, struct Curl_asn1Element *dn)
+       if(result)
+         goto error;
+ 
+-      str = curlx_dyn_ptr(&temp);
++      str = curlx_dyn_uptr(&temp);
+ 
+       if(!str) {
+         result = CURLE_BAD_FUNCTION_ARGUMENT;
+@@ -737,7 +735,7 @@ static CURLcode encodeDN(struct dynbuf *store, struct Curl_asn1Element *dn)
+       }
+ 
+       /* Encode attribute name. */
+-      result = curlx_dyn_add(store, str);
++      result = curlx_dyn_add(store, (const char *)str);
+       if(result)
+         goto error;
+ 
+@@ -769,13 +767,14 @@ error:
+  * See RFC 5280.
+  */
+ int Curl_parseX509(struct Curl_X509certificate *cert,
+-                   const char *beg, const char *end)
++                   const uint8_t *beg, const uint8_t *end)
+ {
+   struct Curl_asn1Element elem;
+   struct Curl_asn1Element tbsCertificate;
+-  const char *ccp;
+-  static const char defaultVersion = 0;  /* v1. */
++  const uint8_t *ccp;
++  static const uint8_t defaultVersion = 0;  /* v1. */
+ 
++  memset(cert, 0, sizeof(*cert));
+   cert->certificate.header = NULL;
+   cert->certificate.beg = beg;
+   cert->certificate.end = end;
+@@ -831,6 +830,9 @@ int Curl_parseX509(struct Curl_X509certificate *cert,
+     return -1;
+   if(!getASN1Element(&cert->notAfter, ccp, elem.end))
+     return -1;
++  /* These two fields MUST consume all of the validity elem */
++  if(elem.end != cert->notAfter.end)
++    return -1;
+   /* Get subject. */
+   beg = getASN1Element(&cert->subject, beg, end);
+   if(!beg)
+@@ -851,10 +853,10 @@ int Curl_parseX509(struct Curl_X509certificate *cert,
+   cert->issuerUniqueID.tag = cert->subjectUniqueID.tag = 0;
+   cert->extensions.tag = elem.tag = 0;
+   cert->issuerUniqueID.header = cert->subjectUniqueID.header = NULL;
+-  cert->issuerUniqueID.beg = cert->issuerUniqueID.end = "";
+-  cert->subjectUniqueID.beg = cert->subjectUniqueID.end = "";
++  cert->issuerUniqueID.beg = cert->issuerUniqueID.end = beg;
++  cert->subjectUniqueID.beg = cert->subjectUniqueID.end = beg;
+   cert->extensions.header = NULL;
+-  cert->extensions.beg = cert->extensions.end = "";
++  cert->extensions.beg = cert->extensions.end = beg;
+   if(beg < end) {
+     beg = getASN1Element(&elem, beg, end);
+     if(!beg)
+@@ -888,7 +890,7 @@ int Curl_parseX509(struct Curl_X509certificate *cert,
+ 
+ static CURLcode dumpAlgo(struct dynbuf *store,
+                          struct Curl_asn1Element *param,
+-                         const char *beg, const char *end)
++                         const uint8_t *beg, const uint8_t *end)
+ {
+   struct Curl_asn1Element oid;
+ 
+@@ -901,7 +903,7 @@ static CURLcode dumpAlgo(struct dynbuf *store,
+   param->tag = 0;
+   param->beg = param->end = end;
+   if(beg < end) {
+-    const char *p = getASN1Element(param, beg, end);
++    const uint8_t *p = getASN1Element(param, beg, end);
+     if(!p)
+       return CURLE_BAD_FUNCTION_ARGUMENT;
+   }
+@@ -972,7 +974,7 @@ static int do_pubkey(struct Curl_easy *data, int certnum, const char *algo,
+ {
+   struct Curl_asn1Element elem;
+   struct Curl_asn1Element pk;
+-  const char *p;
++  const uint8_t *p;
+ 
+   /* Generate all information records for the public key. */
+ 
+@@ -1004,7 +1006,7 @@ static int do_pubkey(struct Curl_easy *data, int certnum, const char *algo,
+     return 1;
+ 
+   if(curl_strequal(algo, "rsaEncryption")) {
+-    const char *q;
++    const uint8_t *q;
+     size_t len;
+ 
+     p = getASN1Element(&elem, pk.beg, pk.end);
+@@ -1017,7 +1019,7 @@ static int do_pubkey(struct Curl_easy *data, int certnum, const char *algo,
+     len = ((elem.end - q) * 8);
+     if(len) {
+       unsigned int i;
+-      for(i = *(const unsigned char *)q; !(i & 0x80); i <<= 1)
++      for(i = *q; !(i & 0x80); i <<= 1)
+         len--;
+     }
+     if(len > 32)
+@@ -1083,8 +1085,8 @@ static CURLcode DNtostr(struct dynbuf *store, struct Curl_asn1Element *dn)
+ 
+ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
+                                int certnum,
+-                               const char *beg,
+-                               const char *end)
++                               const uint8_t *beg,
++                               const uint8_t *end)
+ {
+   struct Curl_X509certificate cert;
+   struct Curl_asn1Element param;
+@@ -1093,7 +1095,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
+   struct dynbuf out;
+   CURLcode result = CURLE_OK;
+   unsigned int version;
+-  const char *ptr;
++  const uint8_t *ptr;
+   int rc;
+ 
+   if(!data->set.ssl.certinfo)
+@@ -1132,7 +1134,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data,
+   /* Version (always fits in less than 32 bits). */
+   version = 0;
+   for(ptr = cert.version.beg; ptr < cert.version.end; ptr++)
+-    version = (version << 8) | *(const unsigned char *)ptr;
++    version = (version << 8) | *ptr;
+   if(data->set.ssl.certinfo) {
+     result = curlx_dyn_addf(&out, "%x", version);
+     if(result)
+diff --git a/lib/vtls/x509asn1.h b/lib/vtls/x509asn1.h
+index 829dfd884f..e5374108e5 100644
+--- a/lib/vtls/x509asn1.h
++++ b/lib/vtls/x509asn1.h
+@@ -38,11 +38,11 @@
+ 
+ /* ASN.1 parsed element. */
+ struct Curl_asn1Element {
+-  const char *header;         /* Pointer to header byte. */
+-  const char *beg;            /* Pointer to element data. */
+-  const char *end;            /* Pointer to 1st byte after element. */
+-  unsigned char eclass;       /* ASN.1 element class. */
+-  unsigned char tag;          /* ASN.1 element tag. */
++  const uint8_t *header;      /* Pointer to header byte. */
++  const uint8_t *beg;         /* Pointer to element data. */
++  const uint8_t *end;         /* Pointer to 1st byte after element. */
++  uint8_t eclass;             /* ASN.1 element class. */
++  uint8_t tag;                /* ASN.1 element tag. */
+   BIT(constructed);           /* Element is constructed. */
+ };
+ 
+@@ -70,22 +70,22 @@ struct Curl_X509certificate {
+  */
+ 
+ int Curl_parseX509(struct Curl_X509certificate *cert,
+-                   const char *beg, const char *end);
++                   const uint8_t *beg, const uint8_t *end);
+ CURLcode Curl_extract_certinfo(struct Curl_easy *data, int certnum,
+-                               const char *beg, const char *end);
++                               const uint8_t *beg, const uint8_t *end);
+ CURLcode Curl_verifyhost(struct Curl_cfilter *cf, struct Curl_easy *data,
+-                         const char *beg, const char *end);
++                         const uint8_t *beg, const uint8_t *end);
+ 
+ #ifdef UNITTESTS
++const uint8_t *getASN1Element(struct Curl_asn1Element *elem,
++                              const uint8_t *beg, const uint8_t *end)
++  WARN_UNUSED_RESULT;
+ #if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_MBEDTLS) || \
+   defined(USE_RUSTLS)
+ 
+ /* used by unit1656.c */
+ CURLcode Curl_x509_GTime2str(struct dynbuf *store,
+                              const char *beg, const char *end);
+-/* used by unit1657.c */
+-CURLcode Curl_x509_getASN1Element(struct Curl_asn1Element *elem,
+-                                  const char *beg, const char *end);
+ #endif /* USE_GNUTLS || USE_SCHANNEL || USE_MBEDTLS || RUSTLS */
+ #endif /* UNITTESTS */
+ 
+diff --git a/tests/unit/unit1651.c b/tests/unit/unit1651.c
+index 10fc979724..ce8cbaedc5 100644
+--- a/tests/unit/unit1651.c
++++ b/tests/unit/unit1651.c
+@@ -33,7 +33,7 @@ static CURLcode test_unit1651(const char *arg)
+ 
+   /* cert captured from gdb when connecting to curl.se on October 26
+      2018. */
+-  static unsigned char cert[] = {
++  static uint8_t cert[] = {
+     0x30, 0x82, 0x0F, 0x5B, 0x30, 0x82, 0x0E, 0x43, 0xA0, 0x03, 0x02, 0x01,
+     0x02, 0x02, 0x0C, 0x08, 0x77, 0x99, 0x2C, 0x6B, 0x67, 0xE1, 0x18, 0xD6,
+     0x66, 0x66, 0x9E, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,
+@@ -365,8 +365,8 @@ static CURLcode test_unit1651(const char *arg)
+   };
+ 
+   CURLcode result;
+-  const char *beg = (const char *)&cert[0];
+-  const char *end = (const char *)&cert[sizeof(cert)];
++  const uint8_t *beg = &cert[0];
++  const uint8_t *end = &cert[sizeof(cert)];
+   struct Curl_easy *data;
+   int i;
+   int byte;
+diff --git a/tests/unit/unit1657.c b/tests/unit/unit1657.c
+index 7c769e78da..716df1856c 100644
+--- a/tests/unit/unit1657.c
++++ b/tests/unit/unit1657.c
+@@ -23,7 +23,8 @@
+  ***************************************************************************/
+ #include "unitcheck.h"
+ 
+-#if defined(USE_GNUTLS) || defined(USE_SCHANNEL) || defined(USE_MBEDTLS)
++#if defined(USE_GNUTLS) || defined(USE_WOLFSSL) || defined(USE_SCHANNEL) || \
++  defined(USE_MBEDTLS) || defined(USE_RUSTLS)
+ 
+ #include "vtls/x509asn1.h"
+ 
+@@ -38,8 +39,8 @@ static CURLcode make1657_nested(const struct test1657_spec *spec,
+ {
+   CURLcode result;
+   size_t i;
+-  unsigned char open_undef[] = { 0x32, 0x80 };
+-  unsigned char close_undef[] = { 0x00, 0x00 };
++  uint8_t open_undef[] = { 0x32, 0x80 };
++  uint8_t close_undef[] = { 0x00, 0x00 };
+ 
+   for(i = 0; i < spec->n; ++i) {
+     result = curlx_dyn_addn(buf, open_undef, sizeof(open_undef));
+@@ -66,7 +67,8 @@ static bool do_test1657(const struct test1657_spec *spec, size_t i,
+ {
+   CURLcode result;
+   struct Curl_asn1Element elem;
+-  const char *in;
++  const uint8_t *in;
++  const uint8_t *ptr;
+ 
+   memset(&elem, 0, sizeof(elem));
+   curlx_dyn_reset(buf);
+@@ -75,8 +77,9 @@ static bool do_test1657(const struct test1657_spec *spec, size_t i,
+     curl_mfprintf(stderr, "test %zu: error setting buf %d\n", i, result);
+     return FALSE;
+   }
+-  in = curlx_dyn_ptr(buf);
+-  result = Curl_x509_getASN1Element(&elem, in, in + curlx_dyn_len(buf));
++  in = curlx_dyn_uptr(buf);
++  ptr = getASN1Element(&elem, in, in + curlx_dyn_len(buf));
++  result = ptr ? CURLE_OK : CURLE_BAD_FUNCTION_ARGUMENT;
+   if(result != spec->result_exp) {
+     curl_mfprintf(stderr, "test %zu: expect result %d, got %d\n",
+                   i, spec->result_exp, result);
+@@ -85,6 +88,59 @@ static bool do_test1657(const struct test1657_spec *spec, size_t i,
+   return TRUE;
+ }
+ 
++struct test1657_cert_spec {
++  const char * const pem;
++  bool exp_success;
++};
++
++static const struct test1657_cert_spec test1657_certs[] = {
++  { /* a valid certificate */
++    "MIIBGTCBzKADAgECAhQ8Ssn8BaVsqlKKccv81NFuKY1vATAFBgMrZXAwADAeFw0y"
++    "NjA5MDIwNDU0MjZaFw0yNjEwMDIwNDU0MjZaMAAwKjAFBgMrZXADIQBeG0S343s9"
++    "5yRmIK8xZmGvUmiiYvRH5ZMcPq6rvHHKwqNYMFYwNQYDKgMEBC4wADAqMAUGAytl"
++    "cAMhAPP5TXSe2WHt/bebbP8eHPXrG3LNxYz8TnHNgpwTFsT7MB0GA1UdDgQWBBR6"
++    "aqL9LrZiIpgYCy0X4fNrhgFQsTAFBgMrZXADQQALU0OHGcIvfTwyin/+u9csJ9hZ"
++    "W0c+XdHJY5uDdCR1O92K4Vnozf/QCe7ITOJ8aUnCs7Jgf5xrDgyXZNdum04A",
++    TRUE
++  },
++  { /* a certificate with "validity" element that has too long length */
++    "MIIBGTCBzKADAgECAhQ8Ssn8BaVsqlKKccv81NFuKY1vATAFBgMrZXAwADBZFw0y"
++    "NjA5MDIwNDU0MjZaFw0yNjEwMDIwNDU0MjZaMAAwKjAFBgMrZXADIQBeG0S343s9"
++    "5yRmIK8xZmGvUmiiYvRH5ZMcPq6rvHHKwqNYMFYwNQYDKgMEBC4wADAqMAUGAytl"
++    "cAMhAPP5TXSe2WHt/bebbP8eHPXrG3LNxYz8TnHNgpwTFsT7MB0GA1UdDgQWBBR6"
++    "aqL9LrZiIpgYCy0X4fNrhgFQsTAFBgMrZXADQQALU0OHGcIvfTwyin/+u9csJ9hZ"
++    "W0c+XdHJY5uDdCR1O92K4Vnozf/QCe7ITOJ8aUnCs7Jgf5xrDgyXZNdum04A",
++    FALSE
++  }
++};
++
++static bool test1657_parse_cert(size_t i,
++                                const struct test1657_cert_spec *spec)
++{
++  struct Curl_X509certificate cert;
++  CURLcode result;
++  uint8_t *cert_der;
++  size_t cert_der_len;
++  bool success;
++
++  result = curlx_base64_decode(spec->pem, &cert_der, &cert_der_len);
++  if(result) {
++    curl_mfprintf(stderr, "cert %zu: base64 decoding failed: %d\n",
++                  i, (int)result);
++    return FALSE;
++  }
++
++  success = !Curl_parseX509(&cert, cert_der, cert_der +  cert_der_len);
++  if(success != spec->exp_success) {
++    curl_mfprintf(stderr, "cert %zu: parsing DER %sfailed\n", i,
++                  spec->exp_success ? "" : "should have ");
++    return FALSE;
++  }
++
++  curlx_free(cert_der);
++  return TRUE;
++}
++
+ static CURLcode test_unit1657(const char *arg)
+ {
+   UNITTEST_BEGIN_SIMPLE
+@@ -104,7 +160,14 @@ static CURLcode test_unit1657(const char *arg)
+     if(!do_test1657(&test1657_specs[i], i, &dbuf))
+       all_ok = FALSE;
+   }
+-  fail_unless(all_ok, "some tests of Curl_x509_getASN1Element() fails");
++  fail_unless(all_ok, "some getASN1Element() tests failed");
++
++  all_ok = TRUE;
++  for(i = 0; i < CURL_ARRAYSIZE(test1657_certs); ++i) {
++    if(!test1657_parse_cert(i, &test1657_certs[i]))
++      all_ok = FALSE;
++  }
++  fail_unless(all_ok, "some certificate tests failed");
+ 
+   curlx_dyn_free(&dbuf);
+   curl_global_cleanup();
+@@ -117,7 +180,7 @@ static CURLcode test_unit1657(const char *arg)
+ static CURLcode test_unit1657(const char *arg)
+ {
+   UNITTEST_BEGIN_SIMPLE
+-  puts("not tested since Curl_x509_getASN1Element() is not built in");
++  puts("not tested since getASN1Element() is not built in");
+   UNITTEST_END_SIMPLE
+ }
+ 
+-- 
+2.35.6
diff --git a/meta/recipes-support/curl/curl_8.19.0.bb b/meta/recipes-support/curl/curl_8.19.0.bb
index 026b5a3638..51479d8b6a 100644
--- a/meta/recipes-support/curl/curl_8.19.0.bb
+++ b/meta/recipes-support/curl/curl_8.19.0.bb
@@ -71,6 +71,7 @@ SRC_URI = "https://curl.se/download/${BP}.tar.xz \
            file://CVE-2026-94266_p1.patch \
            file://CVE-2026-94266_p2.patch \
            file://CVE-2026-107929.patch \
+           file://CVE-2026-87866.patch \
            "
 
 SRC_URI:append:class-nativesdk = " \
