June 29, 2026
CVE-2026–39904: How I Crashed an Entire Server Using Nothing but a DOCX File?
Welcome Researchers!

By Ashik Mohamed ( ashikmd7 )
7 min read
Welcome Researchers!
I hope you are all doing great.
For those who are reading my articles for the first time, I'm Ashik Mohamed (ashikmd7), and I currently work as an Application Security Engineer at CircleLytics, a Netherlands-based SaaS company specializing in collective intelligence & collaborative decision-making.
In this article, I would like to share my journey of discovering CVE-2026–39904, a vulnerability in GoPhish v0.12.1 that allows a low-privileged user to completely crash the entire server simply by uploading a specially crafted Office document:
What makes this finding even more interesting is that the issue was initially questioned during the disclosure process because it was believed to be exploitable only by administrators. However, after performing additional analysis and providing supporting evidence, I was able to demonstrate that even a standard user account could exploit the vulnerability, ultimately leading to CVE assignment.
So, let's dive in…
Introducing GoPhish
For those unfamiliar with GoPhish, it is one of the most widely used open-source phishing frameworks, designed to help security professionals and organizations conduct phishing simulations and security awareness campaigns. With more than 14,000+ stars on GitHub, the project has established itself as a trusted and widely adopted tool within the cybersecurity community.
GoPhish provides features such as:
- Campaign management
- Email template creation
- Landing page hosting
- User and group management
- Detailed campaign reporting
With that in mind, I decided to take a closer look at one of the platform's core features: email attachments. Since phishing campaigns frequently rely on Office documents and other attachments, I decided to explore this functionality further to see whether the file-processing workflow introduced any unexpected behavior.
Understanding How Email Attachments Work
While exploring the application, I noticed that users are allowed to create email templates and attach files to phishing emails.
Since GoPhish supports attaching Office documents such as:
.docx.pptx.xlsx
At first glance, the workflow appeared straightforward: a user uploads a document, associates it with an email template, saves the template, and later uses it in a campaign.
However, one question immediately came to mind:
What exactly happens to this file after it reaches the backend?
Modern Office documents are far more than simple files, they are ZIP archives containing numerous internal components and metadata files. Because parsing complex file formats has historically introduced security issues, I decided to trace the attachment-processing workflow in greater detail.
That investigation eventually led me to discover CVE-2026–39904.
Looking Behind the Scenes
Since GoPhish is completely open source, I decided to inspect the source code responsible for attachment processing.
After tracing the code flow, I discovered that uploaded attachments are validated using the ApplyTemplate() function located in:
models/attachment.gomodels/attachment.goWhile reviewing the implementation of attachment.go, I encountered the following logic:
// File: models/attachment.go
for _, zipFile := range zipReader.File {
ff, err := zipFile.Open()
if err != nil {
return nil, err
}
// Entire uncompressed file is loaded into memory
// without any size restriction.
contents, err := ioutil.ReadAll(ff)
if err != nil {
return nil, err
}
// Further processing...
}// File: models/attachment.go
for _, zipFile := range zipReader.File {
ff, err := zipFile.Open()
if err != nil {
return nil, err
}
// Entire uncompressed file is loaded into memory
// without any size restriction.
contents, err := ioutil.ReadAll(ff)
if err != nil {
return nil, err
}
// Further processing...
}At first glance, this may not look particularly dangerous. But there is something extremely important to understand.
The application reads each file extracted from the Office document directly into memory using ioutil.ReadAll(). Because Office documents are ZIP archives internally, this means that GoPhish fully decompresses and loads archive entries into memory without enforcing any limits on their size.
In other words, there are no safeguards restricting how much data can be extracted or allocated during processing:
- No maximum extraction limits.
- No validation of decompressed file size.
- No memory usage restrictions.
- No protection against maliciously crafted archives.
As soon as I saw this, a question immediately came to mind:
What would happen if a ZIP bomb were uploaded while masquerading as a legitimate
.docxfile?
Creating a Malicious Office Document
To test this hypothesis, I decided to create a highly compressed file that would expand to several gigabytes when decompressed.
The idea was straightforward.
- Generate a file containing several gigabytes of null bytes.
- Compress it into a ZIP archive.
- Rename the archive to
.docx. - Upload it to GoPhish.
I wrote a small Python script to generate the archive:
import zipfile
payload_size = 5 * 1024 * 1024 * 1024
with zipfile.ZipFile("bomb.zip", "w", zipfile.ZIP_DEFLATED) as z:
z.writestr("huge.bin", b"\x00" * payload_size)
print("Created bomb.zip")import zipfile
payload_size = 5 * 1024 * 1024 * 1024
with zipfile.ZipFile("bomb.zip", "w", zipfile.ZIP_DEFLATED) as z:
z.writestr("huge.bin", b"\x00" * payload_size)
print("Created bomb.zip")Once the archive was generated, I simply renamed it:
The resulting file remained relatively small. However, once decompressed, it would occupy approximately 5 GB of memory.
Starting the Test
I logged into the application and navigated to the Email Template creation page:
Before uploading the malicious document, I wanted to establish a baseline so that I could accurately observe any changes in resource consumption during the test. To do this, I used htop to monitor the application's memory usage in real time and capture the normal operating state before triggering the vulnerability:
Everything looked healthy, as confirmed by the htop output shown above. The server remained stable, memory consumption was minimal, and no abnormal resource spikes were observed. With the environment appearing normal, it was now time to upload the malicious document and observe how the server behaved under attack conditions.
Uploading the Malicious File
I selected the crafted exploit.docx file and uploaded it as an attachment.
After uploading the file, I clicked the Save Template button.
The moment the template was saved, the backend started processing the attachment. And that's when things became interesting.
Something Strange Happened…
Within seconds, I noticed a dramatic spike in memory consumption. The GoPhish process started allocating an enormous amount of memory.
The memory usage continued increasing until the operating system eventually stepped in. Shortly afterward, the GoPhish process was terminated entirely.
The shell displayed:
zsh: killed ./gophishzsh: killed ./gophishAnd just like that…
The Entire Server went Offline.
No additional interaction was required. A single malicious Office document uploaded by an authenticated user was sufficient to completely crash the application.
Why Does This Happen?
The root cause is fairly straightforward.
The vulnerable code uses:
contents, err := ioutil.ReadAll(ff)contents, err := ioutil.ReadAll(ff)ioutil.ReadAll() attempts to read everything from the supplied stream until EOF is reached.
When processing a malicious Office document containing a highly compressed file, GoPhish attempts to decompress and load the entire content into memory.
Since no size restrictions exist, the application eventually exhausts available system memory.
As a result:
- Memory consumption skyrockets.
- The operating system's OOM killer intervenes.
- The GoPhish process is terminated.
- The entire application becomes unavailable.
But There Was One More Challenge…
After responsibly reporting the issue, the initial response from the Security Team indicated that the finding was believed to be exploitable only by administrators. The concern was understandable.
If only administrators could exploit the issue, one could argue that administrators already possess extensive control over the application.
At first, this seemed like a potential roadblock. However, during my testing, I had already verified something important. The vulnerable functionality was not restricted to administrators.
A standard user account could also create email templates and upload Office attachments. This completely changes the security impact.
Proving the Security Impact
To validate my assumption, I revisited the Official Documentation and performed additional testing. I confirmed that users with the default User role can create Email Templates and upload attachments.
This meant that exploitation did not require administrative privileges.
Any authenticated low-privileged user could:
- Log into GoPhish.
- Create an email template.
- Upload a malicious Office document.
- Crash the entire server.
I shared this evidence with the Security Team and explained why the issue crossed a meaningful security boundary. Although standard users are expected to manage campaigns and templates, they are certainly not expected to completely exhaust server resources and deny access to administrators and all other users.
After reviewing the additional evidence, the Security Team agreed with the assessment.
Shortly afterward, the vulnerability was assigned: CVE-2026–39904
Impact
The impact of this vulnerability is significant because a low-privileged authenticated user can trigger a complete denial of service simply by uploading a specially crafted Office document.
Despite requiring only minimal privileges, successful exploitation causes the entire GoPhish process to crash, rendering the management interface inaccessible to all users, including administrators.
As a result, ongoing phishing campaigns are interrupted, new campaigns cannot be launched, and administrators are effectively locked out until the service is manually restarted. In other words, a single malicious document uploaded by a low-privileged user is sufficient to bring down the entire phishing infrastructure.
How Can Developers Fix This?
Applications should never read unbounded amounts of data from user-controlled archives. Since Office documents such as .docx, .pptx, and .xlsx files are ZIP archives internally, they should enforce strict validation before extracting and processing their contents.
Before reading any archive entry, the application should validate both the compressed and uncompressed sizes and reject files that exceed predefined limits. Additionally, the extraction logic should track the cumulative size of all extracted entries and impose limits on the total number of files processed in order to mitigate ZIP bomb attacks.
Most importantly, direct usage of ioutil.ReadAll() on attacker-controlled input should be avoided, as it allows unbounded memory allocation.
Instead, extraction should be performed using io.LimitedReader or an equivalent mechanism to enforce strict size limits.
For example:
const maxFileSize = 50 * 1024 * 1024 // 50MB
lr := &io.LimitedReader{
R: ff,
N: maxFileSize,
}
contents, err := ioutil.ReadAll(lr)
if lr.N == 0 {
return nil, errors.New("attachment exceeds maximum allowed size")
}const maxFileSize = 50 * 1024 * 1024 // 50MB
lr := &io.LimitedReader{
R: ff,
N: maxFileSize,
}
contents, err := ioutil.ReadAll(lr)
if lr.N == 0 {
return nil, errors.New("attachment exceeds maximum allowed size")
}Implementing safeguards such as these ensures that malicious Office documents cannot trigger excessive memory consumption, effectively preventing ZIP bomb attacks and application-wide denial-of-service conditions.
Final Thoughts
This research once again demonstrates that even seemingly harmless functionality such as attachment processing can introduce significant security risks.
It also highlights another important lesson for vulnerability researchers. Sometimes discovering the vulnerability is only half the work. Being able to explain why the issue matters, prove privilege boundaries, and provide convincing evidence is equally important.
I hope you found this article useful :-)
If you enjoyed reading it or have any thoughts, feel free to connect with me on LinkedIn. Until next time. Happy hacking!