Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-41146

CVE-2026-41146: facil.io JSON Parser DoS Vulnerability

CVE-2026-41146 is a denial of service flaw in facil.io's JSON parser that causes infinite loops when processing malformed JSON, pegging CPU at 100%. This post covers technical details, affected versions, and mitigation.

Published:

CVE-2026-41146 Overview

A denial of service vulnerability exists in facil.io, a C micro-framework for web applications. The fio_json_parse function can enter an infinite loop when processing maliciously crafted JSON input containing nested values starting with i or I. This causes the process to spin in user space, pegging one CPU core at approximately 100% utilization instead of returning a parse error. The vulnerability also affects the iodine Ruby web server which vendors the same parser code.

Critical Impact

Remote attackers can trigger CPU exhaustion by sending specially crafted JSON payloads as small as two characters ([i), causing denial of service to applications using facil.io or iodine for JSON parsing.

Affected Products

  • facil.io (versions prior to commit 5128747363055201d3ecf0e29bf0a961703c9fa0)
  • iodine Ruby HTTP/WebSocket server (vendors facil.io parser code)
  • Applications using facil.io's fio_json_parse function

Discovery Timeline

  • 2026-04-22 - CVE-2026-41146 published to NVD
  • 2026-04-22 - Last updated in NVD database

Technical Details for CVE-2026-41146

Vulnerability Analysis

This vulnerability is categorized as CWE-400 (Uncontrolled Resource Consumption). The flaw resides in the JSON parser's handling of numeric value parsing. When the parser encounters input starting with i or I in a value context, the numeric parsing functions (fio_atol and fio_atof) fail to advance the position pointer, causing the parser to re-process the same character indefinitely.

The smallest reproducer is simply [i — a two-character payload that triggers the infinite loop. The quoted-value form ["\"i also triggers the bug because the parser tolerates missing commas between elements and subsequently treats the trailing i as the start of another value.

Root Cause

The root cause lies in the numeric parsing logic within lib/facil/fiobj/fio_json_parser.h. The original code checked whether the temporary pointer (tmp) was null or pointing to a numeric character, but failed to verify whether the parsing functions actually consumed any input. When fio_atol or fio_atof encounters an invalid numeric string starting with i or I (likely intended for values like "infinity"), it returns without advancing the position pointer, yet the original validation checks passed, causing the parser to loop indefinitely.

Attack Vector

The vulnerability is exploitable over the network without authentication or user interaction. An attacker can send a minimal JSON payload containing the malicious pattern to any endpoint that parses JSON using facil.io's fio_json_parse function. This includes:

  • HTTP POST requests with JSON body content
  • WebSocket messages containing JSON data
  • Any API endpoint accepting JSON input

The attack requires minimal bandwidth (as few as 2 bytes) and can exhaust CPU resources on the target server.

c
// Security patch from lib/facil/fiobj/fio_json_parser.h
// Source: https://github.com/boazsegev/facil.io/commit/5128747363055201d3ecf0e29bf0a961703c9fa0

       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;

The fix adds a critical check tmp == pos to verify that the parsing functions actually advanced the position pointer. If no characters were consumed (indicating invalid input), the parser now correctly jumps to the error handler instead of looping.

Detection Methods for CVE-2026-41146

Indicators of Compromise

  • Sustained 100% CPU utilization on a single core by web application processes
  • Web server processes becoming unresponsive to legitimate requests
  • Increased request timeouts or connection failures from client perspective
  • Log entries showing incomplete or malformed JSON payloads with patterns containing i or I characters in unexpected positions

Detection Strategies

  • Monitor for anomalous CPU utilization patterns where a single core sustains 100% usage while others remain idle
  • Implement request timeout monitoring to detect endpoints that stop responding
  • Analyze incoming JSON payloads for suspicious patterns like [i, ["i, or nested arrays with i/I characters
  • Deploy application-level monitoring to track JSON parsing duration and flag operations exceeding expected thresholds

Monitoring Recommendations

  • Configure process monitoring to alert on single-threaded CPU exhaustion scenarios
  • Implement connection timeout thresholds at load balancer and reverse proxy layers
  • Enable detailed logging of malformed JSON parsing errors with payload sampling
  • Set up health check endpoints that bypass JSON parsing to detect hung application states

How to Mitigate CVE-2026-41146

Immediate Actions Required

  • Update facil.io to include commit 5128747363055201d3ecf0e29bf0a961703c9fa0 or later
  • Update iodine gem if using Ruby with iodine as the web server
  • Implement request timeouts at the application or infrastructure level to limit impact of potential exploitation
  • Consider rate limiting on endpoints that accept JSON input from untrusted sources

Patch Information

The vulnerability is fixed in facil.io commit 5128747363055201d3ecf0e29bf0a961703c9fa0. The patch modifies the JSON parser in lib/facil/fiobj/fio_json_parser.h to add a position advancement check that prevents the infinite loop condition. For detailed patch information, see the GitHub Commit and the GitHub Security Advisory GHSA-2x79-gwq3-vxxm.

Workarounds

  • Implement JSON input validation or sanitization before passing to fio_json_parse
  • Deploy request timeout mechanisms at the web server, reverse proxy, or load balancer level to terminate long-running requests
  • Use an alternative JSON parser for untrusted input until the patch can be applied
  • Implement resource limits (CPU time, memory) for request-handling processes using containerization or OS-level controls
bash
# Example: Configure nginx upstream timeout to limit request processing time
# Add to nginx configuration to mitigate potential DoS impact

upstream facil_backend {
    server 127.0.0.1:3000;
}

server {
    location /api/ {
        proxy_pass http://facil_backend;
        proxy_connect_timeout 5s;
        proxy_send_timeout 10s;
        proxy_read_timeout 30s;
        
        # Limit request body size for JSON endpoints
        client_max_body_size 1m;
    }
}

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.