Cloudanix VulnDB

CVE-2026-40295

Medium · 6.1

CVSS

6.1

EPSS

0.3%

Published

May 22, 2026

CISA due date

—

Cloudanix analysis

Next patch cycle SSVC: Track

A flaw in the login timeout process can let attackers send users from a trusted website to a fake or harmful website.

Chainable
Exploitation
Requires User Interaction
Attacker needs
User Interaction
Complexity
Low
Impact
Other
Component
Web Framework
Class
Open Redirect
Remediation
Upgrade
Effort
Medium
Patch risk
Low

What it actually does

CVE-2026-40295 is an open redirect vulnerability in Devise, the Rails authentication framework, affecting versions 5.0.3 and earlier when the Timeoutable module is enabled. For non-GET requests that encounter an expired session, Devise::FailureApp#redirect_url uses the HTTP Referer header directly as the redirect destination. Because Referer is attacker-controllable and is not constrained to an internal path or trusted host, an attacker can cause the application to redirect an expired-session user from the legitimate application domain to an arbitrary external site. The issue is specific to the non-GET timeout handling path; the GET timeout path and Devise’s normal stored-location logic use safer server-side or path-extraction behavior. Rails’ built-in open redirect protections do not reliably mitigate this because Devise::FailureApp uses its own isolated redirect behavior.

Why it matters to the business

The main risk is user deception: attackers can use the trusted application as a stepping stone to send users to phishing pages, credential-harvesting sites, fake reauthentication prompts, or malware delivery pages. This can undermine user trust in the application domain and increase the likelihood that victims interact with malicious content because the redirect begins from a legitimate service. The CVSS score is medium severity and the EPSS score is currently low, and it is not listed in CISA KEV, but the flaw is simple to trigger remotely and requires only user interaction plus an expired Devise session. Organizations using Devise with Timeoutable should treat this as a meaningful phishing-enablement issue, especially for public-facing Rails applications with large user populations.

How an attack unfolds

An attacker first identifies a Rails application using Devise with Timeoutable enabled and running an affected version. The attacker then hosts a malicious web page that contains an auto-submitting cross-origin form targeting a non-GET endpoint on the legitimate application. When a victim who has an expired Devise session visits the attacker-controlled page, the browser submits the form to the trusted application and includes a Referer value pointing to the attacker’s page. Because the user’s session is expired, Devise invokes the timeout failure path. In vulnerable versions, for non-GET requests, Devise constructs the redirect destination from request.referrer without validating whether it is internal or trusted. The victim’s browser is then redirected from the legitimate application to the attacker-controlled URL, where the attacker can present phishing content, fake login prompts, malware downloads, or other social-engineering material.

How to fix it

Upgrade Devise to version 5.0.4 or later. If package-specific dependency constraints are used, ensure the application resolves to Devise 5.0.4 or newer and that the deployed artifact actually contains the updated gem version. If immediate upgrade is not possible, reduce exposure by disabling Devise Timeoutable where operationally acceptable, avoiding affected non-GET timeout behavior, or adding application-level controls that reject or normalize external redirect destinations in authentication failure flows. Do not rely solely on Rails open redirect settings such as config.action_controller.action_on_open_redirect = :raise or older raise_on_open_redirects behavior, because the vulnerable Devise::FailureApp path is not protected by those settings. After upgrading, restart application processes and redeploy all affected Rails services so the fixed gem is loaded.

How to confirm the fix worked

Confirm the deployed Devise version is 5.0.4 or later by checking dependency lockfiles, runtime gem versions, container images, and deployed release artifacts. Review application configuration to determine whether Devise Timeoutable is enabled for any user model. Functional validation can be performed in a non-production environment by creating an expired Devise session, issuing a non-GET request with an external Referer header, and confirming the application no longer redirects to the external Referer. The expected safe behavior is that redirects are constrained to an internal path, a configured safe destination, or an authentication page on the trusted application. Also verify that all application instances, background release images, and horizontally scaled nodes have been rebuilt or restarted after the dependency update.

Typical attack path

  1. Identify a public Rails application using Devise with the Timeoutable module enabled and a vulnerable Devise version, 5.0.3 or earlier.
  2. Create an attacker-controlled web page containing an auto-submitting form that sends a non-GET request, such as POST, to the target application.
  3. Set up the malicious page so the victim’s browser sends a Referer header pointing to the attacker-controlled origin.
  4. Lure a user with an expired session for the target application to visit the attacker-controlled page.
  5. The victim’s browser submits the non-GET request to the legitimate application.
  6. Devise detects the expired session and invokes the vulnerable non-GET timeout redirect path.
  7. The application redirects the victim to the unvalidated Referer URL controlled by the attacker.
  8. The attacker displays phishing, fake reauthentication, credential theft, or malware-delivery content.

How to detect it

To assess possible prior exploitation, review web access logs, application logs, reverse proxy logs, CDN/WAF logs, and authentication failure or timeout logs. Focus on non-GET requests that occurred when sessions were expired and resulted in HTTP 302, 303, or other redirect responses. Correlate those events with external Referer header values, especially Referer domains that are not part of the organization’s trusted domains and are followed by redirects to the same external domain. Look for spikes in non-GET requests from unusual origins, requests to authentication-protected endpoints with expired-session outcomes, and user reports of being redirected from the legitimate application to unexpected login or download pages. If logs capture response Location headers, search for 3xx responses where the Location value is an absolute external URL derived from the Referer. Because this vulnerability enables redirection rather than server compromise, host-level artifacts may be absent; investigation should emphasize HTTP request/response telemetry, phishing infrastructure, user complaint data, and downstream credential-theft indicators.

  • Devise::FailureApp
  • Timeoutable
  • HTTP 302 with external Referer on non-GET request
  • HTTP 303 with external Referer on non-GET request
  • Referer: http://
  • Referer: https://
  • Location: http://
  • Location: https://
  • POST request with external Referer followed by 302
  • PUT request with external Referer followed by 302
  • PATCH request with external Referer followed by 302
  • DELETE request with external Referer followed by 302
  • You need to sign in or sign up before continuing
  • Your session expired

What your security team should do

  • Inventory Rails applications using Devise and identify any deployments running Devise 5.0.3 or earlier.
  • Prioritize public-facing applications where Devise Timeoutable is enabled, especially those with large user populations or sensitive authentication workflows.
  • Upgrade Devise to 5.0.4 or later and redeploy all affected services.
  • Do not treat Rails global open redirect protection settings as sufficient mitigation for this issue.
  • Add regression tests for expired-session non-GET requests with external Referer headers to ensure future authentication changes do not reintroduce open redirects.
  • Monitor web logs for non-GET requests that receive 3xx responses and have external Referer values, particularly around timeout or authentication failure endpoints.
  • Coordinate with fraud, help desk, and user-support teams to watch for reports of unexpected redirects, fake login prompts, or phishing pages that appear to originate from the legitimate application.

The record

Devise is an authentication solution for Rails based on Warden. In versions 5.0.3 and below, when the Timeoutable module is enabled in Devise, the FailureApp#redirect_url method returns request.referrer — the HTTP Referer header, which is attacker-controllable — without validation for any non-GET request that results in a session timeout. An attacker who hosts a page with an auto-submitting cross-origin form can cause a victim with an expired Devise session to be redirected to an arbitrary external URL. This contrasts with the GET timeout path (which uses server-side attempted_path) and Devise's own store_location_for mechanism (which strips external hosts via extract_path_from_location), both of which are protected; only the non-GET timeout redirect path is unprotected. Expired-session users can be silently redirected from the trusted app domain to attacker-controlled URLs, enabling phishing and malware delivery while bypassing browser warnings. Note: Rails' built-in open-redirect protection does not mitigate this issue. Devise::FailureApp is an ActionController::Metal app with its own isolated copy of the relevant redirect configuration, so config.action_controller.action_on_open_redirect = :raise (and the older raise_on_open_redirects setting) do not reach it. This issue has been fixed in version 5.0.4.

Affected packages

Ecosystem Package Introduced Fixed

Related vulnerabilities