CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2025-49136

Listmonk's Dirty Laundry: Exfiltrating Secrets via SSTI

Alon Barad
Alon Barad
Software Engineer

Feb 26, 2026·5 min read·81 visits

Executive Summary (TL;DR)

Critical SSTI in listmonk versions < 5.0.2 allows authenticated users to read host-level environment variables (including secrets) by injecting Sprig helper functions into email templates.

In the world of self-hosted software, 'convenience' is often a polite synonym for 'security hole.' Listmonk, a high-performance newsletter manager written in Go, fell victim to this classic trade-off. By importing the entire Sprig template library without adequate filtering, the application allowed authenticated users to perform Server-Side Template Injection (SSTI). This wasn't just a minor UI glitch; it gave attackers a direct line to the server's environment variables, exposing database passwords, SMTP credentials, and AWS keys in cleartext.

The Hook: When 'Feature-Rich' Becomes 'Leak-Rich'

Listmonk is the darling of the self-hosted marketing world. It’s fast, written in Go, and lets you send millions of emails without paying a cent to Mailchimp. To make emails dynamic—like greeting a user by name or formatting dates—it uses Go's native templating engine. But native Go templates are a bit bare-bones.

To spice things up, the developers integrated Sprig, a library that adds over 100 convenience functions to Go templates. Need to base64 encode a string? Sprig has you covered. Need to format a timestamp? Easy.

But here is the problem: Sprig also includes functions that have absolutely no business being accessible inside a marketing email template. Functions like env (read environment variables) and expandenv (expand system paths). By exposing the default Sprig function map to the user, listmonk effectively turned its template editor into a system shell's printenv command. It’s like installing a smart lock on your front door but leaving a key under the mat, and then broadcasting the location of the mat on a billboard.

The Flaw: The Kitchen Sink Approach

The root cause of CVE-2025-49136 is a classic case of Implicit Trust. The developers trusted the Sprig library to be safe by default. In reality, Sprig is a general-purpose utility belt; it contains sharp knives alongside the harmless sporks.

When listmonk initialized the template engine for campaigns, it loaded the generic Sprig function map. This map includes:

  • os.Getenv: Wraps the system call to read environment variables.
  • os.ExpandEnv: Replaces ${var} in strings with their environment values.

In a secure context, like a CLI tool running on your laptop, these are fine. In a web application where users (even trusted marketing interns) define the template content, this is catastrophic. The application failed to curate this list, blindly passing the ability to read server memory into the hands of the user. It is a textbook breakdown of the Principle of Least Privilege.

The Code: Deleting the Dangerous bits

Let's look at the smoking gun. The vulnerability existed because the code grabbed the default map and served it up raw. The fix, applied in version 5.0.2, is elegantly simple: it manually deletes the dangerous keys from the map before the template engine ever sees them.

Here is the diff from internal/manager/manager.go:

func (m *Manager) makeGnericFuncMap() template.FuncMap {
    // ... existing setup ...
 
    // VULNERABLE CODE (Conceptual Previous State)
    // sprigFuncs := sprig.GenericFuncMap()
    // maps.Copy(funcs, sprigFuncs)
 
    // PATCHED CODE (v5.0.2)
    sprigFuncs := sprig.GenericFuncMap()
    
    // The fix: Explicitly nuke the dangerous functions
    delete(sprigFuncs, "env")
    delete(sprigFuncs, "expandenv")
 
    maps.Copy(funcs, sprigFuncs)
    return funcs
}

> [!NOTE] > This is a "allow-list via deny-list" approach. While effective here, a more robust security posture would be to explicitly allow only the functions you need (e.g., string manipulation and math) rather than trying to delete the ones you know are bad. Who knows what other weird functions Sprig might add in the future?

The Exploit: Hello, {{ env "DB_PASSWORD" }}

Exploiting this requires authenticated access, but don't let that lower your blood pressure. In many organizations, the person managing newsletters has weak credentials, no MFA, or is a third-party contractor. Once inside, the escalation to full infrastructure compromise is trivial.

The Attack Chain:

  1. Access: Log in as a user with campaigns or templates permissions.
  2. inject: Create a new Campaign. In the body editor (switch to Raw HTML to be safe), insert the payload.
  3. Payload Construction: You don't need to guess variable names. Standard Docker setups for listmonk use predictable keys.
<!-- The "I own your database" Payload -->
<p>Welcome to our newsletter!</p>
<p>Debug Info: {{ env "LISTMONK_db__password" }}</p>
<p>AWS Key: {{ env "AWS_SECRET_ACCESS_KEY" }}</p>
  1. Trigger: Click the "Preview" button.
  2. Exfiltration: The server parses the template, executes os.Getenv("LISTMONK_db__password"), and renders the cleartext password right into the preview pane in your browser.

If the attacker wants to be subtle, they could send a "Test Email" to themselves. The server will render the secrets into the email body and kindly deliver them to the attacker's inbox via the configured SMTP server.

The Impact: Why You Should Panic

This is not just about reading the newsletter configuration. Because listmonk is a modern, 12-factor app, it is almost exclusively configured via Environment Variables.

If you run listmonk in Kubernetes or Docker, the process environment likely contains:

  • Database Credentials: Full read/write access to your user data.
  • SMTP Credentials: The ability to send spoofed emails from your domain, or reset passwords on other platforms via email loops.
  • Object Storage Keys: AWS S3 or MinIO credentials used for uploads. An attacker could use these to steal backups or host malware on your domain.

CVSS 9.1 is arguably conservative. If your listmonk instance shares an environment with other services (e.g., a monolithic .env file mounted into multiple containers), this vulnerability compromises your entire stack.

The Fix: Patch and Rotate

The remediation is two-fold. First, stop the bleeding. Second, assume the patient has already lost blood.

Step 1: Update Software Pull the latest Docker image or build from source. You need version v5.0.2 or higher. There is no config change required; the binary itself has been patched to disable the template functions.

Step 2: Rotate Secrets (Mandatory) If you were running a vulnerable version exposed to the internet (or untrusted internal users), you must treat your environment variables as compromised.

  • Change your PostgreSQL password.
  • Generate new SMTP API keys.
  • Rotate AWS IAM keys.

Simply patching the software closes the window, but it doesn't chase the burglar out of the house if they already stole the keys.

Official Patches

listmonkRelease v5.0.2 containing the fix

Fix Analysis (1)

Technical Appendix

CVSS Score
9.1/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H
EPSS Probability
41.27%
Top 3% most exploited

Affected Systems

listmonk < 5.0.2

Affected Versions Detail

Product
Affected Versions
Fixed Version
listmonk
knadh
>= 4.0.0, < 5.0.25.0.2
AttributeDetail
CWECWE-1336 (Improper Neutralization of Special Elements Used in a Template Engine)
Attack VectorNetwork (Authenticated)
CVSS v3.19.1 (Critical)
ImpactInformation Disclosure (High), System Compromise
Exploit StatusPoC Available
ArchitectureGo (text/template + Sprig)

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1552.001Unsecured Credentials: Environment Variables
Credential Access
CWE-1336
Improper Neutralization of Special Elements Used in a Template Engine

Known Exploits & Detection

GitHub Security AdvisoryOriginal advisory containing payload examples and impact analysis.

Vulnerability Timeline

Internal identification of Sprig misconfiguration
2025-05-25
Patch committed by maintainer
2025-06-08
Public disclosure (GHSA) and Release v5.0.2
2025-06-09

References & Sources

  • [1]NVD - CVE-2025-49136
  • [2]Fix Commit on GitHub

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•2 days ago•GHSA-7PPR-R889-MCF2
7.5

GHSA-7PPR-R889-MCF2: Unbounded WebSocket Message Aggregation in http4s-blaze-server leads to Denial of Service

An uncontrolled resource consumption vulnerability exists in the Scala-based http4s-blaze-server package of the http4s/blaze library. The vulnerability allows remote, unauthenticated attackers to cause an Out of Memory Error (OOM) and JVM crash by streaming a continuous sequence of small or empty WebSocket continuation frames with the FIN bit set to 0. This bypasses typical payload size checks because of the JVM's per-object allocation overhead, leading to rapid heap exhaustion with minimal network bandwidth.

Alon Barad
Alon Barad
7 views•5 min read
•2 days ago•GHSA-95CV-R8X4-VH75
7.6

GHSA-95cv-r8x4-vh75: Path Traversal Vulnerability in OpenList Batch Rename Handler

A critical path traversal vulnerability has been identified in the OpenList Go-based backend package. The vulnerability exists within the batch rename handler because the application does not validate the source filename parameter before constructing filesystems paths. This omission allows authenticated users to escape their designated directory and rename files in sibling paths.

Amit Schendel
Amit Schendel
9 views•7 min read
•2 days ago•GHSA-P6PH-3JX2-3337
4.3

GHSA-P6PH-3JX2-3337: Horizontal Privilege Escalation and Metadata Information Disclosure via Bleve Search in OpenList

OpenList version 4.2.3 and prior is vulnerable to an authorization bypass and metadata leakage. When configured with the Bleve search engine backend, OpenList fails to perform separator-aware path matching when validating tenant containment. This allows authenticated users to access sibling directories sharing similar name prefixes. Furthermore, the search backend returns unfiltered global result counts, leaking existence verification data of unauthorized files via side-channel analysis.

Amit Schendel
Amit Schendel
8 views•5 min read
•2 days ago•GHSA-86CX-WWF4-PHQ4
6.5

GHSA-86cx-wwf4-phq4: Path Prefix Confusion Authorization Bypass in OpenList

An authorization bypass vulnerability in OpenList version 4.2.3 and below allows authenticated users to read arbitrary files outside of their designated base directories due to an insecure path prefix check using Go's standard strings.HasPrefix function.

Amit Schendel
Amit Schendel
7 views•6 min read
•2 days ago•CVE-2026-16584
7.0

CVE-2026-16584: Security Policy Bypass in AWS API MCP Server via Startup Initialization Failure

A security policy bypass vulnerability exists in the AWS API MCP Server (awslabs-aws-api-mcp-server) from version 0.2.13 through 1.3.46. When the server fails to load the read-only operations index during startup (due to transient network failures, file permission issues, or other exceptions), it logs a warning but continues running in an insecure, degraded state. Under this condition, the security policy engine fails open, silently skipping all subsequent security checks and consent prompts for the lifetime of the process. This permits unauthorized mutating AWS CLI commands to execute via indirect prompt injection attacks.

Amit Schendel
Amit Schendel
12 views•7 min read
•2 days ago•GHSA-6V4M-FW66-8R4X
6.5

GHSA-6V4M-FW66-8R4X: Path Disclosure and Shell Expansion Bypass in Shescape

An incomplete escaping vulnerability in the npm package 'shescape' allows unauthenticated users to trigger dynamic shell expansions, absolute path disclosure, and command block break-outs on Unix and Windows systems.

Alon Barad
Alon Barad
6 views•7 min read