BACK HOME
November 2024
RESEARCH

Email Parser Discrepancy in Nodemailer

#Security Research
#Nodemailer
#Email Parser
#RFC 5322
#GHSA-mm7p-fcc7-pg87

Email Parser Discrepancy in Nodemailer

TL;DR

  • This blog reveals two issues in Nodemailer’s email address parser. The first was fixed in v6.9.16.
  • The second issue was later reported as a security advisory and patched in v7.0.7. See GHSA-mm7p-fcc7-pg87.

After reading Splitting the Email Atom research, I set out to find a zero-day bug in Nodemailer for one of my CTF challenges. I discovered that Nodemailer was not correctly parsing certain valid email addresses. Consider this example:

"test@0xhexr4.htb"@google.com

According to RFC 5322, this is a valid email address. The portion "test@0xhexr4.htb" is a quoted local-part, which allows the @ character. The domain is google.com. Thus, the mailbox is "test@0xhexr4.htb" at the domain google.com.

However, Nodemailer’s parser attempts to identify the address by splitting at the first @ found outside of a properly recognized quoted local-part. Here’s a snippet (taken from Nodemailer’s code) showing how it separates tokens into different lists:

data = {
    address: [],
    comment: [],
    group: [],
    text: []
};

When Nodemailer encounters "test@0xhexr4.htb"@google.com, it correctly identifies the quoted string "test@0xhexr4.htb" as the local-part, but then treats the subsequent @google.com segment as non-quoted “text.” It fails to recognize that google.com is the domain. Instead, it might parse the input as:

[{
    name: "@google.com",
    address: "test@0xhexr4.htb"
}]

This results in Nodemailer interpreting "test@0xhexr4.htb" as the entire mailbox and @google.com as a display name, effectively losing the actual domain information (google.com).

I reported this to the Nodemailer team, hoping it might be treated as a security issue, since incorrect parsing could lead to emails being sent to the wrong domain. However, they considered it a regular bug rather than a security flaw. They fixed this issue in version 6.9.16 without providing credit.

Nodemailer Issue 1 Nodemailer Issue 2

Nodemailer Zero Day

Accepting their stance, I moved on and found another problem. I found out that it is still vulnerable to the same kind of issue. For example, consider this payload:

"test@email.htb x"@interstellar.htb

It exhibits similar behavior, and the email is sent to the test mailbox on email.htb rather than interstellar.htb.

If we parse the following email using a library such as Email-Addresses:

Welcome to Node.js v23.3.0.
Type ".help" for more information.
> addrs = require("email-addresses")
[Function: parse5322] {
    parseOneAddress: [Function: parseOneAddressSimple],
    parseAddressList: [Function: parseAddressListSimple],
    parseFrom: [Function: parseFromSimple],
    parseSender: [Function: parseSenderSimple],
    parseReplyTo: [Function: parseReplyToSimple]
}
> addrs.parseOneAddress(`"test@email.htb x"@interstellar.htb`)
{
    parts: {
    name: null,
    address: {
        name: 'addr-spec',
        tokens: '"test@email.htb x"@interstellar.htb',
        semantic: 'test@email.htb x@interstellar.htb',
        children: [Array]
    },
    local: {
        name: 'local-part',
        tokens: '"test@email.htb x"',
        semantic: 'test@email.htb x',
        children: [Array]
    },
    domain: {
        name: 'domain',
        tokens: 'interstellar.htb',
        semantic: 'interstellar.htb',
        children: [Array]
    },
    comments: []
    },
    type: 'mailbox',
    name: null,
    address: 'test@email.htb x@interstellar.htb',
    local: 'test@email.htb x',
    domain: 'interstellar.htb',
    comments: '',
    groupName: null
}
>

The domain is “interstellar.htb”. I showcased this second bug in the University CTF 2024 Intergalactic Bounty web challenge.

Update: Second Issue Patched (October 2025)

I eventually reported this second issue as a security advisory to the Nodemailer team. The advisory was published as GHSA-mm7p-fcc7-pg87 and the issue was patched in v7.0.7 on October 6, 2025.

The core problem was identical to the first issue — the email parsing library incorrectly handles quoted local-parts containing @, leading to misrouting of email recipients where the parser extracts and routes to an unintended domain instead of the RFC-compliant target.

Payload: "xclow3n@gmail.com x"@internal.domain

Instead of sending to internal.domain, Nodemailer would extract and route the email to gmail.com. This could lead to:

  • Email misdelivery / data leakage — emails sent to unintended external domains
  • Filter evasion — logs and anti-spam systems bypassed by hiding recipients inside quoted local-parts
  • Domain-based access control bypass in downstream applications using Nodemailer

Both issues are now fixed. These findings highlight how subtle RFC 5321/5322 parsing errors can lead to real security impact in widely-used libraries.