Zammad CVE-2026-102489: Session Leak to RCE
Summary
- CVE
- CVE-2026-102489
- Published
- Collected
📦 Full-Text Content Snapshot
R2 Archive · Full Article PreservedAuthor: Zach Hanley · Published: October 7, 2026 · Source: horizon3.ai

Introduction
On 24 September 2026, the Dutch Institute for Vulnerability Disclosure (DIVD) announced publicly that they had suffered a security incident and had attributed it to an “agentic AI powered attack” given the forensic artifacts they discovered during the incident response. They attributed the source of the initial breach to Zammad, a helpdesk and ticketing application.
During their investigation, they determined that two distinct 0-day vulnerabilities were abused:
- CVE-2026-102489 – A session hijack that ultimately allows executing code as the
zammaduser. - CVE-2026-102490 – A privilege escalation that allows escalating to
root.
Soon after, DIVD released further details of the Zammad vulnerabilities and released an Indicators of Compromise script which looked for leaked session cookies in error logs.
CVE-2026-102489: Zammad Session Leak
Given the above details, it was classified as a session hijack and that session cookies would appear in the logs, so we dug in.
We prompted a vulnerability research harness, with Anthropic’s Opus 4.8 as the model, to attempt to identify and reproduce the issues given:
- The DIVD CSIRT cases
- The DIVD IOC script
- The Zammad open-source GitHub repository
After a couple hours, the results were back and the harness did confirm that if there was a way to trigger an error it would leak the session cookie strings, but it was unable to find an unauthenticated trigger request.
Fuzzing The Code
Re-prompting the agent, we advised it to build fuzzing tooling to target the areas of code it suspected most likely to be associated with the vulnerable area of code. Several minutes later into a fuzzing campaign against the websocket code, it triggered an error that was reflected back to the requestor which contained the session cookies we were looking for.
The vulnerability trigger is a simple single request to the WebSocket endpoint, /ws, with a payload of {"event": "base"}.

Figure 1. Triggering the leak
The server then reflects this error back to the client, which leaks the cookies for all active users.

Figure 2. Example exploit request
Understanding the Source
Starting from the architectural perspective, Zammad is a Ruby application that utilizes websockets. It stores all global connection states in the @clients class-level instance variable. The headers variable notably includes the session Cookie header.

Figure 3. websocket_server.rb storing headers
Every event that occurs in the framework, the @clients variable is passed with it. There is no event type or client based filtering.

Figure 4. websocket_server.rb event dispatching
The base event handler for the session object takes every parameter passed to it and unpacks each key-value pair stored in it. Which means the sensitive cookies are stored inside the headers key of the clients variable.

Figure 5. sessions/event/base.rb handler
Lastly, in sessions/event.rb, the run() method returns the entire event’s instance variables in a response to the client when an error occurs.

Figure 6. Returns event variables in response to client
When a client sends {"event":"base"}, the dispatcher successfully resolves Sessions::Event::Base as a real Ruby constant, instantiates it with the full @clients registry mass-assigned onto the object, then fails when .run is called – as Base has no implementation. Ruby constructs the NoMethodError message to include the receiver’s full object representation, which contains every instance variable including @clients, and sessions/event.rb returns that message string directly to the caller.
Authenticated Session to Code Execution
Once an attacker has a valid admin session cookie from the leak, they can write arbitrary files into the Zammad application directory via the package installation endpoint. By writing a malicious ERB template that overrides the built-in password reset email view, they can trigger its execution by initiating a password reset for any user – causing Zammad’s mailer to render the attacker-controlled template with full Ruby execution privileges, achieving remote code execution as the zammad OS user.

Figure 7. Exploit in action
Our proof of concept exploit can be found here: https://github.com/horizon3ai/CVE-2026-102489
Given that the privilege escalation vector we believe to be CVE-2026-102490 remains unpatched, we will be withholding those details.
References
📦 Full-Text Markdown Snapshot archived by Phying News · Original source: horizon3.ai
---
id: 10177
canonical_url: "https://phying.com/item/10177"
title: "Zammad CVE-2026-102489: Session Leak to RCE"
type: "vulnerability"
cve: "CVE-2026-102489"
cvss: null
severity: "high"
vendor: "Zammad"
product: "Zammad"
affected_versions: "Zammad <= 6.3.1"
source_domain: "horizon3.ai"
source_url: "https://horizon3.ai/attack-research/disclosures/cve-2026-102489-zammad-session-leak-rce/"
published_at: "2026-10-07T10:00:00Z"
snapshot_at: "2026-10-26T05:50:00Z"
archived_by: "Phying News (https://phying.com/item/10177)"
lang: "en"
---
# Zammad CVE-2026-102489: Session Leak to RCE
*Author: Zach Hanley · Published: October 7, 2026 · Source: [horizon3.ai](https://horizon3.ai/attack-research/disclosures/cve-2026-102489-zammad-session-leak-rce/)*

## **Introduction**
On 24 September 2026, the Dutch Institute for Vulnerability Disclosure (DIVD) announced publicly that they had suffered a security incident and had attributed it to an “agentic AI powered attack” given the forensic artifacts they discovered during the incident response. They attributed the source of the initial breach to [Zammad](https://github.com/zammad/zammad), a helpdesk and ticketing application.
During their investigation, they determined that two distinct 0-day vulnerabilities were abused:
1. **CVE-2026-102489** – A session hijack that ultimately allows executing code as the `zammad` user.
2. **CVE-2026-102490** – A privilege escalation that allows escalating to `root`.
Soon after, DIVD released further details of the Zammad vulnerabilities and released an Indicators of Compromise script which looked for leaked session cookies in error logs.
## **CVE-2026-102489: Zammad Session Leak**
Given the above details, it was classified as a session hijack and that session cookies would appear in the logs, so we dug in.
We prompted a vulnerability research harness, with Anthropic’s Opus 4.8 as the model, to attempt to identify and reproduce the issues given:
1. The DIVD CSIRT cases
2. The DIVD IOC script
3. The Zammad open-source GitHub repository
After a couple hours, the results were back and the harness did confirm that if there was a way to trigger an error it would leak the session cookie strings, but it was unable to find an unauthenticated trigger request.
### Fuzzing The Code
Re-prompting the agent, we advised it to build fuzzing tooling to target the areas of code it suspected most likely to be associated with the vulnerable area of code. Several minutes later into a fuzzing campaign against the websocket code, it triggered an error that was reflected back to the requestor which contained the session cookies we were looking for.
The vulnerability trigger is a simple single request to the WebSocket endpoint, `/ws`, with a payload of `{"event": "base"}`.

**Figure 1.** Triggering the leak
The server then reflects this error back to the client, which leaks the cookies for all active users.

**Figure 2.** Example exploit request
### **Understanding the Source**
Starting from the architectural perspective, Zammad is a Ruby application that utilizes websockets. It stores all global connection states in the `@clients` class-level instance variable. The `headers` variable notably includes the session `Cookie` header.

**Figure 3.** `websocket_server.rb` storing headers
Every event that occurs in the framework, the `@clients` variable is passed with it. There is no event type or client based filtering.

**Figure 4.** `websocket_server.rb` event dispatching
The base event handler for the session object takes every parameter passed to it and unpacks each key-value pair stored in it. Which means the sensitive cookies are stored inside the `headers` key of the `clients` variable.

**Figure 5.** `sessions/event/base.rb` handler
Lastly, in `sessions/event.rb`, the `run()` method returns the entire event’s instance variables in a response to the client when an error occurs.

**Figure 6.** Returns event variables in response to client
When a client sends `{"event":"base"}`, the dispatcher successfully resolves `Sessions::Event::Base` as a real Ruby constant, instantiates it with the full `@clients` registry mass-assigned onto the object, then fails when `.run` is called – as `Base` has no implementation. Ruby constructs the `NoMethodError` message to include the receiver’s full object representation, which contains every instance variable including `@clients`, and `sessions/event.rb` returns that message string directly to the caller.
### **Authenticated Session to Code Execution**
Once an attacker has a valid admin session cookie from the leak, they can write arbitrary files into the Zammad application directory via the package installation endpoint. By writing a malicious ERB template that overrides the built-in password reset email view, they can trigger its execution by initiating a password reset for any user – causing Zammad’s mailer to render the attacker-controlled template with full Ruby execution privileges, achieving remote code execution as the `zammad` OS user.

**Figure 7.** Exploit in action
Our proof of concept exploit can be found here: [https://github.com/horizon3ai/CVE-2026-102489](https://github.com/horizon3ai/CVE-2026-102489)
Given that the privilege escalation vector we believe to be CVE-2026-102490 remains unpatched, we will be withholding those details.
## References
- [https://csirt.divd.nl/cases/DIVD-2026-00014/](https://csirt.divd.nl/cases/DIVD-2026-00014/)
- [https://csirt.divd.nl/cases/DIVD-2026-00015/](https://csirt.divd.nl/cases/DIVD-2026-00015/)
---
> 📦 **Full-Text Markdown Snapshot** archived by [Phying News](https://phying.com/item/10177) · Original source: [horizon3.ai](https://horizon3.ai/attack-research/disclosures/cve-2026-102489-zammad-session-leak-rce/)