CVE-2026-81921 Overview
CVE-2026-81921 is a missing authorization vulnerability [CWE-862] in Concrete CMS versions 8.5.3 through 9.5.2. The flaw resides in the OAuth 2.0 refresh-token grant, which uses the unmodified upstream League OAuth2 grant implementation. The grant issues new access tokens from a valid refresh token without re-validating the associated account's active status. A user who obtained a refresh token while active can continue to mint valid access tokens after being deactivated or suspended (uIsActive=0). Deactivating an account therefore does not revoke its API access.
Critical Impact
Deactivated or suspended Concrete CMS accounts retain the ability to generate new OAuth access tokens, allowing continued API access after account revocation.
Affected Products
- Concrete CMS 8.5.3 through 8.x (final 8.x releases)
- Concrete CMS 9.0 through 9.5.2
- Deployments using the OAuth 2.0 refresh-token grant
Discovery Timeline
- 2026-09-15 - CVE-2026-81921 published to the National Vulnerability Database (NVD)
- 2026-09-16 - Last updated in NVD database
- Reported by sh4d0byss and credited by the Concrete CMS security team
Technical Details for CVE-2026-81921
Vulnerability Analysis
The vulnerability is a missing authorization check in the OAuth 2.0 refresh-token flow. Concrete CMS integrates the upstream League OAuth2 server library and relies on its default refresh-token grant behavior. That default flow validates the refresh token's cryptographic integrity, expiration, and scope, but does not consult application-level account state. Concrete CMS did not extend the grant to re-check the uIsActive flag on the associated user account before issuing new access tokens.
The consequence is a durable authorization gap. Once an attacker or former user obtains a valid refresh token, that token can be exchanged for access tokens even after an administrator disables the account. The account appears revoked in the administrative interface while retaining live API credentials.
Root Cause
The root cause is unmodified reuse of a third-party OAuth grant without application-specific policy enforcement. The upstream League grant treats a refresh token as sufficient proof of continued authorization. Concrete CMS never inserts a post-token-validation hook to query the user store and reject requests where uIsActive=0.
Attack Vector
The attack is network-based and requires low privileges: the actor must already hold a valid refresh token issued while the account was active. After the account is deactivated, the actor sends a standard grant_type=refresh_token request to the OAuth token endpoint. The server validates the refresh token, skips the account-state check, and returns a new access token. The actor then invokes API endpoints authorized to the original user, achieving limited read and write access to resources within that user's scope.
No public exploit or proof-of-concept code has been published. See the ConcreteCMS 9.5.3 Release Notes for the vendor's technical description.
Detection Methods for CVE-2026-81921
Indicators of Compromise
- OAuth token endpoint requests using grant_type=refresh_token where the underlying user has uIsActive=0 in the Concrete CMS database.
- Successful API calls authenticated with an access token whose owning account is marked deactivated or suspended.
- Long-lived refresh-token reuse patterns from IP addresses or user agents that differ from the account's historical activity.
Detection Strategies
- Correlate OAuth token issuance logs with the Users table state, alerting when tokens are minted for accounts where uIsActive=0.
- Baseline expected refresh-token exchange rates per account and flag activity from accounts recently disabled by administrators.
- Audit administrative deactivation events and verify that no API traffic follows within the refresh-token lifetime.
Monitoring Recommendations
- Enable verbose logging on the /oauth/token endpoint, capturing grant type, client identifier, user identifier, and result.
- Forward OAuth server logs and Concrete CMS application logs to a centralized analytics platform for cross-referencing with account-state changes.
- Review OAuth client and refresh-token inventories on a scheduled cadence, revoking tokens issued to accounts that are no longer active.
How to Mitigate CVE-2026-81921
Immediate Actions Required
- Upgrade Concrete CMS to version 9.5.3 or later, which addresses the missing account-state check.
- Immediately revoke all outstanding refresh tokens belonging to accounts that have been deactivated or suspended.
- Audit the OAuth client and token stores to identify tokens issued to accounts no longer in good standing.
Patch Information
The fix is included in Concrete CMS 9.5.3. Refer to the ConcreteCMS 9.5.3 Release Notes for upgrade instructions and the full changelog. Administrators running 8.5.3 through 8.x should plan migration to a supported 9.5.3+ release, as the vulnerable grant behavior affects the 8.x branch as well.
Workarounds
- Disable the OAuth 2.0 refresh-token grant for clients that do not require it, forcing re-authentication instead of token renewal.
- Shorten refresh-token lifetimes to reduce the window during which a deactivated account can continue to mint access tokens.
- Implement an administrative procedure that revokes all OAuth tokens tied to a user at the moment uIsActive is set to 0.
# Revoke OAuth refresh tokens for a deactivated user (illustrative)
# Adjust table and column names to match your Concrete CMS schema and OAuth store
mysql -u <admin> -p <database> -e \
"DELETE FROM OauthRefreshTokens WHERE user_id IN (SELECT uID FROM Users WHERE uIsActive = 0);"
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.