Skip to main content
Vulnerability Database/CVE-2026-59814

CVE-2026-59814: Joplin Server XSS Vulnerability

CVE-2026-59814 is a cross-site scripting flaw in Joplin Server that lets attackers execute malicious scripts through crafted SVG attachments. This post covers technical details, affected versions, and mitigation steps.

Published:

CVE-2026-59814 Overview

CVE-2026-59814 is a stored cross-site scripting (XSS) vulnerability in Joplin Server, the synchronization backend for the open-source Joplin note-taking application. The flaw exists in the GET /shares/:id?resource_id= route, which serves uploaded resources using an attacker-controlled MIME type and omits the Content-Disposition header when the resource title is empty. A low-privileged authenticated user can publish an empty-title image/svg+xml attachment containing script content. When a victim opens the public share link, the script executes in the Joplin Server application origin. The issue is fixed in version 3.7.7 [CWE-79].

Critical Impact

Script execution on the application origin enables theft of same-origin data, administrative information, and anti-CSRF tokens, and permits actions performed under the victim's authenticated session.

Affected Products

  • Joplin Server prior to version 3.7.7
  • Joplin deployments using default USER_CONTENT_BASE_URL (shared application origin)
  • Joplin deployments with USER_CONTENT_BASE_URL configured to a separate user-content origin (script still executes, but scoped to that origin)

Discovery Timeline

  • 2026-09-21 - CVE-2026-59814 published to the National Vulnerability Database (NVD)
  • 2026-09-23 - Last updated in NVD database

Technical Details for CVE-2026-59814

Vulnerability Analysis

Joplin Server exposes shared resources through the /shares/:id?resource_id= endpoint. The handler previously returned the resource body with the MIME type stored on the resource record. That MIME type is user-controlled at upload time. When the resource title field is empty, the handler also omits the Content-Disposition header, so the browser renders the response inline rather than treating it as a download.

An attacker uploads an SVG file with the MIME type image/svg+xml and an empty title. Because SVG documents can embed <script> elements, the payload executes in the browser context of any user who opens the share URL. By default, user content is served from the Joplin Server application origin, so the script gains same-origin access to application state, administrative endpoints, and anti-CSRF tokens for the victim's authenticated session.

Root Cause

The root cause is missing output hardening on user-uploaded content. The share route trusted the resource's stored MIME value and conditionally suppressed the Content-Disposition header when no filename was present. The fix introduces a safeUserContentResponse utility that normalizes response headers to prevent inline script execution.

Attack Vector

Exploitation requires a low-privileged Joplin Server account and user interaction: the victim must open the attacker's public share link. Successful exploitation grants same-origin script execution and permits session-scoped actions such as reading admin data and exfiltrating CSRF tokens.

typescript
// Patch: packages/server/src/routes/index/shares.ts
 import { Item, Share } from '../../services/database/types';
 import { ModelType } from '@joplin/lib/BaseModel';
 import { FileViewerResponse, renderItem as renderJoplinItem } from '../../utils/joplinUtils';
-import { friendlySafeFilename } from '@joplin/lib/path-utils';
+import safeUserContentResponse from '../../utils/safeUserContentResponse';
 
 async function renderItem(context: AppContext, item: Item, share: Share): Promise<FileViewerResponse> {
 	if (item.jop_type === ModelType.Note) {

// Patch: packages/server/src/utils/routeUtils.ts
 import { hasOwnProperty } from '@joplin/utils/object';
 import { ltrimSlashes, rtrimSlashes } from '@joplin/lib/path-utils';
+import safeUserContentResponse from './safeUserContentResponse';

Source: GitHub commit 920cd8f

Detection Methods for CVE-2026-59814

Indicators of Compromise

  • Resource records in the Joplin Server database with mime = image/svg+xml and an empty title field created by low-privileged accounts.
  • Public share responses served without a Content-Disposition header for user-uploaded resources.
  • Unexpected outbound requests from browsers of authenticated users after visiting a Joplin share link.

Detection Strategies

  • Query the Joplin Server database for resources with MIME types capable of embedding scripts (image/svg+xml, text/html, application/xhtml+xml) uploaded before upgrading to 3.7.7.
  • Inspect HTTP access logs for GET /shares/:id?resource_id= requests returning SVG payloads to unauthenticated or cross-user sessions.
  • Correlate share access events with subsequent administrative API calls originating from the same session token.

Monitoring Recommendations

  • Enable web server access logging with full URI, response MIME type, and response headers to identify inline user-content responses.
  • Alert on newly uploaded resources with empty titles from non-administrative accounts.
  • Monitor for administrative endpoint access initiated from browser contexts that recently loaded a public share URL.

How to Mitigate CVE-2026-59814

Immediate Actions Required

  • Upgrade all Joplin Server instances to version 3.7.7 or later.
  • Audit existing resources for empty titles combined with scriptable MIME types and remove or sanitize them.
  • Rotate administrative session tokens and anti-CSRF tokens if a share URL served an SVG payload to authenticated users.

Patch Information

The vulnerability is resolved in Joplin 3.7.7. The fix is implemented in GitHub Pull Request #15787 and merged in commit 920cd8f, which introduces a safeUserContentResponse helper to enforce safe headers on user-uploaded content. See the GitHub Security Advisory GHSA-mx98-7h4g-6gmh for full advisory details.

Workarounds

  • Configure USER_CONTENT_BASE_URL to a separate origin so that script execution is isolated from the Joplin Server application origin.
  • Place Joplin Server behind a reverse proxy that overrides Content-Type for user resources and adds Content-Disposition: attachment and Content-Security-Policy: sandbox headers.
  • Restrict resource upload permissions to trusted users until the patch is applied.
bash
# Example nginx override for the shares route to force downloads
location ~ ^/shares/ {
    proxy_pass http://joplin_server_upstream;
    proxy_hide_header Content-Disposition;
    add_header Content-Disposition "attachment" always;
    add_header Content-Security-Policy "sandbox; default-src 'none'" always;
    add_header X-Content-Type-Options "nosniff" always;
}

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.