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.
// 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
# 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.


