Unrestricted Resource Consumption

Unrestricted Resource Consumption in Go (Gin) [CVE-2026-41146]

[Updated April 2026] Updated CVE-2026-41146

Overview

CVE-2026-41146 describes a CPU-exhaustion DoS in the facil.io JSON parser (fio_json_parse) where, for attacker-controlled JSON with certain nested values starting with i or I, the parser can enter an infinite loop and peg a CPU core at ~100%. The issue could be triggered by carefully crafted payloads and was fixed by the commit 5128747363055201d3ecf0e29bf0a961703c9fa0e. This class of vulnerability maps to CWE-400 (Uncontrolled Resource Consumption) and CWE-835 (DoS via resource consumption). In Go applications using the Gin framework, the risk is most acute if you rely on vulnerable external parsers (e.g., via CGO) or otherwise process untrusted JSON without input bounds. While Go’s standard encoding/json is a separate implementation, integrating or multiplexing with a vulnerable C parser can reintroduce similar DoS vectors; even without CGO, unbounded or oversized JSON payloads can cause CPU or memory exhaustion under load. The real-world implication is that an attacker can overwhelm your service by sending crafted JSON payloads, causing slowdowns or outages for legitimate users.

Code Fix Example

Go (Gin) API Security Remediation
package main

import (
  "encoding/json"
  "io/ioutil"
  "net/http"
  "github.com/gin-gonic/gin"
)

func main() {
  r := gin.Default()

  // Vulnerable pattern: reads entire body and parses JSON without bounds
  r.POST("/vuln", func(c *gin.Context) {
    var payload map[string]interface{}
    body, err := ioutil.ReadAll(c.Request.Body)
    if err != nil {
      c.Status(http.StatusBadRequest)
      return
    }
    if err := json.Unmarshal(body, &payload); err != nil {
      c.Status(http.StatusBadRequest)
      return
    }
    c.JSON(http.StatusOK, gin.H{"status": "ok"})
  })

  // Fixed pattern: bound the body size and use streaming decoding
  r.POST("/fixed", func(c *gin.Context) {
    // Limit to 1MB to prevent unbounded resource consumption
    c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, 1<<20)
    var payload map[string]interface{}
    dec := json.NewDecoder(c.Request.Body)
    if err := dec.Decode(&payload); err != nil {
      c.Status(http.StatusBadRequest)
      return
    }
    c.JSON(http.StatusOK, gin.H{"status": "ok"})
  })

  r.Run(":8080")
}

CVE References

Choose which optional cookies to allow. You can change this any time.