Cloudanix VulnDB

CVE-2026-3644

High · 7.5

CVSS

7.5

EPSS

0.5%

Published

Mar 16, 2026

CISA due date

—

Cloudanix analysis

Next patch cycle SSVC: Track

Some Python web applications may accidentally let attackers tamper with browser cookies if they build those cookies from unsafe user input.

Exploitation
Remote Authenticated
Attacker needs
Low Privilege
Complexity
Moderate
Impact
Data Tampering
Component
Library
Class
Improper Input Validation
Remediation
Upgrade
Effort
Medium
Patch risk
Low

What it actually does

This vulnerability is an incomplete input-validation fix in Python's standard-library http.cookies implementation. Control characters that were rejected in some http.cookies.Morsel paths can still be introduced through Morsel.update(), the Morsel union/update operator, and unpickling. BaseCookie.js_output() also lacks the output validation applied to BaseCookie.output(). If an application lets attacker-controlled data influence cookie names, values, or attributes through these paths, the library may emit malformed cookie output containing control characters such as carriage return or line feed. In practical terms, this can enable HTTP header injection, response-splitting behavior, cookie manipulation, or unsafe JavaScript cookie output depending on how the application uses the affected APIs.

Why it matters to the business

Applications using affected Python versions to generate cookies from user-influenced data may expose users to session manipulation, forced cookie changes, cache poisoning, or response tampering. The issue is not currently listed in CISA KEV, has low EPSS activity, and has no reported public exploit maturity, but it affects a widely used core language library, so exposure can be broad in Python-based web services and downstream frameworks that rely on http.cookies behavior.

How an attack unfolds

An attacker first needs to reach application functionality where cookie content or cookie attributes are derived from data they can influence, typically through an authenticated workflow, submitted profile data, preference values, redirect state, or another application parameter. The attacker supplies a crafted value containing control characters, most importantly CR/LF sequences, and relies on the application or a dependent library to place that value into a Morsel through one of the incompletely patched paths such as Morsel.update(), the |= operator, or deserialization of a Morsel-like object. When the application later serializes the cookie, especially through BaseCookie.js_output() or an affected output path, the control characters may be preserved rather than rejected. The resulting response can cause downstream clients, proxies, or browsers to interpret attacker-controlled content as additional headers, altered Set-Cookie directives, or unsafe script output. Successful exploitation depends on the application exposing one of these paths to attacker-influenced input and on how the emitted cookie output is consumed by clients or intermediaries.

How to fix it

Apply the Python security update from the operating-system, container-base-image, or language-runtime vendor once available for the affected Python release line. No exact fixed versions were provided in the input, so track the relevant Python advisory and vendor package channels for the complete fix to CVE-2026-3644. Where immediate upgrade is not possible, mitigate by ensuring application code never passes untrusted data directly into http.cookies.Morsel fields, Morsel.update(), cookie merge operations, unpickled cookie objects, or BaseCookie.js_output(). Reject or encode ASCII control characters in all cookie names, values, and attributes before they reach cookie-generation code. Avoid unpickling untrusted data entirely. Prefer framework cookie APIs that perform strict validation and output encoding, and add defensive tests that verify CR, LF, NUL, and other control characters are rejected in every cookie construction path.

How to confirm the fix worked

Confirm the runtime Python package has been updated to a vendor build containing the complete fix, not only the earlier CVE-2026-0672 fix. Inventory Python runtimes in hosts, containers, virtual environments, serverless functions, and packaged applications, then compare against the vendor advisory for the installed release line. Review code and dependency usage for http.cookies.Morsel.update(), Morsel |= operations, pickle.loads or pickle.load of cookie-related data, and BaseCookie.js_output(). Add regression tests that attempt to set cookie values and attributes containing \r, \n, \x00, and other control characters through Morsel.update(), union/update operators, unpickling if applicable, BaseCookie.output(), and BaseCookie.js_output(); the fixed or mitigated behavior should reject or safely encode those values and must not emit embedded control characters in response headers or script output. For running services, send safe test requests containing URL-encoded CR/LF sequences to non-production instances and verify no injected headers or malformed Set-Cookie output are returned.

Typical attack path

  1. Identify a Python-based web application or service that generates cookies using the standard-library http.cookies module.
  2. Find an input path where attacker-controlled data is incorporated into cookie names, values, attributes, or serialized cookie state.
  3. Submit a crafted value containing control characters such as carriage return and line feed, often encoded as %0d%0a or represented as raw CR/LF characters.
  4. Trigger application logic that updates a Morsel through Morsel.update(), the |= operator, unpickling, or a code path that later calls BaseCookie.js_output().
  5. Cause the application to emit a malformed Set-Cookie header or JavaScript cookie output containing the injected control characters.
  6. Abuse the interpreted response to manipulate cookies, inject additional headers, influence caching behavior, or tamper with client-side handling.

How to detect it

Look for evidence of attempted CR/LF or control-character injection into inputs that influence cookies. Relevant log sources include web server access logs, reverse-proxy logs, WAF events, application request logs, application error logs, HTTP response capture logs if available, and endpoint telemetry showing Python application behavior. Search requests for URL-encoded carriage return and line feed sequences in query strings, form bodies, JSON fields, Cookie headers, and parameters that are later used to set preferences, sessions, redirects, localization, theme settings, or other cookie-backed state. Review responses for anomalous Set-Cookie headers, multiple unexpected Set-Cookie headers, headers containing user-supplied values, or malformed response-header parsing by proxies. In code-aware telemetry, prioritize findings where suspicious requests coincide with use of http.cookies.Morsel.update(), BaseCookie.js_output(), cookie deserialization, or pickled cookie-like state. Also investigate downstream symptoms such as unexpected session changes, unusual cookie names, cache anomalies, or browser-side script errors following requests containing %0d or %0a. There are no known named threat actors, KEV activity, or public exploitation indicators provided, so detection should focus on behavior and malformed input/output artifacts rather than campaign-specific infrastructure.

  • %0d%0aSet-Cookie:
  • %0D%0ASet-Cookie:
  • %0d%0aLocation:
  • %0D%0ALocation:
  • %0d%0aContent-Length:
  • %0D%0AContent-Length:
  • %0d%0aContent-Type:
  • %0D%0AContent-Type:
  • \r\nSet-Cookie:
  • \r\nLocation:
  • \r\nContent-Length:
  • \r\nContent-Type:
  • Morsel.update(
  • BaseCookie.js_output(
  • pickle.loads(
  • pickle.load(

What your security team should do

  • Prioritize inventory of externally exposed Python web applications and APIs that set cookies based on user-controlled input.
  • Patch Python runtimes through official vendor channels as soon as fixed packages are available for the deployed release lines.
  • Search application code for direct use of http.cookies, especially Morsel.update(), Morsel merge/update operators, BaseCookie.js_output(), and pickle handling of cookie-related objects.
  • Add centralized validation that rejects all ASCII control characters in cookie names, values, and attributes before cookie serialization.
  • Block or alert on requests containing CR/LF encodings in parameters commonly reflected into cookies, such as %0d, %0a, %0D, and %0A.
  • Review WAF, reverse-proxy, and application logs for prior attempts to inject CR/LF sequences into cookie-related parameters or headers.
  • Treat any untrusted pickle usage as a separate high-risk design issue and remove it where possible.
  • Because EPSS is currently low, no KEV listing exists, and exploit maturity is reported as none, schedule remediation based on exposure: internet-facing and authentication/session-related services first.

The record

The fix for CVE-2026-0672, which rejected control characters in http.cookies.Morsel, was incomplete. The Morsel.update(), |= operator, and unpickling paths were not patched, allowing control characters to bypass input validation. Additionally, BaseCookie.js_output() lacked the output validation applied to BaseCookie.output().

Affected packages

Ecosystem Package Introduced Fixed
Chainguard python-3.13 0 3.13.12-r7
Chainguard python-3.14 0 3.14.3-r6
SUSE:Linux Enterprise High Performance Computing 15 SP4-ESPOS python310 0 3.10.20-150400.4.107.1
SUSE:Linux Enterprise High Performance Computing 15 SP4-ESPOS python310-core 0 3.10.20-150400.4.107.1
SUSE:Linux Enterprise High Performance Computing 15 SP4-LTSS python310 0 3.10.20-150400.4.107.1
SUSE:Linux Enterprise High Performance Computing 15 SP4-LTSS python310-core 0 3.10.20-150400.4.107.1
SUSE:Linux Enterprise Module for Basesystem 15 SP7 python311-core 0 3.11.15-150600.3.53.1
SUSE:Linux Enterprise Module for Package Hub 15 SP7 python 0 2.7.18-150000.111.1
SUSE:Linux Enterprise Module for Package Hub 15 SP7 python-base 0 2.7.18-150000.111.1
SUSE:Linux Enterprise Module for Python 3 15 SP7 python311 0 3.11.15-150600.3.53.1
SUSE:Linux Enterprise Module for Python 3 15 SP7 python311-core 0 3.11.15-150600.3.53.1
SUSE:Linux Enterprise Server 15 SP4-LTSS python310 0 3.10.20-150400.4.107.1
SUSE:Linux Enterprise Server 15 SP4-LTSS python310-core 0 3.10.20-150400.4.107.1
SUSE:Linux Enterprise Server 15 SP5-LTSS python39 0 3.9.25-150300.4.99.1
SUSE:Linux Enterprise Server 15 SP5-LTSS python39-core 0 3.9.25-150300.4.99.1
SUSE:Linux Enterprise Server 15 SP6-LTSS python311 0 3.11.15-150600.3.53.1
SUSE:Linux Enterprise Server 15 SP6-LTSS python311-core 0 3.11.15-150600.3.53.1
SUSE:Linux Enterprise Server 15 SP6-LTSS python312 0 3.12.13-150600.3.53.1
SUSE:Linux Enterprise Server 15 SP6-LTSS python312-core 0 3.12.13-150600.3.53.1
SUSE:Linux Enterprise Server for SAP Applications 15 SP4 python310 0 3.10.20-150400.4.107.1
SUSE:Linux Enterprise Server for SAP Applications 15 SP4 python310-core 0 3.10.20-150400.4.107.1
SUSE:Linux Enterprise Server for SAP Applications 15 SP5 python39 0 3.9.25-150300.4.99.1
SUSE:Linux Enterprise Server for SAP Applications 15 SP5 python39-core 0 3.9.25-150300.4.99.1
SUSE:Linux Enterprise Server for SAP Applications 15 SP6 python311 0 3.11.15-150600.3.53.1
SUSE:Linux Enterprise Server for SAP Applications 15 SP6 python311-core 0 3.11.15-150600.3.53.1
SUSE:Linux Enterprise Server for SAP Applications 15 SP6 python312 0 3.12.13-150600.3.53.1
SUSE:Linux Enterprise Server for SAP Applications 15 SP6 python312-core 0 3.12.13-150600.3.53.1
Wolfi python-3.13 0 3.13.12-r7
Wolfi python-3.14 0 3.14.3-r6
openSUSE:Leap 15.6 python 0 2.7.18-150000.111.1
openSUSE:Leap 15.6 python-base 0 2.7.18-150000.111.1
openSUSE:Leap 15.6 python-doc 0 2.7.18-150000.111.1
openSUSE:Leap 15.6 python310 0 3.10.20-150400.4.107.1
openSUSE:Leap 15.6 python310-core 0 3.10.20-150400.4.107.1
openSUSE:Leap 15.6 python310-documentation 0 3.10.20-150400.4.107.1
openSUSE:Leap 15.6 python311 0 3.11.15-150600.3.53.1
openSUSE:Leap 15.6 python311-core 0 3.11.15-150600.3.53.1
openSUSE:Leap 15.6 python311-documentation 0 3.11.15-150600.3.53.1
openSUSE:Leap 15.6 python312 0 3.12.13-150600.3.53.1
openSUSE:Leap 15.6 python312-core 0 3.12.13-150600.3.53.1
openSUSE:Leap 15.6 python312-documentation 0 3.12.13-150600.3.53.1
openSUSE:Leap 15.6 python39 0 3.9.25-150300.4.99.1
openSUSE:Leap 15.6 python39-core 0 3.9.25-150300.4.99.1
openSUSE:Leap 15.6 python39-documentation 0 3.9.25-150300.4.99.1
openSUSE:Leap 16.0 python313 0 3.13.13-160000.1.1
openSUSE:Leap 16.0 python313-core 0 3.13.13-160000.1.1
openSUSE:Leap 16.0 python313-documentation 0 3.13.13-160000.1.1
openSUSE:Leap 16.0 python313-nogil 0 3.13.13-160000.1.1
openSUSE:Leap 16.0 python313-nogil-nogil-core 0 3.13.13-160000.1.1
openSUSE:Tumbleweed python310 0 3.10.20-3.1
openSUSE:Tumbleweed python311 0 3.11.15-4.1
openSUSE:Tumbleweed python312 0 3.12.13-4.1
openSUSE:Tumbleweed python313 0 3.13.12-3.1
openSUSE:Tumbleweed python314 0 3.14.3-4.1
openSUSE:Tumbleweed python315 0 3.15.0~a7-3.1

Related vulnerabilities