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



GHSA-2X79-GWQ3-VXXM

GHSA-2x79-gwq3-vxxm: Infinite Loop Denial of Service in facil.io and iodine JSON Parser

Amit Schendel
Amit Schendel
Senior Security Researcher

Apr 15, 2026·6 min read·11 visits

Executive Summary (TL;DR)

A flaw in the JSON parser of facil.io and iodine causes an infinite loop when parsing malformed numerals starting with 'i' or 'I'. This allows unauthenticated remote attackers to exhaust CPU resources and cause a severe denial of service.

An uncontrolled resource consumption vulnerability in the facil.io C framework and the iodine Ruby gem allows remote attackers to cause a Denial of Service (DoS). The vulnerability is triggered by parsing crafted JSON payloads containing malformed numeral values, resulting in an infinite loop that exhausts CPU resources.

Vulnerability Overview

The vulnerability is located within the fio_json_parse function defined in the fio_json_parser.h header file. This parser functions as the core JSON processing unit for the facil.io C framework, which is designed for high-performance networking applications. The iodine Ruby gem heavily relies on this vendored parser for handling JSON operations in HTTP and WebSocket contexts.

The flaw represents a classic CWE-835: Loop with Unreachable Exit Condition ('Infinite Loop'). When the JSON parser encounters specific malformed inputs, the internal state machine fails to advance the read cursor. The parser continuously attempts to evaluate the same byte sequence without making forward progress or transitioning to an error state.

Attackers exploit this behavior by submitting crafted JSON payloads containing nested structures combined with bare characters like i or I. Because the framework operates as an asynchronous event loop, triggering this infinite loop inside the single-threaded parsing process locks the executing core, rendering the process incapable of handling further requests.

Root Cause Analysis

The root cause originates in the numeral parsing logic implemented between lines 434 and 468 of lib/facil/fiobj/fio_json_parser.h. The parser utilizes an internal state machine to process JSON tokens sequentially. When the parser operates inside an array or object context and identifies a character starting a new value, it checks whether the sequence represents a numerical input.

Upon encountering the characters i or I—often used in systems to denote inf or Infinity—the parser state machine jumps to the numeral: label. At this stage, the parser invokes the fio_atol function, passing a double pointer (char **)&tmp to attempt standard integer conversion. The fio_atol function relies on standard numerical characters to consume the buffer.

When fio_atol processes a bare i character, it successfully consumes zero characters and returns immediately. Crucially, the pointer tmp remains equal to the original position pointer pos. Following this operation, the parser evaluates the condition if (!tmp || JSON_NUMERAL[*tmp]). The lookup table JSON_NUMERAL['i'] evaluates to false (0), bypassing the failure detection branch.

Because the failure branch is bypassed, the parser erroneously concludes that a valid numeric sequence was processed. It executes pos = tmp, updating the main parser position to the exact same memory location it started at. Since the parsing depth remains greater than zero and the end of the buffer has not been reached, the outer while loop restarts, immediately encountering the same i character and repeating the cycle infinitely.

Code Analysis

Analyzing the source code reveals the structural oversight in pointer validation. The vulnerable logic implicitly trusts that the underlying conversion functions (fio_atol and fio_atof) will either advance the memory pointer upon success or that the subsequent character lookup (JSON_NUMERAL) will fail decisively upon error.

The patch addresses this gap by explicitly verifying whether the pointer has moved. The developer introduced a direct comparison between the temporary pointer tmp and the position pointer pos.

--- a/lib/facil/fiobj/fio_json_parser.h
+++ b/lib/facil/fiobj/fio_json_parser.h
@@
        uint8_t *tmp = pos;
        long long i = fio_atol((char **)&tmp);
        if (tmp > limit)
          goto stop;
-       if (!tmp || JSON_NUMERAL[*tmp]) {
+       if (!tmp || tmp == pos || JSON_NUMERAL[*tmp]) {
          tmp = pos;
          double f = fio_atof((char **)&tmp);
          if (tmp > limit)
            goto stop;
-         if (!tmp || JSON_NUMERAL[*tmp])
+         if (!tmp || tmp == pos || JSON_NUMERAL[*tmp])
            goto error;
          fio_json_on_float(parser, f);
          pos = tmp;

By injecting the tmp == pos check, the condition enforces forward progress. If fio_atol or fio_atof consumes zero characters, tmp will equal pos. The logical OR condition will immediately trigger, causing the routine to recognize the invalid input and correctly jump to the error label, terminating the loop and gracefully failing the parse operation.

Exploitation Methodology

Exploitation requires no authentication, specific configurations, or complex interaction chains. An attacker merely needs network access to an endpoint that parses JSON payloads using facil.io or iodine. This typically involves sending an HTTP POST request with the Content-Type: application/json header and a specially crafted body.

The minimal payload required to trigger the vulnerability is simply [i. This string initiates an array and immediately introduces the malformed numeral character. Alternative payloads such as {"a":i or [""i achieve the same outcome by tricking the parser into evaluating the i character as a new value context.

The following Ruby code demonstrates a minimal proof-of-concept for an iodine server. When the Iodine::JSON.parse method is invoked on the request body containing [i, the worker thread immediately locks.

require "iodine"
 
APP = proc do |env|
  body = env["rack.input"].read.to_s
  warn "Parsing JSON: #{body.inspect}"
  Iodine::JSON.parse(body) # Triggers infinite loop on '[i'
  [200, { "Content-Type" => "text/plain" }, ["ok"]]
end
 
Iodine.listen service: :http, port: "3000", handler: APP
Iodine.threads = 1
Iodine.start

To execute the exploit against the vulnerable server, an attacker utilizes standard HTTP clients. The command printf '[i' | curl -X POST --data-binary @- http://127.0.0.1:3000/ dispatches the payload without URL encoding or trailing line breaks, guaranteeing the parser processes the exact bytes required to stall the state machine.

Impact Assessment

The operational impact of this vulnerability is a complete localized Denial of Service. When the infinite loop initiates, the underlying thread consumes 100% of the assigned CPU core's cycles. It will never timeout natively because the thread is actively processing code rather than blocking on I/O.

In architectures like facil.io and iodine which utilize asynchronous event loops, a blocked worker thread ceases processing all other queued connections assigned to that thread. If the application runs a single-threaded event loop, a single malformed request brings down the entire application.

In multi-threaded deployments, an attacker can achieve a total service outage by sending concurrent requests equal to the number of configured worker threads. Once all threads are trapped in the infinite loop parsing [i, the application becomes entirely unresponsive to legitimate traffic. The system administrator must forcefully terminate and restart the process to restore functionality.

Remediation Guidance

The primary remediation strategy requires updating the vulnerable packages to their patched versions. Applications relying on the iodine Ruby gem must upgrade to version greater than 0.7.58. Applications utilizing the facil.io C framework directly must integrate the latest commits from the master branch, specifically ensuring the fio_json_parser.h changes are applied.

For environments where immediate patching is impossible, network-level mitigations can provide temporary defense. Web Application Firewalls (WAFs) can be configured to inspect incoming JSON bodies for the specific byte sequences used in the exploit. Regular expressions targeting \[\s*i or :\s*i can intercept the most common variants of the payload before they reach the application layer.

Developers should verify their deployment architectures include adequate resource monitoring and process supervision. Configuring orchestration tools to health-check the application and restart uncooperative containers can reduce the total downtime during an active attack, though it does not eliminate the underlying vulnerability.

Official Patches

boazsegevOfficial Security Advisory and Patch Details

Technical Appendix

CVSS Score
8.7/ 10
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

Affected Systems

facil.io C framework versions 0.7.5 and 0.7.6iodine Ruby gem versions <= 0.7.58

Affected Versions Detail

Product
Affected Versions
Fixed Version
facil.io
boazsegev
0.7.5, 0.7.6-
iodine
boazsegev
<= 0.7.58> 0.7.58
AttributeDetail
Vulnerability IDGHSA-2x79-gwq3-vxxm
CWECWE-835: Loop with Unreachable Exit Condition ('Infinite Loop')
Attack VectorNetwork
CVSS v4.0 Score8.7 (High)
Exploit StatusProof of Concept Available
ImpactDenial of Service (CPU Exhaustion)

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Impact
CWE-835
Loop with Unreachable Exit Condition ('Infinite Loop')

The program contains an iteration or loop with an exit condition that cannot be reached, i.e., an infinite loop.

Known Exploits & Detection

Advisory PoCMinimal curl payload and Ruby testing server configuration.

Vulnerability Timeline

Advisory Published on GitHub
2026-04-14

References & Sources

  • [1]GitHub Security Advisory GHSA-2x79-gwq3-vxxm

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 9 hours ago•CVE-2026-54720
5.4

CVE-2026-54720: Stored Cross-Site Scripting (XSS) via Sandbox Bypass in Silverstripe Framework

CVE-2026-54720 is a stored Cross-Site Scripting (XSS) vulnerability inside the Silverstripe Framework's media shortcode processor. Due to a flawed performance optimization, HTML inputs containing two or fewer opening angle brackets bypassed security sandboxing. This flaw allows authenticated or lower-privileged users to inject administrative panel payloads that execute arbitrary client-side JavaScript when viewed by system administrators.

Amit Schendel
Amit Schendel
3 views•6 min read
•about 10 hours ago•CVE-2026-54713
3.7

CVE-2026-54713: Idempotency Key Collision and Silent Job Dropping in cakephp/queue

An incomplete array comparison vulnerability in cakephp/queue version 0.1.11 through 2.3.0 allows unauthenticated attackers to cause key collisions in unique job deduplication. This is caused by standard array value sorting that discards associative keys, normalizing different payload keys to identical arrays and leading to a denial of service (DoS) by dropping legitimate jobs.

Alon Barad
Alon Barad
2 views•7 min read
•about 11 hours ago•CVE-2026-55558
5.9

CVE-2026-55558: STARTTLS Response Injection in aiosmtplib

An input buffering vulnerability exists in the aiosmtplib asynchronous SMTP client library before version 5.1.2. When upgrading a plaintext connection to TLS via STARTTLS, the library processes buffered plaintext responses after transport negotiation has completed. This behavior allows a network-positioned attacker to inject spoofed server responses prior to negotiation, leading to command/response desynchronization, arbitrary capability injection, and potential credential theft.

Alon Barad
Alon Barad
2 views•6 min read
•about 12 hours ago•CVE-2026-54770
6.1

CVE-2026-54770: Open Redirect via Parser Differential in WebOb

An open redirect vulnerability exists in WebOb before version 1.8.11 due to a parser differential between WebOb's validation logic and Python's standard urllib.parse.urljoin() function. Under Python 3.10+, the urljoin function strips leading and trailing space characters and C0 control characters, which allowed specially crafted inputs to bypass WebOb's prefix checks while still resolving as off-host redirects.

Amit Schendel
Amit Schendel
3 views•7 min read
•about 13 hours ago•CVE-2026-54687
6.1

CVE-2026-54687: Path Traversal via User-Controlled Database File Path in n8n-nodes-sqlite3

Prior to version 1.0.0, the n8n-nodes-sqlite3 integration exposed the db_path parameter as an unrestricted node parameter. By default, n8n node parameters allow the evaluation of dynamic data expressions, meaning untrusted external input could be mapped to the database path. This vulnerability allows an external attacker to control which SQLite database file the n8n backend process attempts to open, leading to directory traversal outside of the intended directory context.

Amit Schendel
Amit Schendel
6 views•5 min read
•about 14 hours ago•CVE-2026-42350
5.1

CVE-2026-42350: Client-Side Open Redirect in Kargo UI OIDC Authentication Flow

A client-side open redirect vulnerability has been identified in the Kargo user interface. The flaw resides in the handling of OpenID Connect (OIDC) login and token renewal flows, where the application extracts an unvalidated destination path from the redirectTo query parameter. Attackers can exploit this to redirect authenticated users to arbitrary external domains.

Alon Barad
Alon Barad
4 views•6 min read