CVE-2026-22794

Trust Issues: Hijacking Appsmith Accounts via Origin Header Abuse

Alon Barad
Alon Barad
Software Engineer

Jan 15, 2026·5 min read

Executive Summary (TL;DR)

Appsmith trusted the client-supplied 'Origin' header when generating password reset links. An attacker can send a reset request for a victim's email with a malicious Origin (e.g., evil.com). The victim receives a valid email from the Appsmith system, but the link points to the attacker's server. Clicking the link leaks the password reset token, allowing the attacker to hijack the account.

A critical Account Takeover (ATO) vulnerability in Appsmith allows unauthenticated attackers to poison password reset emails by spoofing the HTTP Origin header. This manipulation forces the application to generate legitimate emails containing links to attacker-controlled domains, facilitating credential harvesting.

The Low-Code Honeypot

Appsmith is the darling of the internal tooling world. It’s the glue that holds together your startups' PostgreSQL databases, your Stripe APIs, and your AWS S3 buckets. Developers love it because it turns hours of frontend boilerplate into minutes of drag-and-drop magic. Security researchers love it because it is effectively a centralized repository of your organization's most sensitive credentials.

Think about it: if I compromise your main web app, I might get customer data. If I compromise your Appsmith instance, I get the "God View"—direct access to the admin panels used to manage that customer data, refund transactions, and nuke databases. It is the soft underbelly of the enterprise network, often sitting behind a half-hearted VPN or, worse, exposed directly to the internet with default configurations.

CVE-2026-22794 isn't some complex memory corruption bug requiring a Ph.D. in heap feng shui. It’s a logic flaw born from a developer being too polite. The application asked the user, "Where are you connecting from?" and when the attacker replied, "I'm from the legitimate admin panel, trust me," the server just nodded and handed over the keys.

The Flaw: Blind Trust

The root cause here is a classic violation of the First Commandment of AppSec: Never Trust Client Input. Specifically, this is an implementation of CWE-346: Origin Validation Error. When a user requests a password reset, the server needs to construct a URL that points back to the frontend so the user can enter a new password.

In a robust system, the server knows its own name. It relies on a static configuration file or an environment variable like SITE_URL to build these links. However, prior to version 1.93, Appsmith's UserServiceCEImpl.java took a shortcut. Instead of checking a config, it looked at the HTTP Origin header provided in the request.

This is akin to a bank mailing your new credit card to whatever address you scribbled on a napkin, without checking if it matches the address on file. The server logic effectively said: String baseUrl = request.getHeader("Origin");. It then appended the sensitive reset token to this unvalidated string. If I send Origin: https://evil-hacker.com, the server dutifully generates a link to https://evil-hacker.com/user/resetPassword?token=SECRET_TOKEN.

The Smoking Gun

Let's look at the crime scene. The vulnerability existed in the forgotPasswordTokenGenerate and resendEmailVerification methods. The code grabbed the header and used it immediately. The fix, introduced in commit 6f9ee6226bac13fb4b836940b557913fff78b633, forces a reality check.

Here is the logic that was introduced to patch the hole. Notice the explicit validation against a trusted configuration:

// The Fix: UserServiceCEImpl.java
 
private Mono<Void> validateBaseUrl(String providedBaseUrl) {
    // DANGER: If the config is missing, we might still be vulnerable!
    if (!StringUtils.hasText(appsmithBaseUrl)) {
        return Mono.empty(); 
    }
    // The actual security check
    if (!appsmithBaseUrl.equals(providedBaseUrl)) {
        return Mono.error(new AppsmithException(
                AppsmithError.GENERIC_BAD_REQUEST,
                "Origin header does not match APPSMITH_BASE_URL configuration."));
    }
    return Mono.empty();
}

The developers added validateBaseUrl, which compares the incoming header against a server-side appsmithBaseUrl variable. If they don't match, the request dies. Simple, effective, but with a catch we'll discuss in the mitigation section.

The Exploit Chain

Exploiting this is terrifyingly simple because it leverages the victim's trust in the platform's own email infrastructure. This isn't a spoofed email; it is a legitimate email sent by the Appsmith server, DKIM-signed and everything.

Here is how an attacker pulls off the heist:

  1. Recon: The attacker identifies the email address of an Appsmith administrator (LinkedIn is great for this).
  2. The Hook: The attacker sends a POST /api/v1/users/forgotPassword request. They set the Host header correctly, but inject Origin: https://attack-infrastructure.com.
  3. The Line: Appsmith processes the request, generates a token, and emails the victim: "Click here to reset your password." The link points to https://attack-infrastructure.com/user/resetPassword?token=....
  4. The Sinker: The victim clicks the link. Their browser navigates to the attacker's server. The attacker's server logs the URL (containing the token), then immediately redirects the victim back to the real Appsmith login page to avoid suspicion.
  5. Game Over: The attacker uses the stolen token to reset the victim's password and logs in.

Mitigation: The "Config" Trap

The fix is available in version 1.93. However, simply upgrading the binary is not enough to guarantee safety. The patch includes a conditional check designed for backward compatibility that leaves a massive gap.

Look closely at the patch logic again:

if (!StringUtils.hasText(appsmithBaseUrl)) {
    return Mono.empty(); // Returns success if config is missing!
}

If the administrator has not explicitly defined the APPSMITH_BASE_URL environment variable or configuration setting, the validation is skipped entirely, and the server reverts to the vulnerable behavior. This is a "secure by configuration" approach rather than "secure by default."

To be safe:

  1. Update to Appsmith v1.93 or later.
  2. IMPERATIVE: Set APPSMITH_BASE_URL in your docker.env or environment configuration to your actual domain (e.g., https://internal-tools.company.com).
  3. Restart the container.

Fix Analysis (1)

Technical Appendix

CVSS Score
9.6/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H
EPSS Probability
0.03%
Top 93% most exploited
5,000
via Shodan

Affected Systems

Appsmith Community Edition < 1.93Appsmith Enterprise Edition < 1.93

Affected Versions Detail

Product
Affected Versions
Fixed Version
Appsmith
Appsmith
< 1.931.93
AttributeDetail
CWE IDCWE-346
Attack VectorNetwork
CVSS Score9.6 (Critical)
Vector StringCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H
ImpactAccount Takeover
EPSS Score0.00027
CWE-346
Origin Validation Error

The application does not properly verify that the Origin header matches the expected source, allowing attackers to manipulate the base URL used in generated links.

Vulnerability Timeline

Fix committed to main branch
2025-11-28
CVE Published & Public Disclosure
2026-01-12

Subscribe to updates

Get the latest CVE analysis reports delivered to your inbox.