Jun 15, 2026·6 min read·17 visits
Nodemailer's disableFileAccess and disableUrlAccess security flags are bypassed when using jsonTransport or the attachDataUrls feature, enabling unauthorized local file reads and server-side request forgery.
Nodemailer prior to version 8.0.9 contains a security control bypass vulnerability. Transport-level configuration parameters designed to restrict local file system access and remote URL requests are not propagated to all content-resolution execution paths. This failure allows unauthorized local file inclusion and server-side request forgery when the application utilizes specific transports or processing flags.
Nodemailer is a widely utilized package within the Node.js ecosystem for handling SMTP and alternative email transport operations. To mitigate security risks associated with dynamically defined attachments and message structures, Nodemailer exposes two critical security configuration options: disableFileAccess and disableUrlAccess. When enabled, these parameters are intended to act as security boundaries, preventing unauthorized access to the host's local file system and blocking arbitrary outbound HTTP or HTTPS requests.
However, a security control bypass exists in versions of Nodemailer preceding version 8.0.9. The vulnerability is characterized by a failure to propagate these access-restriction flags across all internal content-resolution pathways. Specifically, when an application utilizes the jsonTransport configuration or relies on pre-processing options such as attachDataUrls, Nodemailer performs resource pre-resolution outside of the standard security filter architecture.
This bypass allows attackers who can control the structured elements of an email (such as attachment paths or body properties) to retrieve local system files and initiate outbound network connections. This behavior completely bypasses the security controls established by developers, transforming a restricted mail utility into a vector for local file inclusion (LFI) and Server-Side Request Forgery (SSRF).
The root cause of this vulnerability lies in the architectural divergence between standard message streaming paths and serialization/pre-resolution paths. In a conventional SMTP or file-based transport sequence, file and URL validation is performed inside lib/mime-node/index.js during the _getStream() execution cycle. The transport explicitly transfers its configuration parameters to the mime-node instance, which evaluates disableFileAccess and disableUrlAccess immediately before opening filesystem descriptors or initializing TCP connections.
Conversely, when jsonTransport is configured, Nodemailer bypasses the normal streaming process to output a serialized JSON string representing the email structure. This transport delegates serialization to a normalization workflow defined in lib/mailer/mail-message.js via the resolveAll() function. The purpose of resolveAll() is to evaluate and flatten any lazy or asynchronously defined content properties, such as attachment arrays, inline images, or complex text blocks, prior to compiling the final output.
During this normalization process, resolveAll() iterates over individual components of the message and invokes the utility helper function shared.resolveContent() from lib/shared/index.js. This helper handles the low-level retrieval of resources, directly invoking fs.createReadStream() for file paths and nmfetch() for HTTP/HTTPS requests. Because shared.resolveContent() was designed as a low-level utility, it does not receive, evaluate, or enforce the configuration context containing the disableFileAccess and disableUrlAccess policy restrictions, leading to a complete security bypass.
The execution flow and omission can be traced through the following code comparisons. In vulnerable versions (< 8.0.9), lib/shared/index.js resolved the local or remote contents without checking the transport's restrictions.
// Vulnerable Implementation (lib/shared/index.js)
function resolveContent(data, key, callback) {
let content = data[key];
if (content && content.path) {
// BUG: Directly resolves the local file path without validation
let stream = fs.createReadStream(content.path);
// ... stream reading logic ...
} else if (content && content.href) {
// BUG: Directly fetches the remote URL without checking policy
let req = nmfetch(content.href);
// ... fetch logic ...
}
}During jsonTransport invocation, lib/mailer/mail-message.js triggers this helper directly during the normalization phase:
// lib/mailer/mail-message.js (resolveAll execution flow)
resolveAll(callback) {
// ... loops over attachments, html, text ...
shared.resolveContent(attachment, 'path', (err, data) => {
// The configuration options are not passed to shared.resolveContent()
// Results in automatic, unauthorized file resolution into base64
});
}To correct this vulnerability, the internal architecture was refactored to pass the transport option context down through the resolution chain. The code below represents the conceptual fix deployed in version 8.0.9:
// Patched Implementation (lib/shared/index.js)
function resolveContent(data, key, options, callback) {
if (typeof options === 'function') {
callback = options;
options = {};
}
let content = data[key];
// Verify local file access policy before reading
if (content && content.path) {
if (options.disableFileAccess) {
return callback(new Error('EFILEACCESS'));
}
let stream = fs.createReadStream(content.path);
// ...
}
// Verify outbound request policy before fetching
if (content && content.href) {
if (options.disableUrlAccess) {
return callback(new Error('EURLACCESS'));
}
let req = nmfetch(content.href);
// ...
}
}An attacker can exploit this vulnerability if the application permits user input to influence the properties of the message structure, and subsequently uses a vulnerable transport (like jsonTransport) or pre-processing settings (like attachDataUrls).
For a local file inclusion attack, the threat actor submits an email configuration structure containing a specific local file path in the attachment list. Even if the developer configured the transport with disableFileAccess: true, Nodemailer's serialization flow ignores this policy. The system reads the target file and base64-encodes its contents into the attachment object of the returned JSON string.
For a server-side request forgery attack, the threat actor specifies a sensitive local network resource inside the body href, such as the cloud instance metadata endpoint. When Nodemailer processes the object, it performs a GET request to the endpoint and injects the returned response directly into the serialized body field of the JSON structure, disclosing sensitive session credentials or environment data to the attacker.
The impact of this vulnerability depends heavily on the context in which the mail data is handled and where the serialized JSON string is stored or transmitted. In applications that use jsonTransport to buffer messages in external queue systems or databases, an attacker can extract any file readable by the Node.js runtime process, including API credentials, SSL certificates, environment variables, and application source code.
From an SSRF perspective, because outbound connections originate directly from the application server, this vulnerability enables attackers to bypass network perimeters. Attackers can scan local network ranges, query metadata services, and interact with internal administrative tools that trust localhost or local subnet connections.
This vulnerability is assigned a CVSS score of 5.4 (Medium). It requires low privileges to execute, has low complexity, and does not require user interaction. However, because it relies on the specific application configurations of using jsonTransport or attachDataUrls, it is not universally exploitable on all Nodemailer installations.
The primary remediation for this vulnerability is upgrading the nodemailer dependency to version 8.0.9 or higher. This version correctly propagates transport-level security policies into the shared content resolution engine, preventing file reads and remote fetches when access flags are set.
If upgrading the library is not immediately possible, developers must validate all input structures before passing them to the mail utility. Applications should implement recursive validation schemas to ensure that attachment definitions do not contain arbitrary string paths or external URLs.
Furthermore, developers should enforce host-level security policies. Operating system permissions should restrict the Node.js process to only the necessary directories, and firewall rules should block unauthorized outbound connections from the application server to internal subnets or cloud provider metadata services.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
nodemailer Nodemailer | < 8.0.9 | 8.0.9 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-610 |
| Attack Vector | Network |
| CVSS Score | 5.4 |
| EPSS Score | 0.012 |
| Impact | Information Disclosure / Server-Side Request Forgery |
| Exploit Status | poc |
| KEV Status | Not Listed |
The product uses an externally controlled reference to a resource, allowing an attacker to access unauthorized files or network resources.
An SSRF vulnerability exists in Flyto2 Core due to improper validation of intermediate HTTP redirect hops. While the initial request target is validated against an SSRF protection policy, the HTTP client library (aiohttp) transparently follows 30x redirects to local, internal, or cloud metadata endpoints without application-level revalidation.
A logic vulnerability exists in @dynatrace-oss/dynatrace-mcp-server prior to version 1.8.7. The create_dynatrace_notebook tool lacks a human-approval gate, allowing an attacker to exploit indirect prompt injection to force the underlying LLM client to create persistent Dynatrace notebooks without the operator's consent.
A critical authentication and authorization bypass vulnerability in the Quarkus Java framework exists due to a parser differential mismatch between the HTTP security policy layer and downstream handlers. By leveraging encoded reserved characters such as semicolons, slashes, and backslashes, attackers can bypass configured path-based security policies to gain unauthorized access to secure administrative endpoints and static resources.
A critical code injection vulnerability exists in @aws/agentcore CLI (AWS AgentCore CLI) during the Bedrock Agent import lifecycle. An authenticated remote attacker with permissions to configure Bedrock collaborator attributes can inject python code by embedding triple-double-quotes (""") inside the collaborationInstruction metadata field. The CLI formats this metadata directly into a Python docstring in a generated main.py file without adequate escaping, leading to arbitrary code execution when the imported agent is run or deployed.
GHSA-WCHH-9X6H-7F6P documents the critical deprecation of the cryptographic library libolm (Olm) and its Python binding wrapper python-olm, which matrix-commander depended upon via its downstream client library matrix-nio. Multiple cryptographic vulnerabilities (timing leaks, side-channels, signature malleability, and protocol confusion) were disclosed in 2022 and 2024. Because libolm is unmaintained, Python clients using matrix-commander are considered cryptographically unsafe until migrating to vodozemac.
An Excessive Data Exposure vulnerability in Easy!Appointments v1.5.2 allows low-privileged administrative users, such as restricted Providers and Secretaries, to harvest unique, stateless appointment hashes belonging to other providers. These hashes act as capability tokens, granting full authorization to reschedule, take over, or delete appointments via stateless endpoints, resulting in a complete Broken Object Level Authorization (BOLA) scenario.