Sep 2, 2026·7 min read·3 visits
Filament's TOTP verification allowed the replay of older valid codes within the drift window because it tracked used codes individually rather than globally tracking the last accepted timestep. This allowed an attacker with compromised passwords to bypass multi-factor authentication.
A multi-factor authentication bypass vulnerability exists in Filament (Laravel full-stack framework panels) due to improper time-step tracking of Time-Based One-Time Password (TOTP) codes. By submitting valid TOTP codes from an older time window within the drift allowance, an attacker with a user's password can bypass the single-use MFA guarantee and obtain unauthorized account access.
Filament is an administrative panel and full-stack rapid development framework built on top of Laravel. Within its core architecture, Filament provides built-in support for Multi-Factor Authentication (MFA), including Time-Based One-Time Passwords (TOTP) conforming to RFC 6238. This capability is used to secure high-privilege access to admin panels and backend management consoles, exposing an administrative attack surface to malicious actors.
A vulnerability designated as CVE-2026-84306 (GHSA-r3j6-gpjw-qfjr) was identified in the MFA verification logic of Filament. The software failed to enforce strict monotonic progression of the TOTP time-steps. As a result, older, unused TOTP codes within the accepted time-drift window could be successfully replayed even after a newer TOTP code had already been verified and processed.
This flaw belongs to the class of CWE-294 (Authentication Bypass by Capture-replay). By exploiting this vulnerability, an attacker who has already acquired a target user's primary credentials can bypass the secondary MFA challenge, gaining unauthorized administrative access to the application panel.
The security flaw resides in the packages/panels/src/Auth/MultiFactor/App/AppAuthentication.php component, specifically within the verifyCode method. According to the RFC 6238 specifications, once a TOTP code corresponding to a specific timestep is verified and accepted, the server must invalidate that entire timestep and all previous timesteps. This behavior ensures that the authentication state progresses strictly forward, preventing the validation of any older codes, even if those codes still fall within the configured clock drift window (typically around 4 minutes to accommodate network latency and client desynchronization).
In vulnerable versions of Filament, the code-tracking mechanism maintained state on a per-code basis rather than a per-secret basis. The application generated a unique cache key for each verification attempt using the following schema:
$cacheKey = 'filament.app_authentication_codes.' . md5($secret . $code);Because the cache key incorporated both the user's multi-factor secret and the specific 6-digit verification code string submitted, each unique code generated its own distinct cache entry. While a user could not reuse the exact same 6-digit code within its active validity lifespan, the server treated any other valid code from a different timestep within the allowed clock drift window as entirely separate and untracked. Consequently, if a user logged in with a code from timestep T, an attacker possessing an unused code from timestep T-1 could submit it, bypass the tracking check, and successfully authenticate.
Analyzing the patch applied to packages/panels/src/Auth/MultiFactor/App/AppAuthentication.php reveals how the flaw was remedied. The tracking mechanism was modified to monitor the timestamp of the last validated code globally for each secret rather than monitoring individual 6-digit code strings.
Before the patch, the verifyCode method tracked code reuse by incorporating the submitted code into the MD5 hash:
$cacheKey = 'filament.app_authentication_codes.' . md5($secret . $code);
$timestamp = $this->google2FA->verifyKeyNewer($secret, $code, cache()->get($cacheKey), $this->getCodeWindow());Because each individual code generated a separate cache key, the underlying library's verifyKeyNewer function compared the current code's timestep against an empty or non-existent cached timestamp, allowing older but still mathematically valid codes to pass verification.
In the patched implementation, the cache key is generated using only the multi-factor secret, ensuring a single centralized record of the last authenticated timestamp per user:
$cacheKey = 'filament.app_authentication_codes.' . md5($secret);
$verifyCode = function () use ($cacheKey, $code, $secret): bool {
// Retrieve the last used timestamp globally for this secret
$timestamp = $this->google2FA->verifyKeyNewer($secret, $code, Cache::get($cacheKey), $this->getCodeWindow());
if ($timestamp === false) {
return false;
}
if ($timestamp === true) {
$timestamp = $this->google2FA->getTimestamp();
}
// Save the timestamp of the verified code back into the cache
Cache::put($cacheKey, $timestamp, ($this->getCodeWindow() + 1) * 60);
return true;
};Additionally, the patch implements a critical optimization using cache locks to block race conditions where an attacker could execute parallel, concurrent verification requests:
if (! (Cache::getStore() instanceof LockProvider)) {
return $verifyCode();
}
return Cache::lock("{$cacheKey}.lock", 10)->block(10, $verifyCode);This implementation ensures that concurrent operations must wait for the preceding validation to commit its state to the cache, eliminating race-condition windows.
An attack targeting this vulnerability is classified as highly complex because it requires a specific set of pre-existing conditions and access rights. An attacker cannot exploit this flaw to compromise an account unless they have already obtained the target user's primary credentials (username and password) and can intercept the TOTP codes transmitted by the legitimate user.
Credential Harvest: The attacker steals the user's login credentials via phishing, malware, or credential stuffing.
TOTP Interception: The attacker intercepts the user's TOTP codes. For example, if the user receives TOTP codes via SMS or email, or if the attacker is in a position to monitor the network interface or local device storage, they can intercept a code from an earlier timestep (e.g., T-1 or T-2) that the user did not use because they had already generated a newer code (timestep T).
MFA Replay: The user authenticates with code T. The server accepts the code and writes a cache entry for that specific code. The attacker then authenticates using the intercepted, older code (T-1).
Bypass Verification: Since the older code T-1 has never been recorded in the cache, the server evaluates it as a valid, unused code because it falls within the acceptable clock drift window. The server grants the attacker full access to the administrative panel.
The security impact of CVE-2026-84306 is marked by the complete breakdown of multi-factor authentication integrity for affected Filament installations. When bypassed, the primary layer of credential protection is rendered ineffective, allowing attackers with compromised user credentials to elevate their privileges to that of the targeted administrative account.
Since Filament is frequently used as an administrative interface for business databases, customer information systems, and core application configurations, an administrative session compromise typically results in high confidentiality and integrity impacts. An attacker could extract database contents, manipulate system configuration parameters, or perform unauthorized actions on behalf of administrative users.
Despite the severity of a successful bypass, the exploitability of this vulnerability is limited by the strict prerequisites. The attacker must already hold valid primary credentials and have active visibility into the user's TOTP sequence within a tight time window of approximately four minutes. This requirement accounts for the CVSS score of 6.5 and the high-complexity classification.
To eliminate the exposure caused by CVE-2026-84306, administrators and developers must upgrade Filament to a patched release. No manual configuration changes to the codebase are required once the upgrade is completed.
Run the following commands in the root directory of the application:
# For v4 installations
composer update filament/filament:^4.12.6
# For v5 installations
composer update filament/filament:^5.7.6To ensure the performance and security of the newly introduced mutex lock mechanism, the application's caching backend must support locking. Cache stores such as file, apc, or database drivers without locking support will fail silently back to non-locking verification, maintaining a small race-condition vulnerability window.
It is strongly advised to deploy a cache backend that supports native distributed locking, such as Redis or Memcached, and ensure that the CACHE_DRIVER environment variable is configured to utilize this backend in production.
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Filament FilamentPHP | >= 4.0.0, < 4.12.6 | 4.12.6 |
Filament FilamentPHP | >= 5.0.0, < 5.7.6 | 5.7.6 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-294 |
| Attack Vector | Network |
| CVSS v3.1 Score | 6.5 |
| Exploit Status | None/Unproven |
| CISA KEV Status | Not Listed |
| Vulnerability Type | Authentication Bypass by Capture-replay |
The software receives a one-time password or other authentication credential that was captured from a previous session, and it accepts the replayed credential to establish a new, unauthorized session.
An authentication oracle vulnerability exists in Filament before 4.12.5 and 5.7.5. The application initiates MFA challenge workflows prior to verifying user authorization policies, allowing unauthenticated attackers to validate guessed credentials.
CVE-2026-19418 is a high-severity origin validation vulnerability in TYPO3 CMS that enables Cross-Site Request Forgery (CSRF) and access control bypasses. Due to architectural consolidation of entry points in version 13.0, the core ReferrerEnforcer fails to isolate backend endpoints from the frontend, allowing an attacker with frontend script execution capabilities to perform unauthorized administrative actions.
CVE-2026-84304 is a high-severity uncontrolled resource consumption vulnerability in gRPC-Go, the Go implementation of the gRPC framework. The issue stems from a memory amplification flaw inside the HTTP/2 DATA frame processing subsystem. Remote, unauthenticated attackers can exploit this vulnerability by sending a high volume of heavily fragmented, tiny DATA frames within multiplexed concurrent streams. This causes gRPC-Go servers to allocate excessive internal metadata structures on the Go heap, leading to severe heap memory amplification, intense garbage collection thrashing, and process termination due to Out-of-Memory (OOM) conditions.
CVE-2026-79675 is a critical command injection vulnerability in NLTK versions prior to 3.10.3 that permits remote attackers to execute arbitrary code on the hosting system. This vulnerability stems from an incomplete mitigation of a previous vulnerability, CVE-2026-12841. While NLTK verified global JVM options configured through the library's setup routines, it failed to perform equivalent safety checks on options provided during per-call invocations of Stanford NLP Java wrappers. Attackers controlling these parameters can pass dangerous Java configuration options to the system shell, bypassing security boundaries to spawn interactive processes or load untrusted Java archives.
A vulnerability in Django REST Framework (DRF) before version 3.17.2 allows remote attackers to bypass the native Django DATA_UPLOAD_MAX_MEMORY_SIZE limits. When parsing JSON or URL-encoded request bodies, DRF's JSONParser and FormParser read directly from the low-level HTTP network stream, bypassing Django's high-level request size checks and causing Denial of Service (DoS) via resource exhaustion.
A directory traversal vulnerability exists in pacquet, the Rust port of pnpm. When executing an install with the --trust-lockfile flag enabled, a crafted pnpm-lock.yaml file bypasses resolution-policy verification. This allows an attacker to inject path traversal sequences into package names or versions, leading to symbolic links being written outside the workspace directory.