new file mode 100644
@@ -0,0 +1,203 @@
+From 08d50a791b3197a3d0a4fc2f778e243f5501c67e Mon Sep 17 00:00:00 2001
+From: Daniel Stenberg <daniel@haxx.se>
+Date: Tue, 8 Sep 2026 16:04:42 +0200
+Subject: [PATCH] hsts: cap max-age to two years
+
+And ignore problems saving individual HSTS entries - a single entry
+problem should not affect storing other entries.
+
+Added test 1862 to verify.
+
+Closes #22878
+
+CVE: CVE-2026-87863
+Upstream-Status: Backport [https://github.com/curl/curl/commit/08d50a791b3197a3d0a4fc2f778e243f5501c67e]
+
+Backport Changes:
+- Keep curl 8.19.0's max-age parser, which reads directly from the
+ header using TIME_T_MAX as its numeric limit. Upstream first
+ extracts the value and parses it with a two-year numeric limit.
+ Cap parsed ages and numeric overflows at two years.
+- After overflow in a quoted age, skip its digits before checking
+ the closing quote. The older number reader leaves its position
+ unchanged on overflow. For unquoted overflow, keep that position
+ so trailing text is handled as before.
+- Register test1862 in the older grouped tests/data/Makefile.am list.
+
+Signed-off-by: Darsh Kelaiya <dkelaiya@cisco.com>
+---
+ lib/hsts.c | 32 ++++++++++--------
+ tests/data/Makefile.am | 2 +-
+ tests/data/test1862 | 73 ++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 93 insertions(+), 14 deletions(-)
+ create mode 100644 tests/data/test1862
+
+diff --git a/lib/hsts.c b/lib/hsts.c
+index 5ad5bd4..9e5b456 100644
+--- a/lib/hsts.c
++++ b/lib/hsts.c
+@@ -43,6 +43,8 @@
+ #define MAX_HSTS_DATELEN 256
+ #define UNLIMITED "unlimited"
+
++#define CAP_HSTS_MAX_AGE (2*365*24*3600) /* two years cap */
++
+ #if defined(DEBUGBUILD) || defined(UNITTESTS)
+ /* to play well with debug builds, we can *set* a fixed time this will
+ return */
+@@ -152,11 +154,18 @@ CURLcode Curl_hsts_parse(struct hsts *h, const char *hostname,
+ quoted = TRUE;
+
+ rc = curlx_str_number(&p, &expires, TIME_T_MAX);
+- if(rc == STRE_OVERFLOW)
+- expires = CURL_OFF_T_MAX;
++ if(rc == STRE_OVERFLOW) {
++ expires = CAP_HSTS_MAX_AGE;
++ if(quoted) {
++ while(ISDIGIT(*p))
++ p++;
++ }
++ }
+ else if(rc)
+ /* invalid max-age */
+ return CURLE_BAD_FUNCTION_ARGUMENT;
++ else if(expires > CAP_HSTS_MAX_AGE)
++ expires = CAP_HSTS_MAX_AGE;
+
+ if(quoted) {
+ if(*p != '\"')
+@@ -304,22 +313,21 @@ static CURLcode hsts_push(struct Curl_easy *data,
+ /*
+ * Write this single hsts entry to a single output line
+ */
+-static CURLcode hsts_out(struct stsentry *sts, FILE *fp)
++static void hsts_out(struct stsentry *sts, FILE *fp)
+ {
+ struct tm stamp;
+ if(sts->expires != TIME_T_MAX) {
+ CURLcode result = curlx_gmtime((time_t)sts->expires, &stamp);
+- if(result)
+- return result;
+- curl_mfprintf(fp, "%s%s \"%d%02d%02d %02d:%02d:%02d\"\n",
+- sts->includeSubDomains ? "." : "", sts->host,
+- stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday,
+- stamp.tm_hour, stamp.tm_min, stamp.tm_sec);
++ if(!result)
++ /* skip the entry if the date function fails */
++ curl_mfprintf(fp, "%s%s \"%d%02d%02d %02d:%02d:%02d\"\n",
++ sts->includeSubDomains ? "." : "", sts->host,
++ stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday,
++ stamp.tm_hour, stamp.tm_min, stamp.tm_sec);
+ }
+ else
+ curl_mfprintf(fp, "%s%s \"%s\"\n",
+ sts->includeSubDomains ? "." : "", sts->host, UNLIMITED);
+- return CURLE_OK;
+ }
+
+ /*
+@@ -354,9 +362,7 @@ CURLcode Curl_hsts_save(struct Curl_easy *data, struct hsts *h,
+ for(e = Curl_llist_head(&h->list); e; e = n) {
+ struct stsentry *sts = Curl_node_elem(e);
+ n = Curl_node_next(e);
+- result = hsts_out(sts, out);
+- if(result)
+- break;
++ hsts_out(sts, out);
+ }
+ curlx_fclose(out);
+ if(!result && tempstore && curlx_rename(tempstore, file))
+diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
+index 7a9b8d0..e678290 100644
+--- a/tests/data/Makefile.am
++++ b/tests/data/Makefile.am
+@@ -231,7 +231,7 @@ test1680 test1681 test1682 test1683 test1685 \
+ test1700 test1701 test1702 test1703 test1704 test1705 test1706 test1707 \
+ test1708 test1709 test1710 test1711 test1712 \
+ \
+-test1800 test1801 test1802 test1847 test1848 test1849 test1850 \
++test1800 test1801 test1802 test1847 test1848 test1849 test1850 test1862 \
+ \
+ test1900 test1901 test1902 test1903 test1904 test1905 test1906 test1907 \
+ test1908 test1909 test1910 test1911 test1912 test1913 test1914 test1915 \
+diff --git a/tests/data/test1862 b/tests/data/test1862
+new file mode 100644
+index 0000000..b9a29f6
+--- /dev/null
++++ b/tests/data/test1862
+@@ -0,0 +1,73 @@
++<?xml version="1.0" encoding="US-ASCII"?>
++<testcase>
++<info>
++<keywords>
++HTTP
++HSTS
++</keywords>
++</info>
++
++<reply>
++
++<data crlf="headers" nocheck="yes">
++HTTP/1.1 200 OK
++Date: Tue, 09 Nov 2010 14:49:00 GMT
++Content-Length: 6
++Connection: close
++Strict-Transport-Security: max-age=1152921504606846976
++
++-foo-
++</data>
++</reply>
++
++<client>
++<server>
++http
++</server>
++<features>
++HSTS
++Debug
++</features>
++
++# November 11, 2030
++<setenv>
++CURL_HSTS_HTTP=yes
++CURL_TIME=1920582000
++</setenv>
++
++<name>
++HSTS with extreme max-age
++</name>
++<command>
++http://this.hsts.example:%HTTPPORT/%TESTNUMBER --hsts %LOGDIR/input%TESTNUMBER --resolve this.hsts.example:%HTTPPORT:%HOSTIP
++</command>
++<file name="%LOGDIR/input%TESTNUMBER">
++# Your HSTS cache. https://curl.se/docs/hsts.html
++# This file was generated by libcurl! Edit at your own risk.
++somehere.example "20330525 03:33:20"
++elsewhere.example.com "20330727 03:33:20"
++</file>
++<disable>
++test-duphandle
++</disable>
++</client>
++
++<verify>
++# we let it CONNECT to the server to confirm HSTS but deny from there
++<protocol crlf="headers">
++GET /1862 HTTP/1.1
++Host: this.hsts.example:%HTTPPORT
++User-Agent: curl/%VERSION
++Accept: */*
++
++</protocol>
++<file name="%LOGDIR/input%TESTNUMBER" mode="text">
++# Your HSTS cache. https://curl.se/docs/hsts.html
++# This file was generated by libcurl! Edit at your own risk.
++somehere.example "20330525 03:33:20"
++elsewhere.example.com "20330727 03:33:20"
++this.hsts.example "20321109 23:00:00"
++</file>
++
++</verify>
++</testcase>
+--
+2.35.6
@@ -61,6 +61,7 @@ SRC_URI = "https://curl.se/download/${BP}.tar.xz \
file://CVE-2026-87865_p1.patch \
file://CVE-2026-87865_p2.patch \
file://CVE-2026-92391.patch \
+ file://CVE-2026-87863.patch \
"
SRC_URI:append:class-nativesdk = " \