CVE-2026-107826
OWASP Coraza WAF: JSON body processor: argument-limit truncation reopens an unbounded-depth gjson.Valid stack overflow (process crash)
OWASP Coraza WAF is a golang modsecurity compatible web application firewall library. From 3.0.0 until 3.8.1, readJSON in internal/bodyprocessors/json.go can stop its bounded flattening walk after reaching SecArgumentsLimit or the byte budget and then call gjson.Valid on the complete raw body. An unauthenticated attacker can submit shallow values followed by an extremely deeply nested JSON tail that was not visited by the bounded walk, causing gjson.Valid to recurse without a depth bound and terminate the hosting process with an unrecoverable fatal stack overflow. The ProcessRequest and ProcessResponse JSON paths share the affected readJSON validation flow, and the payload can remain within recommended body-size and argument-count limits. This issue is fixed in version 3.8.1.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- None
- Integrity
- None
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
7.5
OWASP Coraza WAF: JSON body processor: argument-limit truncation reopens an unbounded-depth gjson.Valid stack overflow (process crash)
OWASP Coraza WAF is a golang modsecurity compatible web application firewall library. From 3.0.0 until 3.8.1, readJSON in internal/bodyprocessors/json.go can stop its bounded flattening walk after reaching SecArgumentsLimit or the byte budget and then call gjson.Valid on the complete raw body. An unauthenticated attacker can submit shallow values followed by an extremely deeply nested JSON tail that was not visited by the bounded walk, causing gjson.Valid to recurse without a depth bound and terminate the hosting process with an unrecoverable fatal stack overflow. The ProcessRequest and ProcessResponse JSON paths share the affected readJSON validation flow, and the payload can remain within recommended body-size and argument-count limits. This issue is fixed in version 3.8.1.
- Record
CVE-2026-107826- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - Weakness
- CWE-674
- Updated
- 2026-11-02
EUVDEUVD-2026-95925
7.5
OWASP Coraza WAF is a golang modsecurity compatible web application firewall library. From 3.0.0 until 3.8.1, readJSON in internal/bodyprocessors/json.go can stop its bounded flattening walk after reaching SecArgumentsLimit or the byte budget and then call gjson.Valid on the complete raw body. An unauthenticated attacker can submit shallow values followed by an extremely deeply nested JSON tail that was not visited by the bounded walk, causing gjson.Valid to recurse without a depth bound and terminate the hosting process with an unrecoverable fatal stack overflow. The ProcessRequest and ProcessResponse JSON paths share the affected readJSON validation flow, and the payload can remain within recommended body-size and argument-count limits. This issue is fixed in version 3.8.1.
- Record
EUVD-2026-95925- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-6gcq-wc29-5xf2
7.5
Coraza JSON body processor: argument-limit truncation reopens an unbounded-depth gjson.Valid stack overflow (process crash)
Summary
The JSON body processor (internal/bodyprocessors/json.go) can be made to
crash the whole process with an unrecoverable fatal error: stack overflow,
using a request body that is well under the recommended SecRequestBodyLimit
and the default SecArgumentsLimit.
Root cause
readJSON (json.go:113-143) runs a bounded, best-effort flattening walk
(readItems) and afterwards calls gjson.Valid(s) on the raw body if
readItems returned no error:
json := gjson.Parse(s)
...
truncated, err = readItems(json, key, maxRecursion, argumentLimit, byteBudget, &usedBytes, &argCount, res)
if err != nil {
return res, truncated, err
}
if !gjson.Valid(s) {
return res, truncated, errors.New("invalid JSON")
}
gjson.Valid (gjson v1.18.0, validany -> validarray/validobject) recurses
once per nesting level with no depth bound. readItems does have a depth
bound (maxRecursion), enforced here (json.go:163-182):
func readItems(json gjson.Result, objKey []byte, maxRecursion int, argumentLimit int, byteBudget int, usedBytes *int, argCount *int, res map[string][]string) (truncated bool, err error) {
if byteBudget > 0 && *usedBytes >= byteBudget {
return true, nil // <-- checked first
}
if argumentLimit > 0 && *argCount >= argumentLimit {
return true, nil // <-- checked second
}
...
if maxRecursion <= 0 {
return false, errors.New("max recursion reached while reading json object")
}
The byte-budget and argument-limit checks run before the recursion-depth
check, and they short-circuit the walk with truncated=true, err=nil instead
of recursing further. If the configured SecArgumentsLimit
(ArgumentLimit, default 1000, internal/corazawaf/waf.go:359) is reached by
earlier, shallow values in the document, readItems stops walking before it
ever reaches a deeply nested tail later in the same document — so the
maxRecursion error is never produced, err comes back nil, and readJSON
falls through to the unconditional gjson.Valid(s) call on the complete raw
body, including the part readItems never visited.
This is not a new interaction with the recursion limit itself: at v3.7.0,
gjson.Valid ran unconditionally before any recursion check at all, so a
plain deeply-nested body crashed the process directly. A later fix added a
depth check that returns an error before Valid runs for the straightforward
case (nesting reached before any other guard fires). The argument-limit /
byte-budget guards added since then (GHSA-6r3q-mjv7-xr8m,
GHSA-3ww9-vw83-9w5x) reopened the same crash for the case above, because they
short-circuit the walk (and therefore the recursion counter) ahead of the
depth check, on both the request and response body path (ProcessResponse
calls the same readJSON, json.go:57-88).
Because this is fatal error: stack overflow, not a panic, it is not
recoverable by any recover() in the calling goroutine — the process
terminates unconditionally.
PoC
package bodyprocessors
import (
"strings"
"testing"
)
func TestStackOverflowRepro(t *testing.T) {
body := "[" + strings.Repeat("1,", 1000) + strings.Repeat("[", 13_000_000)
// 13,002,001 bytes total: under the recommended SecRequestBodyLimit
// (13107200, coraza.conf-recommended:78) and default ArgumentLimit (1000,
// internal/corazawaf/waf.go:359).
_, _, _ = readJSON(body, 20, 1000)
}
$ go test -run TestStackOverflowRepro ./internal/bodyprocessors/ -v
runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow
...
github.com/tidwall/gjson.validarray(...)
.../[email protected]/gjson.go:2584
github.com/tidwall/gjson.validany(...)
.../[email protected]/gjson.go:2499
github.com/tidwall/gjson.validarray(...)
.../[email protected]/gjson.go:2589
... (repeats until the goroutine stack limit is hit)
Reproduced against commit 19b86824 (tag v3.8.0),…
- Record
GHSA-6gcq-wc29-5xf2- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - Weakness
- CWE-674
- Updated
- 2026-11-02
NVD
7.5
OWASP Coraza WAF is a golang modsecurity compatible web application firewall library. From 3.0.0 until 3.8.1, readJSON in internal/bodyprocessors/json.go can stop its bounded flattening walk after reaching SecArgumentsLimit or the byte budget and then call gjson.Valid on the complete raw body. An unauthenticated attacker can submit shallow values followed by an extremely deeply nested JSON tail that was not visited by the bounded walk, causing gjson.Valid to recurse without a depth bound and terminate the hosting process with an unrecoverable fatal stack overflow. The ProcessRequest and ProcessResponse JSON paths share the affected readJSON validation flow, and the payload can remain within recommended body-size and argument-count limits. This issue is fixed in version 3.8.1.
- Record
CVE-2026-107826- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - Weakness
- CWE-674
- Updated
- 2026-11-02
OSV
7.5
OWASP Coraza WAF: JSON body processor: argument-limit truncation reopens an unbounded-depth gjson.Valid stack overflow (process crash)
OWASP Coraza WAF is a golang modsecurity compatible web application firewall library. From 3.0.0 until 3.8.1, readJSON in internal/bodyprocessors/json.go can stop its bounded flattening walk after reaching SecArgumentsLimit or the byte budget and then call gjson.Valid on the complete raw body. An unauthenticated attacker can submit shallow values followed by an extremely deeply nested JSON tail that was not visited by the bounded walk, causing gjson.Valid to recurse without a depth bound and terminate the hosting process with an unrecoverable fatal stack overflow. The ProcessRequest and ProcessResponse JSON paths share the affected readJSON validation flow, and the payload can remain within recommended body-size and argument-count limits. This issue is fixed in version 3.8.1.
- Record
CVE-2026-107826- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - Weakness
- CWE-674
- Updated
- 2026-11-02
OSVGHSA-6gcq-wc29-5xf2
7.5
Coraza JSON body processor: argument-limit truncation reopens an unbounded-depth gjson.Valid stack overflow (process crash)
Summary
The JSON body processor (internal/bodyprocessors/json.go) can be made to
crash the whole process with an unrecoverable fatal error: stack overflow,
using a request body that is well under the recommended SecRequestBodyLimit
and the default SecArgumentsLimit.
Root cause
readJSON (json.go:113-143) runs a bounded, best-effort flattening walk
(readItems) and afterwards calls gjson.Valid(s) on the raw body if
readItems returned no error:
json := gjson.Parse(s)
...
truncated, err = readItems(json, key, maxRecursion, argumentLimit, byteBudget, &usedBytes, &argCount, res)
if err != nil {
return res, truncated, err
}
if !gjson.Valid(s) {
return res, truncated, errors.New("invalid JSON")
}
gjson.Valid (gjson v1.18.0, validany -> validarray/validobject) recurses
once per nesting level with no depth bound. readItems does have a depth
bound (maxRecursion), enforced here (json.go:163-182):
func readItems(json gjson.Result, objKey []byte, maxRecursion int, argumentLimit int, byteBudget int, usedBytes *int, argCount *int, res map[string][]string) (truncated bool, err error) {
if byteBudget > 0 && *usedBytes >= byteBudget {
return true, nil // <-- checked first
}
if argumentLimit > 0 && *argCount >= argumentLimit {
return true, nil // <-- checked second
}
...
if maxRecursion <= 0 {
return false, errors.New("max recursion reached while reading json object")
}
The byte-budget and argument-limit checks run before the recursion-depth
check, and they short-circuit the walk with truncated=true, err=nil instead
of recursing further. If the configured SecArgumentsLimit
(ArgumentLimit, default 1000, internal/corazawaf/waf.go:359) is reached by
earlier, shallow values in the document, readItems stops walking before it
ever reaches a deeply nested tail later in the same document — so the
maxRecursion error is never produced, err comes back nil, and readJSON
falls through to the unconditional gjson.Valid(s) call on the complete raw
body, including the part readItems never visited.
This is not a new interaction with the recursion limit itself: at v3.7.0,
gjson.Valid ran unconditionally before any recursion check at all, so a
plain deeply-nested body crashed the process directly. A later fix added a
depth check that returns an error before Valid runs for the straightforward
case (nesting reached before any other guard fires). The argument-limit /
byte-budget guards added since then (GHSA-6r3q-mjv7-xr8m,
GHSA-3ww9-vw83-9w5x) reopened the same crash for the case above, because they
short-circuit the walk (and therefore the recursion counter) ahead of the
depth check, on both the request and response body path (ProcessResponse
calls the same readJSON, json.go:57-88).
Because this is fatal error: stack overflow, not a panic, it is not
recoverable by any recover() in the calling goroutine — the process
terminates unconditionally.
PoC
package bodyprocessors
import (
"strings"
"testing"
)
func TestStackOverflowRepro(t *testing.T) {
body := "[" + strings.Repeat("1,", 1000) + strings.Repeat("[", 13_000_000)
// 13,002,001 bytes total: under the recommended SecRequestBodyLimit
// (13107200, coraza.conf-recommended:78) and default ArgumentLimit (1000,
// internal/corazawaf/waf.go:359).
_, _, _ = readJSON(body, 20, 1000)
}
$ go test -run TestStackOverflowRepro ./internal/bodyprocessors/ -v
runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow
...
github.com/tidwall/gjson.validarray(...)
.../[email protected]/gjson.go:2584
github.com/tidwall/gjson.validany(...)
.../[email protected]/gjson.go:2499
github.com/tidwall/gjson.validarray(...)
.../[email protected]/gjson.go:2589
... (repeats until the goroutine stack limit is hit)
Reproduced against commit 19b86824 (tag v3.8.0),…
- Record
GHSA-6gcq-wc29-5xf2- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - Weakness
- CWE-674
- Updated
- 2026-11-02
OSVGO-2026-6693 No score
Coraza JSON body processor: argument-limit truncation reopens an unbounded-depth gjson.Valid stack overflow (process crash) in github.com/corazawaf/coraza
Coraza JSON body processor: argument-limit truncation reopens an unbounded-depth gjson.Valid stack overflow (process crash) in github.com/corazawaf/coraza
- Record
GO-2026-6693- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
github.com/corazawaf/coraza/v3Go |
3.0.0 up to 3.8.1 | 3.8.1 |
github.com/corazawaf/corazaGo |
All versions | None known |
github.com/corazawaf/coraza/v2Go |
All versions | None known |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-107826 is a high vulnerability (CVSS 7.5) in Corazawaf Coraza, published October 8, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.46%, the 40th percentile. Fixed in github.com/corazawaf/coraza/v3 3.8.1.
References
github.com/corazawaf/coraza/security/advisories/GHSA-6gcq-wc29-5xf2
github.com/corazawaf/coraza/commit/814e1898e083d2ff2ceb644382d0da17e930f93f
github.com/corazawaf/coraza/releases/tag/v3.8.1
github.com/advisories/GHSA-6gcq-wc29-5xf2
github.com/CVEProject/cvelistV5/tree/main/cves/2026/107xxx/CVE-2026-107826.json
nvd.nist.gov/vuln/detail/CVE-2026-107826
github.com/corazawaf/coraza
Left out here: the rest of 2 source descriptions. The JSON record has them.