CVE-2026-61629 Overview
CVE-2026-61629 is a denial-of-service vulnerability in nginx-ignition, a user interface for the nginx web server. Versions 2.29.0 through 2.40.0 contain a flaw in the gin i18n middleware. The middleware passes the raw Accept-Language header to golang.org/x/text/language.ParseAcceptLanguage without any size or shape filtering. The underlying parser exhibits quadratic-time behaviour on long lists of malformed language tags. A single unauthenticated GET request can burn approximately 2.4 seconds of CPU on the host. Version 2.40.1 fixes this issue.
Critical Impact
Ten concurrent unauthenticated attackers can saturate a ten-core server while consuming roughly 10 MiB/s of upstream bandwidth, rendering the nginx-ignition management interface unavailable.
Affected Products
- nginx-ignition versions 2.29.0 through 2.40.0
- The api/common/server/i18n.go middleware component
- Deployments exposing the nginx-ignition API server to untrusted networks
Discovery Timeline
- 2026-09-21 - CVE-2026-61629 published to the National Vulnerability Database
- 2026-09-23 - Last updated in NVD database
Technical Details for CVE-2026-61629
Vulnerability Analysis
The vulnerability is an algorithmic complexity attack classified under [CWE-770] Allocation of Resources Without Limits or Throttling. The gin i18n middleware executes in front of every HTTP request handled by the nginx-ignition API server. It reads the Accept-Language header verbatim and forwards it to language.ParseAcceptLanguage from golang.org/x/text. That parser runs in quadratic time when processing long sequences of malformed language tags.
The fix for CVE-2022-32149 added in golang.org/x/text v0.3.8 caps the number of - characters at 1000. However, the guard does not cap _ characters. The parser's internal scanner aliases _ to - before parsing, which allows attackers to bypass the guard entirely by substituting underscores for hyphens.
Root Cause
The middleware performed no validation of the Accept-Language header length or structure before invoking the parser. Combined with an incomplete upstream guard in golang.org/x/text, this allowed unauthenticated clients to trigger the parser's worst-case quadratic behaviour and consume disproportionate CPU per request.
Attack Vector
An unauthenticated remote attacker sends a GET request to any nginx-ignition API endpoint with an Accept-Language header composed of many _ separators. A single request consumes about 2.4 seconds of server CPU. Ten concurrent attackers saturate a ten-core server for the duration of the attack. No authentication, user interaction, or special privileges are required.
// Patch applied in api/common/server/i18n.go
import (
"context"
"strings"
"github.com/gin-gonic/gin"
"golang.org/x/text/language"
"dillmann.com.br/nginx-ignition/core/common/i18n"
)
const maximumLanguageTags = 10
func i18nMiddleware(commands i18n.Commands) gin.HandlerFunc {
return func(ginCtx *gin.Context) {
lang := commands.DefaultLanguage()
langHeader := ginCtx.GetHeader("Accept-Language")
if strings.Count(langHeader, "-")+strings.Count(langHeader, "_") > maximumLanguageTags {
langHeader = ""
}
tags, _, err := language.ParseAcceptLanguage(langHeader)
if err == nil && len(tags) > 0 {
for _, tag := range tags {
// Source: https://github.com/lucasdillmann/nginx-ignition/commit/0c988fc1277c7d291725e8373313f8486fa1b31a
The patch counts both - and _ characters and discards the header when the combined total exceeds ten, preventing the parser from processing pathological inputs.
Detection Methods for CVE-2026-61629
Indicators of Compromise
- HTTP requests to nginx-ignition endpoints containing Accept-Language header values with dozens or more _ characters
- Sustained high CPU utilization on the nginx-ignition process without corresponding legitimate request volume
- Elevated request latency across all API endpoints during periods of low traffic
- Repeated requests from a small set of source IPs preceding CPU saturation events
Detection Strategies
- Inspect reverse proxy or load balancer logs for Accept-Language header values exceeding a reasonable length threshold, such as 100 bytes
- Correlate spikes in per-request processing time on nginx-ignition endpoints with abnormal header characteristics
- Alert when a single client IP issues repeated requests carrying malformed language tag lists
Monitoring Recommendations
- Enable CPU and request-latency metrics on the nginx-ignition host and set thresholds for sustained utilization above baseline
- Capture and retain full HTTP request headers in centralized logs to support retrospective analysis
- Monitor upstream bandwidth consumption on the interface serving nginx-ignition for sustained increases in inbound traffic
How to Mitigate CVE-2026-61629
Immediate Actions Required
- Upgrade nginx-ignition to version 2.40.1 or later, which enforces a maximum of ten language tag separators in the Accept-Language header
- Restrict network access to the nginx-ignition management interface to trusted administrative networks or VPN endpoints
- Place a reverse proxy or WAF in front of nginx-ignition to strip or normalize oversized Accept-Language headers
- Rate-limit unauthenticated requests to the API server at the network edge
Patch Information
The fix is committed in GitHub commit 0c988fc and released in nginx-ignition version 2.40.1. Full advisory details are available in GHSA-jr34-h97m-9hpx. Operators unable to upgrade should apply the middleware guard as a local patch.
Workarounds
- Configure a fronting nginx or reverse proxy to drop the Accept-Language header on incoming requests to nginx-ignition
- Enforce a maximum header size at the proxy layer that rejects oversized Accept-Language values
- Apply strict per-source-IP rate limiting to unauthenticated endpoints of the nginx-ignition API server
# nginx reverse proxy example: cap Accept-Language length and rate-limit clients
limit_req_zone $binary_remote_addr zone=ignition:10m rate=5r/s;
server {
listen 443 ssl;
server_name ignition.example.com;
location / {
limit_req zone=ignition burst=10 nodelay;
if ($http_accept_language ~* ".{100,}") {
return 400;
}
proxy_set_header Accept-Language "";
proxy_pass http://127.0.0.1:8080;
}
}
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

