CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-85730

CVE-2026-85730: Infinite Loop Denial of Service in smol-toml Parser

Amit Schendel
Amit Schendel
Senior Security Researcher

Sep 9, 2026·7 min read·55 visits

Executive Summary (TL;DR)

A 5-byte malformed TOML payload can block the single-threaded Node.js event loop indefinitely, causing 100% CPU utilization and Denial of Service.

Prior to version 1.7.1, smol-toml is vulnerable to an infinite loop Denial of Service when parsing a malformed TOML payload containing an unclosed comment inside an array or inline table.

Vulnerability Overview

The vulnerability CVE-2026-85730 is a critical Denial of Service (DoS) flaw within the smol-toml Node.js library, a performance-focused parser and serializer for the TOML format. It stems from an algorithmic flaw in how the parser skips whitespace and comments when analyzing nested structures such as arrays or inline tables. Unauthenticated remote attackers can leverage this flaw to cause a permanent Denial of Service by submitting highly compact, malformed payloads.

The vulnerability represents an "Infinite Loop" weakness categorized under CWE-835 and CWE-606. When processing untrusted inputs containing specific structural anomalies, the parsing utility fails to recognize the End-of-File (EOF) boundary and continually cycles over the same block of data. Because the Node.js runtime employs a single-threaded event loop, this continuous CPU utilization completely starves other asynchronous processes, disabling the server's capability to process concurrent requests.

The attack surface resides in any exposed application endpoint that accepts TOML payloads and parses them using the default parse interface of smol-toml. This makes microservices, configuration endpoints, and ingestion pipelines primary targets. Given that the minimum payload required to trigger this state is merely five bytes, the processing footprint of the attack is negligible while the impact is absolute for the affected thread.

Root Cause Analysis

The core of the vulnerability is found within the character-skipping routine skipUntil located in src/util.ts. This utility function is designed to scan through strings, ignoring non-structural tokens and comments, until a target separator or boundary character is encountered. In the case of arrays, the parser looks for separators like commas or the terminating bracket, while bypassing nested comments marked by the hash symbol (#).

During execution on a malformed payload like a=[1#, the pointer is positioned on the hash character at the end of the string. The function encounters the # and attempts to skip past the comment by identifying the next newline character. To do this, it calls the internal utility helper indexOfNewline(str, i). Under normal conditions, this returns the index of the next newline, allowing the loop to skip the comment block entirely and resume parsing on the following line.

When the input document abruptly terminates with a comment and contains no trailing newline, the indexOfNewline function fails to match any newline character. Consequently, it returns -1 to signal the failure. The parser directly assigns this return value to the loop index variable i. Since -1 is less than the current index, the pointer is unexpectedly warped backward to the beginning of the file.

The structure of the loop depends on standard iteration mechanics, applying the post-iteration update expression i++ once the loop block finishes. This increments the index i from -1 to 0. During the next iteration check, the condition i < str.length evaluates to true, causing the parser to restart scanning from index 0. This loop repeats indefinitely, continuously scanning the same string from the beginning, finding the same comment, warping back to -1, and incrementing back to 0 as shown in the following visual pipeline:

Code Analysis

The following comparison demonstrates the exact loop-handling flaw before and after the application of the official security patch.

// Vulnerable Code (prior to v1.7.1)
export function skipUntil(str: string, ptr: number, sep: string, end?: string, banNewLines: boolean = false) {
    if (!end) {
        ptr = indexOfNewline(str, ptr)
    }
    for (let i = ptr; i < str.length; i++) {
        let c = str[i]
        if (c === '#') {
            // Vulnerability: No validation of the returned index is performed.
            // If no newline character exists, indexOfNewline returns -1.
            i = indexOfNewline(str, i) 
        } else if (c === sep) {
            return i + 1
        } else if (c === end || (banNewLines && (c === '\n' || (c === '\r' && str[i + 1] === '\n')))) {
            return i
        }
    }
    return str.length
}

In the unpatched code shown above, the return value of indexOfNewline(str, i) is blindly assigned to i. When the search fails, i becomes -1. The loop's step mechanism then increments i to 0 before evaluating i < str.length. Because the string length is greater than zero, the iteration condition is satisfied, and the engine begins scanning from the start of the string again.

To resolve this execution logic defect, the patch introduces immediate evaluation of the search outcome.

// Patched Code (v1.7.1)
export function skipUntil(str: string, ptr: number, sep: string, end?: string, banNewLines: boolean = false) {
    if (!end) {
        ptr = indexOfNewline(str, ptr)
    }
    for (let i = ptr; i < str.length; i++) {
        let c = str[i]
        if (c === '#') {
            i = indexOfNewline(str, i)
            // Security Fix: Break out of the loop immediately if no newline is found
            if (i < 0) break
        } else if (c === sep) {
            return i + 1
        } else if (c === end || (banNewLines && (c === '\n' || (c === '\r' && str[i + 1] === '\n')))) {
            return i
        }
    }
    return str.length
}

The check if (i < 0) break successfully prevents the negative assignment from being incremented and re-evaluated inside the iteration block. Breaking out of the loop allows the function to execute return str.length, accurately marking the end-of-file condition and terminating the parsing execution pathway.

Exploitation Methodology

Exploitation of CVE-2026-85730 requires very little effort. The attack relies on an architectural asymmetry where an incredibly small payload can lead to complete service exhaustion. The prerequisite is that the target Node.js application must ingest untrusted TOML configurations or raw input payloads and process them using the parse method of smol-toml.

An attacker constructs a request payload containing an unclosed array or table with an unclosed inline comment block. Two common variations are available to trigger this state:

# Variant 1: Unclosed Array Payload (5 bytes)
a=[1#
 
# Variant 2: Unclosed Inline Table Payload (7 bytes)
a={k=1#

Once received by the application, the library attempts to find the end-of-comment indicator. Failing to locate a newline character, the execution loop is permanently trapped in a cycle of reset iterations. In a standard single-threaded Node.js deployment, this immediately freezes the main event loop, preventing the application from handling concurrent requests or system heartbeats.

Impact Assessment

The structural failure inside smol-toml results in an immediate loss of service availability. Although there is no risk of remote code execution or data exposure, the absolute exhaustion of resources makes the impact of this vulnerability substantial. This vulnerability receives a CVSS v4.0 Base Score of 8.2.

Because Node.js runs on a single thread, any operation that forces an infinite loop blocks the event queue entirely. Consequently, even if a service employs multiple CPUs, a simple series of malicious requests corresponding to the number of server processes can completely paralyze the infrastructure.

Furthermore, because the exploitation payload is small, detecting the attack based on input size filters is impractical. This enables actors to bypass traditional packet size limits easily, stressing the necessity of patching underlying parser utilities.

Remediation and Mitigation

The primary recommendation is to update the smol-toml dependency to version 1.7.1 or higher. This update resolves the execution logic bug by checking for negative index results and terminating the loop immediately.

When immediate library upgrades are not feasible, you can employ temporary mitigations. Implementing a Web Application Firewall (WAF) rule to block incoming request bodies containing specific malformed TOML structures can block exploit attempts. For example, rules can check for the presence of # inside brackets without a trailing newline character.

Deploying application processes under robust cluster managers or container environments with active liveness probes can minimize downtime. If the event loop freezes, a container orchestrator will fail its health checks and restart the container automatically, mitigating prolonged denial of service states.

Official Patches

squirrelchatFix commit for infinite loop on unclosed comments

Fix Analysis (1)

Technical Appendix

CVSS Score
8.2/ 10
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
EPSS Probability
0.37%
Top 70% most exploited

Affected Systems

smol-toml

Affected Versions Detail

Product
Affected Versions
Fixed Version
smol-toml
squirrelchat
< 1.7.11.7.1
AttributeDetail
Vulnerability IDCVE-2026-85730
CWE IDCWE-835 / CWE-606
CVSS v4.08.2 (High)
Attack VectorNetwork (AV:N)
Exploit StatusProof of Concept (PoC)
CISA KEV ListedNo
Affected Ecosystemnpm (Node.js)

MITRE ATT&CK Mapping

T1499.004Endpoint Denial of Service: Application Exhaustion
Impact
CWE-835
Loop with Unreachable Exit Condition ('Infinite Loop')

The program contains an iteration loop for which the exit condition is never met, causing execution to continue indefinitely.

Known Exploits & Detection

Medium Write-upSeven Bytes That Freeze a Node.js Server Forever : The Story of CVE-2026-85730

Vulnerability Timeline

Maintainer commits security patch and releases version 1.7.1
2026-07-26
Vulnerability officially published via GitHub Security Advisory GHSA-7w5x-hrqm-74c2
2026-09-04
Technical analysis write-up published by researcher
2026-09-05
NVD registers and analyzes the vulnerability
2026-09-09

References & Sources

  • [1]GitHub Security Advisory GHSA-7w5x-hrqm-74c2
  • [2]Official Patch Commit
  • [3]v1.7.1 Release Notes
  • [4]Medium Article by Ravindu Lakmina Munaweera
  • [5]NVD Vulnerability Details

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•about 22 hours ago•CVE-2026-107844
5.3

CVE-2026-107844: Path Traversal Vulnerability in Contao ImagesController

A path traversal vulnerability (CWE-22) in Contao CMS allows unauthenticated remote attackers to bypass directory boundary restrictions in ImagesController and access files within the project directory.

Amit Schendel
Amit Schendel
8 views•5 min read
•about 24 hours ago•CVE-2026-107848
3.5

CVE-2026-107848: Cross-Site Request Forgery (CSRF) in Contao Backend Actions via GET Requests

Contao Open Source CMS versions 4.0.0 through 5.3.49 and 5.4.0-RC1 through 5.7.11 contain a Cross-Site Request Forgery (CSRF) vulnerability in backend parameter handling. The `RequestTokenListener` component validates anti-CSRF tokens solely for HTTP POST requests, while GET-based declarative guards run only when an `act` parameter is present in the query string. Consequently, custom backend actions dispatched via alternative parameters such as `key=` can execute without CSRF token verification when triggered by an authenticated user.

Amit Schendel
Amit Schendel
7 views•5 min read
•1 day ago•CVE-2026-107843
5.3

CVE-2026-107843: Unthrottled Activation Email Resend and Account Enumeration in Contao CMS

Contao CMS versions 4.1.0 through 5.3.49 and 5.4.0-RC1 through 5.7.11 fail to validate form submission tokens and enforce rate limiting when processing activation email resend requests via HTTP POST, enabling resource exhaustion and account state enumeration.

Amit Schendel
Amit Schendel
8 views•4 min read
•1 day ago•CVE-2026-107842
5.3

CVE-2026-107842: Information Disclosure via Stale Indexing in Contao Search Module

An information disclosure vulnerability in Contao CMS allows unauthenticated site visitors to view protected page titles, URLs, and text excerpts through search queries when protected page indexing is disabled after previously being enabled.

Amit Schendel
Amit Schendel
10 views•4 min read
•1 day ago•GHSA-G38J-7V97-X298
6.5

GHSA-G38J-7V97-X298: Missing Authorization Check in Vikunja CalDAV Task Relation Creation

In Vikunja prior to version 2.6.0, relation creation via the CalDAV endpoint fails to invoke the TaskRelation.CanCreate authorization check. This missing access control allows an authenticated user to establish unauthorized relationships and perform write operations against any task, provided its unique identifier (UID) is known.

Alon Barad
Alon Barad
12 views•5 min read
•1 day ago•GHSA-3HC7-R24J-RPWC
6.8

GHSA-3hc7-r24j-rpwc: Cross-Project Task Disclosure via Subtask Expansion in Vikunja

A cross-project information disclosure vulnerability in Vikunja allows authenticated users with read access to one project to view private task details from unauthorized projects via subtask expansion parameters.

Alon Barad
Alon Barad
9 views•5 min read