Skip to main content

Coraza WAF EUVDEUVD-2026-97826

| CVE-2026-41504 MEDIUM
Improper Neutralization of CRLF Sequences ('CRLF Injection') (CWE-93)
2026-10-06 https://github.com/corazawaf/coraza GHSA-prpw-wwv7-xjjr
5.8
CVSS 3.1 · Vendor: https://github.com/corazawaf/coraza
View

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain

  1. Access
    Send POST with raw CRLF-laden body
  2. Exploit
    Coraza writes unescaped bytes into Native audit log
  3. Execution
    Forged boundary and spoofed client lines materialize as records
  4. Impact
    SIEM miscorrelation and attribution shifting

Vulnerability Assessment

Weakness
CWE
OWASP Top 10:2025
A05:2025 - Injection
ASVS 5.0
V1 - Encoding and Sanitization CRLF sequence sanitization
Exploitation Conditions

Requires the defender to run 'SecAuditLogFormat Native' (the shipped coraza.conf-recommended default) with 'SecAuditLogType Serial' or 'Concurrent' and 'SecAuditEngine On'. The request-BODY vector (Part C) is reachable through the stock coraza/v3/http + net/http wrapper and needs 'SecRequestBodyAccess On' plus any audit-logged rule match (trivial). The request/response-HEADER vectors (Parts B/F) are NOT reachable via net/http, which rejects bare CRLF headers with 400 - they only apply to integrations that forward unvalidated header bytes (coraza-spoa/HAProxy SPOP, coraza-proxy-wasm/Envoy WASM, or custom FFI/embedders calling tx.AddRequestHeader with raw bytes). Limiting factors: deployments using JSON or OCSF audit formats, or with SecAuditEngine Off, are entirely unaffected, and real impact depends on the downstream log parser/SIEM making line-based assumptions about boundaries or '[client "..."]' patterns.

Impact

This is a genuine integrity/log-forgery issue, not a high-severity emergency. The input CVSS vector (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:L/A:N, 5.8 Medium) is internally consistent with the description: remote, unauthenticated (PR:N), low-complexity, with only Low integrity impact and no confidentiality or availability impact - appropriate for log injection rather than code execution. The scope change (S:C) is well-justified because the damage lands on a downstream authority (the SIEM / log-parsing pipeline), not Coraza itself. No EPSS score was provided and the CVE is NOT listed in CISA KEV, so there is no evidence of active exploitation. A detailed proof-of-concept (body and header vectors) and regression tests are published in the advisory, so working exploit knowledge is public. Signals are consistent, not conflicting: medium CVSS + no KEV + public PoC + low real-world blast radius (integrity-only, format-dependent) = a real but lower-tier priority. One important nuance the raw CVSS hides: the most dangerous (header) vector is NOT reachable through the stock net/http wrapper because Go rejects bare CRLF in headers - so for typical Go/net-http deployments only the request-body vector applies. The headline 'RCE' tag in the input is incorrect and overstates risk (see data_quality_flags); this is CRLF injection / log forgery (CWE-93/CWE-117), with no path to code execution.

Exploit ScenarioDerived

An attacker sends an ordinary urlencoded POST whose body embeds raw CRLF sequences plus forged '--...--' boundary lines and a spoofed '[client "9.9.9.9"] FAKE ATTACK ENTRY' line; because the Native formatter writes the body unescaped, these appear as structurally genuine lines in /tmp/audit.log. A published PoC demonstrates this against a default 'SecAuditLogFormat Native' configuration, letting the attacker forge entries, confuse SIEM correlation, and bury a real rule match under attacker-controlled noise. No rule fires and no error is raised, so the injection is invisible to the WAF.

This Month Plan within 30 days. Why: MEDIUM severity (CVSS 4.0-6.9).
Patch available 0.4% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv1 – Oct 06, 2026

Remote, unauthenticated log-injection in Coraza WAF's Native audit-log formatter (all releases 3.0.0 through 3.7.0) allows any client whose data lands in an audit-log field - most easily the request body - to embed CR and LF bytes that forge new section boundaries and complete fake log entries inside a defender's audit log. The impact is integrity-only (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:L/A:N, score 5.8): an attacker can shift attribution to a spoofed client IP, split SIEM correlation by fabricating boundary lines, poison line-based grep/awk/tail pipelines, or bury a genuine rule match under attacker-controlled noise. No confirmed active exploitation (not listed in CISA KEV), but the upstream GHSA advisory publishes a reproducible proof-of-concept request, and the fix shipped in v3.8.0.

RemediationAI

Vendor-released patch: upgrade to github.com/corazawaf/coraza/v3 v3.8.0 (commit a3079325547c7c1e08522aed4d6468f25d080e25), which introduces a package-level logEscaper that escapes the backslash first and then CR and LF (\ -> \\, \r -> \\r, \n -> \\n) at every raw-write site - the backslash-first ordering matters so a literal two-character \r cannot be un-escaped back into a line break by a downstream consumer - and lengthens the per-transaction boundary prefix from 10 to 16 random characters, raising the bar on fully forging a separate-looking session. If upgrading immediately is not possible, switch SecAuditLogFormat to JSON or OCSF, which are structurally immune because json.Marshal escapes CR/LF; alternatively trim SecAuditLogParts to exclude the injectable parts (C, B, E, F, H, K), turning off SecRequestBodyAccess, or set SecAuditEngine Off. Each workaround has a cost: JSON/OCSF changes the log schema your parsers and SIEM rules expect, and dropping audit parts or disabling the engine reduces forensic coverage exactly where you need it. Do not attempt to sanitize the Native log downstream as a substitute for patching - the injected bytes are already interleaved with genuine content by the time any parser sees them, and line-based tailers may have acted on them first.

Affected VersionsENISA

coraza 3.0.0, < 3.8.0

Affected Packages

go github.com/corazawaf/coraza no fix
go github.com/corazawaf/coraza/v2 no fix
go github.com/corazawaf/coraza/v3 fix: 3.8.0
euvd coraza_3_0_0 fix: 3.8.0

Source: OSV (Open Source Vulnerabilities)

Affects your stack

Affects 4 packages in go, euvd

Checking this CVE against your own stacks and servers is part of the Basic plan and up.

Technical ContextAI · show details

Coraza's Native audit-log format (internal/auditlog/formats.go) is a line-oriented serialization in which each part is delimited by a boundary line of the form --<10-char random prefix>-<Part>--. The formatter wrote several attacker-influenced values to the output stream verbatim - request headers (Part B), request body (Part C), response body (Part E), response headers (Part F), error messages (Part H) and matched-rule raw data (Part K) - so any embedded carriage return or newline redefined the log's structural grammar. This is CWE-93 (CRLF Injection) manifesting as CWE-117 (Improper Output Neutralization for Logs). The sibling JSON (formats_json.go) and OCSF formatters are immune because they round-trip every value through json.Marshal, which escapes \r and \n. Reachability differs by field: Go's net/http rejects bare CRLF inside header values with 400 Bad Request, so the stock coraza/v3/http wrapper only exposes the request-body (Part C) vector, while Parts B/F require an integration that forwards unvalidated header bytes - coraza-spoa (HAProxy SPOP), coraza-proxy-wasm (Envoy WASM), or a custom FFI/embedder calling tx.AddRequestHeader with raw values. The 10-character random boundary prefix is per-transaction and not predictable externally, which limits an attacker to corrupting the current record rather than fabricating a wholly separate session.

Know when the next one hits your stack

  • Watch products and get an email when something new is published
  • Check this CVE against your own stack and servers
  • Exploit and PoC references, threat intelligence from 22 sources

No credit card · 7-day full trial

Severity by source

Vendor (https://github.com/corazawaf/coraza) PRIMARY 5.8 MEDIUM
AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:L/A:N
vuln.today AI 5.8 MEDIUM

Remote unauthenticated body injection (AV:N/AC:L/PR:N/UI:N); integrity-only impact on a downstream log consumer justifies I:L and S:C, with no confidentiality or availability effect.

3.1 AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:L/A:N
4.0 AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:L/SA:N

Primary rating from Vendor (https://github.com/corazawaf/coraza).

CVSS VectorVendor: https://github.com/corazawaf/coraza

Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Changed
Confidentiality
None
Integrity
Low
Availability
None

DescriptionCVE.org

Root Cause

File: internal/auditlog/formats.go - multiple sites write attacker-influenced bytes into the Native audit-log stream without escaping \r or \n:

go
// Part B - request headers (lines 72-80)
for k, vv := range al.Transaction().Request().Headers() {
    for _, v := range vv {
        res.WriteByte('\n')
        res.WriteString(k)
        res.WriteString(": ")
        res.WriteString(v)   // ← raw
    }
}

// Part C - request body (lines 85-86)
if body := al.Transaction().Request().Body(); body != "" {
    res.WriteString(body)    // ← raw
    res.WriteByte('\n')
}

// Part E - response body (lines 93-94)      raw
// Part F - response headers (lines 111-118) raw
// Part H - error messages (line 125)        raw
// Part K - matched-rule raw data (line 151)  raw

The Native format's section structure is line-based: sections are delimited by lines of the form --<10-char-random-prefix>-<Part>--, and line-based log parsers / SIEM rules rely on that structure. Any attacker-controlled bytes containing \n break the structural invariant and allow the attacker to inject lines that look like genuine audit content.

The other two Native-format implementations in Coraza are not affected: the JSON formatter (formats_json.go) and the OCSF formatter both round-trip values through json.Marshal, which escapes \r and \n.

Impact

An attacker who can land bytes into any of the listed audit-log fields can inject arbitrary lines - including lines that visually resemble new log entries - into the audit log file of a defender running the default SecAuditLogFormat Native configuration. Realistic consequences:

  • Forging entries to shift attribution. An injected line such as [client "9.9.9.9"] Coraza: Warning. ... sits alongside genuine matches in Part H, and a human operator (or simple SIEM rule) reading the log cannot tell them apart.
  • Confusing SIEM correlation. Any ingestion pipeline that splits on --...-[A-Z]-- boundaries or on [client "..."] patterns without validating the session prefix will treat the forged lines as separate records.
  • Breaking log-parsing tooling. Grep/awk pipelines, log tailers, and log-rotation tools with line-based assumptions can be poisoned with crafted binary sequences.
  • Hiding genuine incidents. An attacker who can also trigger a rule match on the same transaction (trivial - send any request that matches *any* audit-logged rule) can bury the real match under noise they control.

The forged lines cannot trivially impersonate an entire *separate* session: the 10-char random prefix in the real boundaries (boundaryPrefix := "--" + utils.RandomString(10) + "-", line 42) is not predictable from outside, and each transaction uses a fresh prefix. But the integrity of a *single* record is fully compromised, which is enough for the SIEM-confusion and attribution-shifting attacks.

Proof of Concept

Server with coraza.conf-recommended-style defaults:

conf
SecRuleEngine On
SecAuditEngine On
SecAuditLogParts ABCFHZ
SecAuditLogType Serial
SecAuditLog /tmp/audit.log
SecAuditLogFormat Native
SecRequestBodyAccess On
SecRule REQUEST_METHOD "@rx ." \
    "id:1001,phase:1,pass,log,auditlog,msg:'trigger'"

Body vector - reachable via stock coraza/v3/http + net/http

Send an ordinary urlencoded POST whose body contains raw CRLF sequences and forged boundaries:

POST / HTTP/1.1
Content-Type: application/x-www-form-urlencoded

evil=benign\r\n--coraza-forged-X--\r\nForgedLine: yes\r\n--coraza-forged-H--\r\n[client "9.9.9.9"] FAKE ATTACK ENTRY

Resulting audit.log:

--heLNtylvjY-C--
evil=benign
--coraza-forged-X--
ForgedLine: yes
--coraza-forged-H--
[client "9.9.9.9"] FAKE ATTACK ENTRY

--heLNtylvjY-F--

The forged --coraza-forged-X-- / --coraza-forged-H-- boundaries and the spoofed [client "9.9.9.9"] line are structurally indistinguishable from the surrounding genuine log content. No rule fires, no error is raised, the attack is invisible to the WAF.

Header vector - reachable via non-net/http integrations only

The same effect applies to Part B (request headers) and Part F (response headers) when a header value contains raw \r\n. Go's net/http rejects such headers at parse time (400 Bad Request), so the stock HTTP wrapper is safe from this path; the vector is reachable when Coraza is called with header values that were not validated by net/http:

  • coraza-spoa (HAProxy SPOP agent) forwards headers from HAProxy, which has more permissive validation.
  • coraza-proxy-wasm / Envoy WASM hosts forward header values from the upstream proxy.
  • Custom FFI/WASM hosts and any embedder calling tx.AddRequestHeader(k, v) with unvalidated bytes.

Other raw-write sites (Part E response body, Part H error messages, Part K matched-rule data) share the same class of issue and should be fixed together.

Mitigation

Escape \r and \n at every raw-write site in internal/auditlog/formats.go. A single package-level helper is sufficient:

go
var logEscaper = strings.NewReplacer("\r", "\\r", "\n", "\\n")

// Part B - header values:
res.WriteString(logEscaper.Replace(v))

// Part F - header values: same
// Part H - error messages:
res.WriteString(logEscaper.Replace(alWithErrMsg.ErrorMessage()))
// Part K - matched-rule raw data:
res.WriteString(logEscaper.Replace(alEntry.Data().Raw()))

For Part C / Part E (bodies), the choice is policy-dependent:

  • Escape inline (logEscaper.Replace(body)): keeps the log human-readable for text bodies but loses fidelity for binary.
  • Base64 / hex-encode the whole part: binary-safe, matches the spirit of ModSecurity v2's binary-log handling, but less human-readable.

Escaping is the minimum; base64 for bodies is the more conservative default and is a reasonable audit-log-default change.

Additional defensive measure

Consider lengthening the boundaryPrefix random suffix from 10 chars to ≥16 chars (line 42). This strictly raises the bar for attackers attempting to *fully* forge a separate-looking session (not just inject lines into the current one). Low-cost change; narrows future variants of this bug class.

Affected versions

The Native formatter has been present since v3.0.0 (file existed at the first-release commit). All releases >= 3.0.0, <= 3.7.0 are affected when SecAuditLogFormat Native is used with SecAuditLogType Serial or SecAuditLogType Concurrent.

Unaffected:

  • Deployments using SecAuditLogFormat JSON (formats_json.go uses json.Marshal which escapes \r\n).
  • Deployments using OCSF output.
  • Deployments with SecAuditEngine Off.

References

  • internal/auditlog/formats.go lines 42, 72-80 (Part B), 85-88 (Part C), 93-96 (Part E), 111-118 (Part F), 125 (Part H), 151 (Part K)
  • coraza.conf-recommended - default SecAuditLogFormat Native, SecAuditLogParts ABIJDEFHZ / ABCFHZ variants
  • CWE-117 - Improper Output Neutralization for Logs
  • CWE-93 - CRLF Injection

Threat Intelligence Overview

EPSS Score
0.4%
Top 69% exploitable
Prevalence
Low
niche OWASP Go WAF library, limited production footprint
Threat Intel
1
1 source
Data Quality
5 sources
Confidence: Medium

How this decision was reached

The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.

SignalValue
Severity MEDIUM
CISA KEV No
Public POC No
EPSS 0.4%
Patch available Yes
Active threat No
Deciding rule
MEDIUM severity (CVSS 4.0-6.9)
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision· derived
Scheduled
Exploitation· derived
None
System Exposure· derived
Open
Automatable· derived
Yes
Human Impact· derived
Medium

Priority Score

29
Low Medium High Critical
KEV: 0
EPSS: 0
CVSS: +29
PoC: 0
Weaponized: 0
Threat intel: 0
Gov advisory: 0

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy