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

CVE-2026-46649: Joplin Server SSO Authentication Bypass

CVE-2026-46649 is an authentication bypass flaw in Joplin Server that allows attackers to bypass SSO authentication through unlimited code guessing. This post explains its impact, affected versions, and mitigation steps.

Published:

CVE-2026-46649 Overview

Joplin is an open source note-taking and to-do application that organizes notes and lists into notebooks. Versions of Joplin Server prior to 3.7.2 contain a missing rate-limiting flaw in the GET /api/login_with_code/:id endpoint used during Single Sign-On (SSO) authentication. The endpoint accepts a nine-digit code with a ten-minute lifetime and does not apply the limiterLoginBruteForce middleware. An unauthenticated attacker can submit unlimited guesses against an active SSO login session. A correct code returns a full session token that grants access to the victim's notes, notebooks, and account settings. The issue is fixed in Joplin 3.7.2.

Critical Impact

Successful brute force of the SSO code returns a valid session token, giving attackers full read and write access to a targeted user's notes, notebooks, and account settings.

Affected Products

  • Joplin Server versions prior to 3.7.2
  • Deployments using SAML/SSO authentication with login_with_code endpoint
  • Self-hosted and multi-user Joplin Server instances

Discovery Timeline

  • 2026-09-21 - CVE-2026-46649 published to NVD
  • 2026-09-23 - Last updated in NVD database

Technical Details for CVE-2026-46649

Vulnerability Analysis

The vulnerability is an Improper Restriction of Excessive Authentication Attempts flaw [CWE-307]. Joplin Server exposes GET /api/login_with_code/:id as part of its SAML SSO flow. The endpoint validates a nine-digit numeric code tied to an SSO session identifier. The keyspace of one billion combinations is finite, and the ten-minute code lifetime narrows the guessing window. Without brute-force protection, an attacker can automate rapid guesses against a target's active session identifier. A correct guess returns a full session token, so the attacker gains authenticated access equivalent to the victim.

Root Cause

The login.ts route handler for the SAML code exchange omitted the limiterLoginBruteForce middleware that Joplin applies to other authentication endpoints. There was no per-IP or per-session cap on failed attempts, no exponential backoff, and no lockout after repeated failures. The :id session parameter is guessable or exposable during an active login, and the nine-digit code provided the only remaining secret.

Attack Vector

The attack requires network access to the Joplin Server API and a target user who has initiated an SSO login. The attacker enumerates or observes the session :id and then issues automated GET /api/login_with_code/:id?code=NNNNNNNNN requests until a code matches. Because the endpoint returns a session token on success, no further credential handling is needed. The attacker inherits the victim's authenticated session and can read, modify, or delete notes and change account settings.

typescript
// Patch: packages/server/src/routes/api/login.ts
 import { redirect, SubPath } from '../../utils/routeUtils';
 import { generateRedirectHtml, getIdentityProvider, getServiceProvider } from '../../utils/saml';
 import { AppContext, RouteType, SamlPostResponse } from '../../utils/types';
-import { bodyFields } from '../../utils/requestUtils';
+import { bodyFields, userIp } from '../../utils/requestUtils';
 import { ErrorBadRequest, ErrorForbidden } from '../../utils/errors';
 import { cookieSet } from '../../utils/cookies';
 import defaultView from '../../utils/defaultView';
+import limiterLoginBruteForce from '../../utils/request/limiterLoginBruteForce';
 
 export const router = new Router(RouteType.Api);

Source: GitHub Commit fd8c1fb. The fix imports userIp and limiterLoginBruteForce, applying rate limiting to the SAML auth code endpoint.

Detect Identity Attacks the Moment Authentication Fails

Singularity™ Identity surfaces credential misuse, lateral movement, and privilege escalation in real time, so you can contain the breach before it spreads.

Stop Identity Attacks

Detection Methods for CVE-2026-46649

Indicators of Compromise

  • High-volume GET /api/login_with_code/:id requests from a single source IP within a ten-minute window
  • Repeated 4xx responses from /api/login_with_code/ followed by a 2xx response and session issuance
  • Session tokens issued from an IP or user-agent that does not match the user's typical SSO login pattern
  • Unexpected note, notebook, or account setting modifications following an SSO login event

Detection Strategies

  • Parse Joplin Server access logs for repeated hits against the /api/login_with_code/ path with varying code query parameters
  • Alert when the request rate per session id exceeds a small threshold (for example, more than 10 attempts per minute)
  • Correlate SSO code endpoint activity with subsequent API calls to note or account endpoints from the same session

Monitoring Recommendations

  • Forward Joplin Server HTTP logs to a centralized logging or SIEM platform for long-term retention and alerting
  • Baseline normal SSO login volume per user and per IP, then alert on deviations
  • Track session token issuance events and flag tokens minted after abnormal code-endpoint traffic

How to Mitigate CVE-2026-46649

Immediate Actions Required

  • Upgrade Joplin Server to version 3.7.2 or later as the primary remediation
  • Invalidate active sessions and force re-authentication for users after upgrading
  • Review server access logs for evidence of prior brute-force attempts against /api/login_with_code/

Patch Information

The fix is available in Joplin 3.7.2. See GitHub Pull Request #15433 and GitHub Security Advisory GHSA-6vwc-4hrg-qp5h. The Joplin 3.7.2 release applies limiterLoginBruteForce to the SAML code endpoint.

Workarounds

  • If patching is delayed, disable SAML/SSO on Joplin Server and require local authentication until the upgrade is applied
  • Restrict access to /api/login_with_code/ at a reverse proxy or Web Application Firewall (WAF) with per-IP rate limits
  • Reduce SSO code lifetime through IdP configuration where supported to shrink the attacker's guessing window
bash
# Example nginx rate-limit for the SSO code endpoint (pre-patch mitigation)
limit_req_zone $binary_remote_addr zone=joplin_sso:10m rate=5r/m;

location /api/login_with_code/ {
    limit_req zone=joplin_sso burst=5 nodelay;
    limit_req_status 429;
    proxy_pass http://joplin_backend;
}

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.