CVE-2026-25476 Overview
CVE-2026-25476 is a session expiration bypass vulnerability affecting OpenEMR, a free and open source electronic health records (EHR) and medical practice management application. Prior to version 8.0.0, the session expiration check in library/auth.inc.php runs only when skip_timeout_reset is not present in the request. When skip_timeout_reset=1 is sent, the entire block that calls SessionTracker::isSessionExpired() and forces logout on timeout is skipped.
This flaw allows any request that includes the skip_timeout_reset parameter (such as auto-refresh pages like the Patient Flow Board) to bypass the expiration check entirely. As a result, expired sessions can continue accessing protected health information indefinitely, abandoned workstations remain active, and attackers with stolen session cookies can perpetually maintain unauthorized access by simply including this parameter in their requests.
Critical Impact
Healthcare systems running vulnerable OpenEMR versions are exposed to unauthorized access to protected health information (PHI), with expired sessions able to access patient data indefinitely when attackers abuse the skip_timeout_reset parameter.
Affected Products
- OpenEMR versions prior to 8.0.0
- Systems utilizing library/auth.inc.php for session management
- Deployments with auto-refresh features (Patient Flow Board, Messages, Reminders)
Discovery Timeline
- 2026-02-25 - CVE CVE-2026-25476 published to NVD
- 2026-02-26 - Last updated in NVD database
Technical Details for CVE-2026-25476
Vulnerability Analysis
This vulnerability is classified as CWE-613 (Insufficient Session Expiration). The core issue lies in how OpenEMR handles session timeout verification when certain request parameters are present.
The vulnerable code path in library/auth.inc.php was designed with a feature to skip timeout resets for background polling scripts (Messages, Reminders, Patient Flow Board). However, the implementation incorrectly scoped this bypass to also skip the session expiration check entirely, not just the timeout reset. This means an attacker who obtains a valid session cookie—even one that should have expired—can maintain persistent access by simply appending skip_timeout_reset=1 to their requests.
The network-accessible nature of this vulnerability combined with the lack of authentication requirements for exploitation makes it particularly dangerous in healthcare environments where patient data confidentiality is paramount under HIPAA regulations.
Root Cause
The root cause is an improper conditional check structure in the session management code. The original implementation combined the expiration check and the timeout reset update under a single conditional block that could be bypassed entirely with a request parameter:
if (empty($skipSessionExpirationCheck) && empty($_REQUEST['skip_timeout_reset'])) {
if (!SessionTracker::isSessionExpired()) {
SessionTracker::updateSessionExpiration();
} else {
// Force logout on timeout
}
}
This design flaw meant that skip_timeout_reset=1 not only prevented the session timer from being reset (intended behavior) but also prevented the expiration check from running at all (unintended security bypass).
Attack Vector
An attacker exploiting this vulnerability would follow this attack pattern:
- Obtain a valid session cookie through session hijacking, XSS, or physical access to an abandoned workstation
- Include the skip_timeout_reset=1 parameter in all subsequent HTTP requests
- The server skips the SessionTracker::isSessionExpired() check entirely
- Even if the session should have expired, access continues indefinitely
- The attacker maintains persistent unauthorized access to patient health records
The security patch restructures the conditional logic to always perform the expiration check, only skipping the timer reset when skip_timeout_reset is present:
// Security patch in library/auth.inc.php - Merge commit from fork
}
}
-// Ensure user has not timed out, if applicable
-// Have a mechanism to skip the timeout and timeout reset mechanisms if a skip_timeout_reset parameter exists. This
-// can be used by scripts that continually request information from the server; for example the Messages
-// and Reminders automated intermittent requests.
-// Also skipping this all on login since entry in session_tracker is not ready yet
-if (empty($skipSessionExpirationCheck) && empty($_REQUEST['skip_timeout_reset'])) {
- if (!SessionTracker::isSessionExpired()) {
- SessionTracker::updateSessionExpiration();
- } else {
+// Ensure user has not timed out, if applicable.
+// Skip on login since the session_tracker entry is not ready yet.
+if (empty($skipSessionExpirationCheck)) {
+ if (SessionTracker::isSessionExpired()) {
// User has timed out.
EventAuditLogger::getInstance()->newEvent("logout", $session->get('authUser'), $session->get('authProvider'), 0, "timeout, so force logout");
authCloseSession();
authLoginScreen(true);
+ } elseif (empty($_REQUEST['skip_timeout_reset'])) {
+ // Reset the session expiration timer unless the request opts out (e.g. background
+ // polling from Messages, Reminders, or the Flow Board).
+ SessionTracker::updateSessionExpiration();
}
}
Source: GitHub Commit Update
Detection Methods for CVE-2026-25476
Indicators of Compromise
- Unusually long session durations in OpenEMR access logs exceeding configured timeout thresholds
- High frequency of requests containing the skip_timeout_reset=1 parameter from unexpected sources or IP addresses
- Session activity continuing from workstations that should have been abandoned or locked
- Access patterns showing consistent use of the skip_timeout_reset parameter across multiple endpoints
Detection Strategies
- Implement web application firewall (WAF) rules to detect and log requests with skip_timeout_reset parameter from non-whitelisted sources
- Configure SIEM alerting for session durations exceeding the configured OpenEMR timeout threshold
- Deploy application-layer monitoring to track authentication events and correlate with session activity patterns
- Enable detailed audit logging in OpenEMR to capture all session-related events including timeout bypasses
Monitoring Recommendations
- Establish baseline metrics for normal session duration and skip_timeout_reset parameter usage in your environment
- Monitor for anomalous access patterns from IP addresses not associated with expected auto-refresh functionality
- Review OpenEMR audit logs regularly for sessions that bypass normal expiration patterns
- Implement network segmentation monitoring to detect unauthorized access to OpenEMR servers
How to Mitigate CVE-2026-25476
Immediate Actions Required
- Upgrade OpenEMR to version 8.0.0 or later immediately
- Audit current active sessions and terminate any suspicious long-running sessions
- Review access logs for evidence of exploitation using the skip_timeout_reset parameter
- Implement additional network-level access controls to limit exposure of the OpenEMR application
Patch Information
OpenEMR version 8.0.0 addresses this vulnerability by restructuring the session expiration logic. The fix ensures that the session expiration check (SessionTracker::isSessionExpired()) always runs regardless of the skip_timeout_reset parameter, while still allowing background polling scripts to opt out of resetting the expiration timer.
For detailed patch information, see the GitHub Security Advisory GHSA-gx7q-6fhr-5h33 and the GitHub Commit Update.
Workarounds
- Configure a reverse proxy or WAF to strip or block the skip_timeout_reset parameter from external requests until patching is possible
- Implement IP whitelisting at the network level to restrict access to trusted addresses only
- Reduce session timeout values to minimize the window of opportunity for exploitation
- Consider disabling auto-refresh features (Patient Flow Board, Messages polling) temporarily in high-risk environments
# Configuration example
# Apache mod_rewrite rule to block skip_timeout_reset from external sources
# Add to OpenEMR .htaccess or virtual host configuration
RewriteEngine On
RewriteCond %{REMOTE_ADDR} !^(127\.0\.0\.1|10\.0\.0\.)
RewriteCond %{QUERY_STRING} skip_timeout_reset [NC]
RewriteRule ^.*$ - [F,L]
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


