Dev.to Security πŸ” Cybersecurity πŸ‘ 0 πŸ“– 3 min read

CVE-2026-126303: CVE-2026-126303: Uncontrolled Resource Consumption in NLTK SteppingRecursiveDescentParser

CVE-2026-126303: Uncontrolled Resource Consumption in NLTK SteppingRecursiveDescentParser Vulnerability ID: CVE-2026-126303 CVSS Score: 8.7 Published: 2026-11-13 CVE-2026-126303 (GHSA-8fx7-8jr8-84rv) is an uncontrol

CVE-2026-126303: Uncontrolled Resource Consumption in NLTK SteppingRecursiveDescentParser

Vulnerability ID: CVE-2026-126303
CVSS Score: 8.7
Published: 2026-11-13

CVE-2026-126303 (GHSA-8fx7-8jr8-84rv) is an uncontrolled resource consumption vulnerability in the Natural Language Toolkit (NLTK) prior to version 3.10.4. The flaw is located in the SteppingRecursiveDescentParser.parse() method within the nltk.parse.recursivedescent module. Because the parser executes a top-down recursive descent stepping loop without enforcing an execution time deadline or step limit, processing tokens against a left-recursive, self-embedding, or ambiguous Context-Free Grammar (CFG) causes the parser to enter an infinite loop. This results in complete CPU core exhaustion and worker thread starvation, leading to an application-level denial of service.

TL;DR

Versions of NLTK prior to 3.10.4 contain an algorithmic denial-of-service flaw in SteppingRecursiveDescentParser.parse(). The class fails to inherit or check the base parser's max_time deadline during stepwise tree expansion. Evaluating inputs against left-recursive or cyclic grammars causes an unbounded execution loop that pins CPU cores at 100% utilization.

⚠️ Exploit Status: POC

Technical Details

  • CVE / GHSA ID: CVE-2026-126303 / GHSA-8fx7-8jr8-84rv
  • Vulnerability Class: CWE-400 (Uncontrolled Resource Consumption) / CWE-407 / CWE-674
  • CVSS v4.0 Score: 8.7 High (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)
  • EPSS Score: 0.49% (42.56th Percentile)
  • Affected Component: nltk.parse.recursivedescent.SteppingRecursiveDescentParser.parse()
  • Impact: Application Denial of Service via 100% CPU core starvation and worker lockup
  • Patched Version: nltk 3.10.4
  • CISA KEV Status: Not Listed

Affected Systems

  • Natural Language Toolkit (nltk) Python package < 3.10.4
  • nltk: < 3.10.4 (Fixed in: 3.10.4)

Code Analysis

Commit: e20c40e

Bound algorithmic-DoS and uncontrolled-recursion vectors (CWE-400/407/674/1333)

diff --git a/nltk/parse/recursivedescent.py b/nltk/parse/recursivedescent.py
index 19eaaf6e19..08e9239bee 100644
--- a/nltk/parse/recursivedescent.py
+++ b/nltk/parse/recursivedescent.py
@@ -407,8 +407,8 @@ class SteppingRecursiveDescentParser(RecursiveDescentParser):
     :see: ``nltk.grammar``
     """

-    def __init__(self, grammar, trace=0):
-        super().__init__(grammar, trace)
+    def __init__(self, grammar, trace=0, max_time=DEFAULT_MAX_TIME):
+        super().__init__(grammar, trace, max_time)
         self._rtext = None
         self._tree = None
         self._frontier = [()]
@@ -428,8 +428,19 @@ def _freeze(self, tree):
     def parse(self, tokens):
         tokens = list(tokens)
         self.initialize(tokens)
+        # step() bypasses the base _parse deadline, so bound the stepping loop
+        # directly: a left-recursive or ambiguous grammar loops unbounded
+        # otherwise (CWE-407/674). max_time=None disables the bound.
+        deadline = None
+        if self._max_time is not None:
+            deadline = time.perf_counter() + self._max_time
         while self.step() is not None:
-            pass
+            if deadline is not None and time.perf_counter() > deadline:
+                raise TimeoutError(
+                    f"SteppingRecursiveDescentParser exceeded its {self._max_time}s "
+                    "time limit; the grammar may be ambiguous or left-recursive. "
+                    "Pass max_time=None to disable the limit."
+                )
         return self.parses()

     def initialize(self, tokens):

Commit: 5c41fc0

Follow-up release and test harness hardening commit for NLTK 3.10.4

Exploit Details

  • GitHub Advisory: Official GitHub Security Advisory detailing the unbounded stepping loop in SteppingRecursiveDescentParser.parse().
  • GitHub Pull Request: Pull Request #3895 containing regression tests and proof-of-concept inputs demonstrating algorithmic DoS in SteppingRecursiveDescentParser.

Mitigation Strategies

  • Upgrade the NLTK library to version 3.10.4 or later to enforce default wall-clock deadlines on SteppingRecursiveDescentParser.parse().
  • Replace SteppingRecursiveDescentParser and RecursiveDescentParser in production services with polynomial-time chart parsers such as nltk.parse.EarleyChartParser or nltk.parse.ChartParser.
  • Restrict or validate user-supplied Context-Free Grammar (CFG) definitions to reject direct and indirect left-recursive production rules prior to parsing.
  • Isolate CPU-intensive NLP parsing tasks inside dedicated worker processes configured with strict OS-level execution timeouts.

Remediation Steps:

  1. Update dependency manifests (requirements.txt, pyproject.toml, Pipfile) to require nltk>=3.10.4.
  2. Run 'pip install --upgrade "nltk>=3.10.4"' across all affected virtual environments and container images.
  3. Audit application code for calls to SteppingRecursiveDescentParser.parse() and ensure explicit max_time values are appropriate for the service's latency budget (do not pass max_time=None on untrusted inputs).
  4. Wrap parser.parse() invocations in try/except blocks that catch TimeoutError and RecursionError to prevent unhandled exceptions from terminating application workers.

References

Read the full report for CVE-2026-126303 on our website for more details including interactive diagrams and full exploit analysis.

πŸ“° Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.