CVE-2026-68899
Executive Summary
CVE-2026-68899 is a stored cross-site scripting (XSS) vulnerability in Wekan, an open-source kanban board application built on the Meteor framework, affecting versions prior to 9.90. An authenticated board member can upload HTML content containing JavaScript disguised as an image file (e.g., image/png MIME type) which bypasses the content-based MIME validation check due to a silent failure in the detectMimeFromFile() function when the Unix file command binary is unavailable on the server. This vulnerability carries a CVSS score of 8.7 (High) and requires the attacker to be an authenticated board member with upload privileges, with victim interaction (another user opening the file) to trigger execution. Successful exploitation results in stored active content being served from the Wekan origin, enabling arbitrary JavaScript execution in the context of other users' sessions. The vulnerability is patched in version 9.90.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Technical Analysis
The vulnerability resides in Wekan's file upload validation logic, specifically in the interaction between isFileValid() in models/fileValidation.js and detectMimeFromFile(). The validation process was designed to use the Unix file command for content-based MIME type detection, which serves as a critical security boundary preventing users from uploading dangerous content types (such as HTML with embedded JavaScript) by merely changing the file extension or the HTTP Content-Type header.
The core flaw exists in the error handling of detectMimeFromFile(). On deployments where the file binary is not present on the host system (a common situation in minimal Docker deployments or containerized environments), this function silently returns undefined rather than raising an error or failing closed. The subsequent validation logic in isFileValid() then falls back to trusting the attacker-controlled fileObj.type property, which is supplied through server/routes/attachmentApi.js. This means the MIME type check effectively becomes a client-provided value with no server-side verification.
The exploitation prerequisite is the deployment configuration WITH_API=true. This environment flag enables the API routes that expose the file upload functionality. On deployments where this flag is not enabled, the vulnerable code path (attachmentApi.js) is not reachable, and the vulnerability is not exploitable.
The attack mechanism is straightforward: an authenticated board member crafts an HTML file containing JavaScript and uploads it with a MIME type of image/png (or another safe type). Because the file command is unavailable, detectMimeFromFile() returns undefined, and the validation falls back to the attacker-supplied fileObj.type. The dangerous MIME check is therefore bypassed, and the file is stored on the server. When another user later opens or previews this attachment, the browser renders the HTML and executes the embedded JavaScript in the context of the Wekan application origin.
The patch introduced in version 9.90 adds a function called looksLikeDangerousMarkup() that inspects file bytes directly to determine if the content resembles HTML or other dangerous markup. When the MIME detection is unavailable (i.e., when detectMimeFromFile() returns undefined), the validation now forces dangerous-content scanning using this new function, closing the bypass vector.
From a vulnerability class perspective, this is CWE-434: Unrestricted Upload of File with Dangerous Type. The issue is compounded by a fail-open design pattern — the security control (MIME detection) silently degrades to an insecure fallback rather than failing closed when its dependency is unavailable.
Exploitation Scenarios
Note: No public PoC is available; the attack chain is inferred from the vulnerability class and the NVD description.
Step 1: Reconnaissance and Target Identification
An attacker first identifies Wekan instances running with the WITH_API=true environment variable. This can be accomplished through various reconnaissance methods: scanning for Wekan-specific HTTP headers or title tags, checking for the Meteor framework's distinctive client-side characteristics, or using Shodan-style search queries targeting the application. The attacker also needs to determine whether the server has the Unix file command available — this can be probed indirectly by uploading a file with a mismatched extension and content type and observing whether the upload succeeds or is rejected.
Step 2: Authentication and Privilege Acquisition
The attacker must be an authenticated board member. This could be a legitimate account, a compromised account, or a self-registered account if the instance allows open registration. The key requirement is having permission to upload attachments to a board they can access. The attacker does not need administrative privileges — standard board membership with upload rights is sufficient.
Step 3: Payload Crafting and Upload
The attacker crafts an HTML payload containing JavaScript (e.g., embedded in <script> tags). The HTML file is then uploaded with the HTTP Content-Type header set to image/png (or another MIME type that passes the safe-type whitelist). Because the target server lacks the file binary, the server-side MIME detection fails silently, and the validation trusts the attacker-provided MIME type. The file "passes" validation and is stored on the Wekan server, becoming accessible via the attachment API endpoint.
Step 4: Victim Interaction and Execution
The attacker plants the malicious attachment on a board that other users access. When another board member opens the attachment (either by clicking the attachment link or previewing it within the kanban card), the browser fetches the content from the Wekan origin. Since the content is served from the same origin as the application, the browser executes the embedded JavaScript with full access to the Wekan application's session context. The attacker's script can perform any action the victim is authorized to do, including but not limited to: exfiltrating board data, modifying card contents, creating new cards, reading API tokens, or performing actions requiring elevated privileges if the victim has them.
Post-Exploitation Impact
Because scripts execute in the context of the victim's session, the attacker inherits the victim's privileges. If the victim is an admin, the attacker can potentially take over the entire Wekan instance, including managing users, deleting boards, and accessing all organizational data. Even with a standard user victim, the attacker can pivot to other boards accessible to that user and potentially chain this with other vulnerabilities for privilege escalation.
Impact Assessment
The CVSS score of 8.7 (High) reflects a network-accessible vulnerability with low attack complexity. The attack requires low privileges (authenticated board member) and user interaction (victim opening the file), but the scope is changed (S:C), meaning the impact extends beyond the vulnerable component. The confidentiality and integrity impacts are both rated High (C:H/I:H), while availability is not affected (A:N).
Business Impact:
- Data Confidentiality Breach: Attacker can extract all data visible to any user who opens the malicious attachment, including project plans, employee information, credentials embedded in notes, and other sensitive kanban content.
- Data Integrity Compromise: The executing JavaScript can modify or delete board content, inject false information into project tracking, or alter task assignments.
- Account Takeover Chain: Stolen session tokens or API credentials can lead to full account takeover of any victim user.
- Supply Chain Risk: If Wekan is used to manage software development workflows (a common use case), compromised boards could be used to inject malicious links, altered commit references, or social engineering content into development pipelines.
Affected Systems:
- All Wekan instances running versions prior to 9.90.
- Specifically vulnerable: Deployments with
WITH_API=trueAND without the Unixfilecommand available in the server environment. - Containerized/Docker deployments are at heightened risk because minimal base images frequently omit the
fileutility.
Blast Radius:
The blast radius is limited to the Wekan instance itself but expands to all boards and users within that instance. Multi-tenant deployments (where one Wekan instance serves multiple organizational units) amplify the impact — a compromise on one board's attachment can affect all tenants sharing the instance.
Detection Guidance
Sigma Rule
title: Wekan File Upload with MIME Type Mismatch - Possible Stored XSS
id: a7f3c2e1-9b4d-4f8e-8a1c-3d5b7e9a1c2d
status: experimental
description: Detects uploads to Wekan attachment API where the declared MIME type does not match content analysis, indicating possible CVE-2026-68899 exploitation
author: Valtersit Threat Intelligence
date: 2026/01/15
logsource:
category: webserver
product: nginx
service: http
detection:
selection_upload:
http.method: POST
cs.method:
- "POST"
http.url|contains:
- "/api/attachments"
- "/api/board"
- "attachment"
selection_html_content:
http.response.body|contains: "<script"
or
http.response.body|contains: "%3Cscript"
selection_mime_type:
cs.content_type|startswith: "image/"
filter_image_magic:
http.response.body|startswith:
- "\x89PNG"
- "\xFF\xD8\xFF"
- "GIF89a"
- "BM"
condition: selection_upload and selection_html_content and selection_mime_type and not filter_image_magic
level: high
falsepositives:
- Legitimate HTML files uploaded as attachments for documentation purposes (unlikely but possible)
tags:
- attack.t1204
- attack.t1059.007
- cve.2026.68899
- cwe.434
YARA Rule
rule wekan_stored_xss_html_masquerading_as_image
{
meta:
author = "Valtersit Threat Intelligence"
description = "Detects HTML payloads with JavaScript that may be uploaded as image MIME types targeting CVE-2026-68899"
date = "2026-01-15"
cve = "CVE-2026-68899"
cwe = "CWE-434"
severity = "high"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2026-68899"
strings:
$html_tag = "<html" ascii nocase
$script_open = "<script" ascii nocase
$script_close = "</script>" ascii nocase
$javascript = "function" ascii nocase
$eval_call = "eval(" ascii nocase
$doc_cookie = "document.cookie" ascii nocase
$img_tag = "<img" ascii nocase
$png_signature = { 89 50 4E 47 } // PNG magic bytes
$gif_header = "GIF8" ascii
$html_payload = "text/html" ascii nocase
condition:
// HTML content not matching declared image format
uint32(0) != 0x474E5089 and uint32(0) != 0x38464947 and
$html_tag and $script_open and $script_close and
(1 of ($eval_call, $doc_cookie, $javascript))
and not ($png_signature at 0)
}
Suricata IDS Rule
alert http any any -> $HOME_NET any (msg:"ET EXPLOIT Wekan Stored XSS via MIME Type Bypass (CVE-2026-68899)"; flow:to_server,established; content:"POST"; http_method; content:"/api/"; http_uri; nocase; content:"attachment"; http_uri; nocase; content:"image/png"; http_header_names; pcre:"/Content-Type:\s*image\/(png|gif|jpeg|jpg)/i"; content:"<script"; http_client_body; nocase; content:"</script>"; http_client_body; nocase; pcre:"/<(html|script|iframe|svg)/i"; sid:202668899; rev:1; priority:1; classtype:web-application-attack; reference:cve,2026-68899; reference:url,https://nvd.nist.gov/vuln/detail/CVE-2026-68899; metadata:created_at 2026_01_15, updated_at 2026_01_15;)
Elastic Detection
// Detect Wekan file upload with HTML content masquerading as image
sequence by host.name, source.ip with maxspan=5s
[network where process.name == "nginx" and event.category == "network" and
destination.port == 443]
[http where event.category == "web" and http.request.method == "POST" and
url.path like "*api*" and url.path like "*attachment*" and
http.request.headers.content-type like "image/*" and
request.body.text contains "<script"]
Splunk SPL Query
index=web sourcetype=access_combined_wcookie
| where method="POST"
| regex uri="(/api/|attachment)"
| regex content_type="image/(png|jpeg|jpg|gif)"
| rex field=_raw "\s(?P<status>\d{3})\s"
| search NOT status=4*
| rex field=_raw "POST\s(?P<uri>[^\s]+)"
| where match(_raw, "(?i)<script|%3Cscript|<script")
| eval suspicious_upload=if(match(uri, "attachment"), "true", "false")
| table _time, src_ip, uri, status, content_type, _raw
| sort - _time
| rename _time as Timestamp, src_ip as SourceIP, uri as RequestURI, content_type as ContentType
Wazuh OSSEC Rule
<group name="wekan,cve_2026_68899,">
<rule id="100289" level="12" frequency="5" timeframe="60">
<if_sid>31100</if_sid>
<field name="url">\.*attachment.*</field>
<field name="url">\.*api.*</field>
<regex>POST</regex>
<regex>image/(png|jpg|jpeg|gif)</regex>
<description>Wekan: HTML upload with image MIME type - potential CVE-2026-68899 exploitation</description>
<group>attack.t1204,attack.t1059.007,cwe.434,cve.2026.68899,</group>
<mitre>
<id>T1204</id>
<id>T1059.007</id>
</mitre>
<options>no_full_log</options>
</rule>
</group>
Mitigation & Patch Guidance
Patch Status: The vendor has released version 9.90 which addresses this vulnerability by adding the looksLikeDangerousMarkup() function. However, our tracked patch sources show no patch evidence (Patch Confidence: 0/4 — marked as UNPATCHED in our intelligence feed, which may indicate this CVE entry is a provisional/vendor-disclosed vulnerability not yet fully verified by independent sources).
Immediate Mitigations (prior to patching):
- Verify the
filecommand availability: Confirm whether the Unixfilebinary is installed on the host running Wekan. If present, the vulnerable fallback path is not exercised. Check withwhich fileinside the container/host. - Disable or restrict the API: Set
WITH_API=falseif the API attachment functionality is not strictly required. This directly removes the attack surface. - Network-level filtering: Deploy a WAF (e.g., ModSecurity, AWS WAF) rule to detect and block HTTP POST requests to attachment endpoints where the content-type is an image type but the payload body contains HTML/JavaScript markers.
- Restrict board membership: Audit board memberships and remove inactive or untrusted users who have upload rights.
- Content Security Policy (CSP): If you control reverse proxy headers, inject a strict
Content-Security-Policyheader that disallows inline script execution. Note that this may break Wekan's legitimate functionality and should be tested carefully.
Patch/Upgrade Steps:
- Upgrade to version 9.90 or later. The fix is included in this release. Review the Wekan changelog for any migration or compatibility notes before upgrading.
- If immediate upgrade is not possible, consider running a minimal file-server sidecar that wraps the attachment serving with MIME sniffing protections (X-Content-Type-Options: nosniff header) — though this does not prevent the upload itself, it mitigates execution in most modern browsers.
- Monitor the Wekan GitHub repository for subsequent security releases or backports to LTS versions.
Long-Term Hardening:
- Enable fail-closed validation: Modify the underlying validation logic (via a fork or configuration) so that when
detectMimeFromFile()returnsundefined, the upload is rejected rather than falling back to client-provided MIME types. - Install the
filepackage in Docker images and base system images:apt-get install -y fileor equivalent. This ensures the content-based MIME detection path executes. - Independent file type validation: Deploy an intermediary content validation service (e.g., ClamAV with MIME detection, or a microservice calling
libmagic) that re-validates all uploads before they are stored. - Archive and serve uploads from a separate domain: Configure attachment storage to serve from a CDN/object storage with a different origin, so that even if HTML is stored, it does not execute with the Wekan application's origin privileges.
- Conduct a code audit of all fail-open patterns in the application — any security function that silently degrades on missing dependencies should be reviewed for similar issues.
References
- NVD Entry: https://nvd.nist.gov/vuln/detail/CVE-2026-68899 — National Vulnerability Database description of the vulnerability with CVSS scoring.
- Wekan Official GitHub Repository: https://github.com/wekan/wekan — Source repository containing the fix in version 9.90; review the commit history around
models/fileValidation.jsand the introduction oflooksLikeDangerousMarkup(). - Wekan Project Release Notes: https://github.com/wekan/wekan/blob/main/CHANGELOG.md — Changelog confirming the version 9.90 release and the security fix.
- MITRE ATT&CK Technique T1204 (User Execution): https://attack.mitre.org/techniques/T1204/ — The tactic category for this exploitation chain (user opens malicious attachment).
- CWE-434 Unrestricted Upload of File with Dangerous Type: https://cwe.mitre.org/data/definitions/434.html — The weakness classification for this vulnerability.
Threat Actor/Exploit-in-the-Wild Information: No evidence of active exploitation in the wild or known threat actor campaigns leveraging CVE-2026-68899 was identified at the time of this report. The CVE is listed as NOT in CISA's Known Exploited Vulnerabilities (KEV) catalog. No public PoC exploits have been published. Organizations using Wekan should nonetheless prioritize patching given the relatively simple exploitation chain and the high CVSS score.
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.