CVE-2026-59816 Overview
Joplin is an open source note-taking and to-do application that organizes notes and lists into notebooks. CVE-2026-59816 is a path traversal vulnerability [CWE-22] affecting Joplin Server instances prior to version 3.7.7 when TRANSCRIBE_ENABLED=true is set. The GET /api/transcribe/:id and POST /api/transcribe/:id handlers in packages/server/src/routes/api/transcribe.ts pass the decoded job id directly into transcription backend URLs. An authenticated user can inject URL-encoded slash and parent-directory segments into the job ID to escape the intended /transcribe/ prefix and reach other backend endpoints.
Critical Impact
An authenticated attacker can proxy requests to arbitrary transcription-backend endpoints, potentially exposing internal administrative, health, or configuration data.
Affected Products
- Joplin Server versions prior to 3.7.7
- Deployments with TRANSCRIBE_ENABLED=true
- The packages/server/src/routes/api/transcribe.ts route handlers
Discovery Timeline
- 2026-09-21 - CVE-2026-59816 published to NVD
- 2026-09-23 - Last updated in NVD database
Technical Details for CVE-2026-59816
Vulnerability Analysis
The flaw resides in Joplin Server's transcription proxy routes. When TRANSCRIBE_ENABLED is enabled, the server exposes GET /api/transcribe/:id and POST /api/transcribe/:id handlers that forward requests to an internal transcription backend. The handlers take the :id route parameter and interpolate it directly into the backend URL without validating its contents.
Because the router uses parseSubPath() to decode the incoming path, an authenticated attacker can supply URL-encoded characters such as %2F (slash) and %2E%2E (parent directory) inside the job identifier. The decoded segments escape the intended /transcribe/ prefix and resolve to sibling paths on the backend. The server proxies those requests and returns the responses to the caller.
Root Cause
The root cause is missing input validation on the id parameter before it is used to construct an outbound URL. The application trusted the router-decoded value and did not enforce a character allowlist. This is a classic path traversal weakness [CWE-22] in a proxy handler.
Attack Vector
Exploitation requires an authenticated account on a Joplin Server with transcription enabled. The attacker crafts a request to /api/transcribe/<encoded-traversal> where the id contains encoded slashes and .. segments. The server decodes the value, builds the backend URL, and issues the proxied request. Response data from internal endpoints (administrative, health, or configuration routes on the transcription backend) can be returned to the attacker.
// Security patch applied in packages/server/src/routes/api/transcribe.ts
// Adds strict allowlist validation for the job ID before it is used in a backend URL
return config().TRANSCRIBE_ENABLED;
};
const validateJobId = (id: string): string => {
if (!/^[a-zA-Z0-9_-]+$/.test(id)) {
throw new ErrorBadRequest('Invalid job ID format');
}
return id;
};
const parseResponseSafely = async (response: Response) => {
const text = await response.text();
Source: GitHub Joplin Commit d97a5091
Detection Methods for CVE-2026-59816
Indicators of Compromise
- Requests to /api/transcribe/:id where the id segment contains URL-encoded characters such as %2F, %2E%2E, %5C, or literal .. sequences.
- Outbound proxy requests from Joplin Server to transcription-backend paths that do not begin with /transcribe/.
- Unexpected transcription-backend responses (administrative, health, or configuration payloads) returned through the /api/transcribe/ endpoint.
Detection Strategies
- Inspect Joplin Server access logs for /api/transcribe/ requests whose decoded id values fail an alphanumeric, underscore, and hyphen allowlist (^[a-zA-Z0-9_-]+$).
- Correlate authenticated user sessions against volume and diversity of /api/transcribe/:id calls to identify enumeration behavior.
- Deploy web application firewall rules that block URL-encoded traversal patterns in the id path parameter of the transcribe route.
Monitoring Recommendations
- Enable verbose logging on the transcription proxy handler and alert on ErrorBadRequest responses raised by the new validateJobId check after upgrading.
- Monitor egress traffic from the Joplin Server host to the transcription backend for requests targeting non-/transcribe/ paths.
- Track configuration drift on the TRANSCRIBE_ENABLED flag to ensure the feature is only enabled where required.
How to Mitigate CVE-2026-59816
Immediate Actions Required
- Upgrade Joplin Server to version 3.7.7 or later, which introduces the validateJobId allowlist check.
- If upgrading immediately is not possible, set TRANSCRIBE_ENABLED=false to disable the vulnerable route entirely.
- Rotate any credentials, tokens, or configuration values that may have been exposed through the transcription backend.
Patch Information
The issue is fixed in Joplin version 3.7.7. The fix adds a validateJobId function in packages/server/src/routes/api/transcribe.ts that rejects any id value not matching ^[a-zA-Z0-9_-]+$. Details are available in the GitHub Security Advisory GHSA-r7wp-3494-fwf4 and the upstream commit d97a5091.
Workarounds
- Disable the transcription feature by unsetting or setting TRANSCRIBE_ENABLED=false in the server configuration.
- Restrict network access so the transcription backend only exposes the /transcribe/ prefix and rejects requests to administrative, health, or configuration paths.
- Place a reverse proxy in front of Joplin Server that rejects requests to /api/transcribe/:id when the id contains encoded slashes, backslashes, or .. sequences.
# Disable the vulnerable transcription route until version 3.7.7 is deployed
export TRANSCRIBE_ENABLED=false
# Restart the Joplin Server service to apply the change
systemctl restart joplin-server
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

