Introduction
An unauthenticated attacker who can reach an OpenAM server running 14.0.0 through 16.1.3 can quietly collect live iPlanetDirectoryPro session tokens as users and administrators log in, log out, and time out. Those tokens are bearer credentials accepted by OpenAM REST endpoints and by applications relying on OpenAM single sign-on, so one captured administrator session can lead to configuration takeover and, according to the maintainer, command execution as the OpenAM service account.
OpenAM is an access management server maintained by Open Identity Platform, an independent community project that describes itself as the free, open-source continuation of the identity stack ForgeRock was built on, forked from the last freely licensed releases. It provides single sign-on, authorization policies, more than 20 authentication modules, multifactor and adaptive authentication, and can act as an identity provider over SAML, OAuth 2.0 and OpenID Connect 1.0. The project is CDDL licensed, with no per-user or per-server fees, and independent vendors offer commercial support. That makes it a self-hosted option for organizations leaving ForgeRock, although the available sources do not quantify its installed base.
Technical information
The primary weakness recorded for CVE-2026-123551 is CWE-201, Insertion of Sensitive Information Into Sent Data. The maintainer also identifies authentication bypass, insufficiently protected credentials, open redirect and missing authorization weaknesses. In practice, the bug is a chain: an internal dispatch skips a security filter, a notification channel accepts subscriptions it should refuse, and the data on that channel is a reusable credential.
The credential on the wire
OpenAM publishes session notifications for policy agents. These notifications carry the full iPlanetDirectoryPro session identifier whenever a session is created, logged out, timed out, or has a property changed. That identifier is a bearer credential, so whoever holds it can act as the session owner. Agent notifications are controlled by the advanced server property org.forgerock.openam.notifications.agents.enabled, which is enabled by default. The advisory states that no separate federation, self-service or agent feature configuration is required for exposure, so a deployment that never intentionally installed policy agents is not automatically safe.
Why the agent-only check could be skipped
The /notifications endpoint is protected by NotificationsWebSocketFilter, which is meant to admit only policy agents. The gap comes from Servlet dispatch semantics. Under the Servlet specification, a <filter-mapping> that lists no <dispatcher> element applies only to REQUEST dispatches. When a servlet calls RequestDispatcher.forward() or include(), or when an async or error page dispatch occurs, the container routes straight to the target. As the fix PR puts it, such a dispatch "reaches the servlet with the filter skipped".
A legacy Liberty ID FF endpoint performed exactly that kind of internal forward to a path taken from the request. The forward lives in FSUtils.forwardRequest. Before the patch, it validated the request-derived path with ForwardPathValidator.isSafeForwardPath and then handed the raw path to getRequestDispatcher. That leaves a gap between the string that was checked and the path the container actually resolves, and because the forward is an internal dispatch, the agent-only gate on /notifications never runs.
Unrestricted topic subscriptions
Once connected, a client could subscribe to any topic, including internal ones, not only the agent namespace. Combined with the bypass above, this lets an unauthenticated client receive the session topic and the tokens it carries. The advisory notes the connection "can be kept open indefinitely".
Attack flow
Based on the advisory, the chain looks like this. The maintainer withholds exact request details and proof-of-concept code, so we describe only the documented stages.
- Reach the service. The attacker needs network access to the OpenAM port. No credentials or user interaction are required.
- Bypass the agent check. The attacker sends a request to a legacy Liberty ID FF endpoint (the advisory names
/openam/preLoginand/openam/postLoginamong them) that triggers an unvalidated internal forward toward the notification WebSocket. Because the forward is aFORWARDdispatch,NotificationsWebSocketFilterdoes not execute. - Subscribe to internal topics. With the WebSocket open, the attacker subscribes to the session topic and other internal topics.
- Collect tokens passively. Every session creation, logout, timeout and property change broadcasts a full
iPlanetDirectoryProidentifier. The attacker simply waits while the connection stays open. - Reuse a captured token. Stolen tokens work against OpenAM REST endpoints and any application relying on OpenAM single sign-on, and the resulting requests look like the legitimate user's own activity.
- Escalate if an administrator was captured. A superuser session carries administrative capabilities. The maintainer states this can escalate to configuration takeover and command execution as the OpenAM service account. This is conditional on capturing an administrator session, not unconditional code execution on every reachable server.
The adjacent redirect issue
The same legacy ID FF endpoints also built redirect destinations from request data without validation. Where URL rewriting for cookieless clients is enabled, the user's session token could be appended to a destination on another host. Version 16.1.4 addresses this path as well.
Severity scoring
Two critical assessments have been published, using different CVSS versions:
- OpenAM maintainer, CVSS 3.1: 10.0, vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H - VulnCheck (CNA), CVSS 4.0: 10.0, vector
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H
NVD displays the VulnCheck score and states that its own assessment has not yet been provided, so the 10.0 should not be read as an independent NVD validation.
Exploitation status
Neither the maintainer advisory nor the VulnCheck advisory reports observed exploitation in the wild, names victims or campaigns, or attributes activity to a threat actor. The maintainer deliberately withholds proof-of-concept code to give operators time to upgrade, which describes the disclosure position rather than proving no exploit exists. The public timeline is: GitHub advisory on October 22, 2026; VulnCheck advisory on November 7, 2026; NVD publication on November 8, 2026. The earlier GitHub advisory still displays "No known CVE" while the CNA and NVD records carry CVE-2026-123551.
Patch information
The fix ships in OpenAM 16.1.4, released October 22, 2026 (tag 16.1.4, release commit f2b13be). No backported fix for older branches has been published. The advisory summarizes the fix as four changes:
- Security filters now run on internal dispatches, including the agent-only check on the WebSocket.
- The legacy Liberty ID FF endpoints were hardened. They no longer forward requests into OpenAM's internal endpoints, never pass a session token to another host, and only accept destinations from a per-provider allow list.
- WebSocket subscriptions are restricted to
/agent/topics. - Session events are still published on the agent session topic, because policy agents depend on it.
The public code for the dispatcher change and the ID FF forward hardening is in PR #1133, "Run the security filters on every dispatch type" (merged September 29, 2026, merge commit 81d8304a, listed in the 16.1.4 release notes). We could not find a separate public commit for the topic allow list or the Relay State allow list, so those two changes are described from the advisory rather than a diff.
1. Filters on every dispatcher type
Four narrowly mapped security filters now run on all five dispatcher types, REQUEST, FORWARD, INCLUDE, ASYNC and ERROR:
AuthNFilteron/ws/*AuthZFilteron/ws/*JAXRPCRequestFilteron/jaxrpc/*NotificationsWebSocketFilteron/notifications
An internal forward to the WebSocket endpoint now passes through the same authentication check as a direct request. The PR adds a regression test, SecurityFilterDispatchersTest, that parses the shipped web.xml and fails the build if any of these mappings loses a dispatcher type. Naming even one dispatcher replaces the default set, so without the test a later edit listing only some types would silently reopen the hole.
The maintainers deliberately did not change the filters mapped to /* (amSetupFilter, SecurityHeaders, AuditContextFilter, ResponseValidationFilter) or FQDNValidationFilter, since running those on every internal forward would change behavior across the product. That is left for a separate change.
2. Making JAXRPCRequestFilter reentrant
Because JAXRPCRequestFilter now also runs on FORWARD and INCLUDE, a nested dispatch can enter it twice on the same thread. The old code always cleared its ThreadLocal on exit, which would drop the outer request's binding. The patched code saves and restores the previous binding:
HttpServletRequest previous = CURRENT_REQUEST.get(); CURRENT_REQUEST.set((HttpServletRequest) request); try { chain.doFilter(request, response); } finally { if (previous == null) { CURRENT_REQUEST.remove(); } else { CURRENT_REQUEST.set(previous); } }
A new test, nestedDispatchRestoresTheOuterRequestOnExit, covers this behavior.
3. Tighter checks on the ID FF forward target
FSUtils.forwardRequest now dispatches only the normalized form returned by a new helper, forwardTarget(), and returns HTTP 400 if the helper returns null. The excerpt below is from the patch:
String dispatchPath = ForwardPathValidator.forwardTarget(resource); if (dispatchPath == null) { FSUtils.debug.warning("FSUtils.forwardRequest: refusing to " + "forward to a path with traversal or a reserved " + "directory");
forwardTarget() reconstructs the path the container would map and checks it again:
- It runs the existing
isSafeForwardPathcheck first. - It strips path parameters (
;...). - It decodes percent escapes in a loop until no
%remains, while keeping+literal. - It refuses any
..segment and refuses aWEB-INFsegment anywhere in the path, not only at the root. For example,/x;a/%57EB-INF/y.jspis now rejected. - It appends the original query string after a fixed
?.
4. Changes described in the advisory only
- Topic allow-listing: clients can subscribe only to
/agent/topics. Any other topic is refused. - ID FF redirect handling: the endpoints no longer redirect to arbitrary request-supplied destinations and no longer append the session token to an off-host URL under cookieless URL rewriting. Destinations must match a new per-provider Relay State URL List.
Upgrade notes
- Customized
web.xml: if you maintain your ownweb.xml, copy the new dispatcher declarations onto theAuthNFilter,AuthZFilter,JAXRPCRequestFilterandNotificationsWebSocketFiltermappings. If you skip this, the bypass stays open even on 16.1.4 binaries. - Empty Relay State URL List: while empty, OpenAM only accepts destinations under the deployment's own URLs. Deployments that send users to another host after ID FF login, federation or logout must add those hosts, otherwise users land on the provider home page or the logout done page.
- Non-agent topics: any notification client subscribing outside
/agent/will be refused after upgrade.
Interim workarounds and post-exposure steps
While the upgrade is in progress, the advisory documents these measures:
- Restrict
/openam/notificationsand/openam/ws/*to legitimate agent hosts at the reverse proxy, load balancer or firewall. - Set
org.forgerock.openam.notifications.agents.enabled=falsewhere agents do not depend on notifications. - Block
/openam/preLoginand/openam/postLoginunless Liberty ID FF federation is required. - Treat current administrator and user sessions as potentially exposed and rotate them. Upgrading does not invalidate tokens that may already have been collected.
- Keep Groovy and JavaScript scripting services under the security manager with a restrictive allow list, restrict scripting configuration changes, and run the OpenAM container in an operating system sandbox with a read-only filesystem, no shell and a least-privilege account.
- Do not expose administrative or agent-facing endpoints to the public internet.
Detection methods
We found no public YARA, Sigma, Snort or Suricata rules and no IoC lists for CVE-2026-123551, and the advisory withholds technical details. Detection therefore rests on behavioral monitoring derived from the vendor's guidance.
The advisory describes the attack as passive: no authentication attempts, no failed logins, no lockouts, and hijacked requests "indistinguishable from the legitimate user's own session activity." Brute-force and login-failure monitoring will not catch it. The useful evidence sits at the start of the chain (reaching and subscribing to the WebSocket) and at the end (a stolen administrator session turned into configuration changes).
1. Allow-list notification WebSocket clients
- From reverse proxy, load balancer or WAF logs, enumerate hosts that connect to
/openam/notificationsand/openam/ws/*. These should be policy agent servers only. - Alert on any WebSocket upgrade or connection to those paths from outside that list, especially from user- or internet-facing networks.
- Prioritize long-lived connections. A client that is not a known agent holding a notification socket open for hours is a strong indicator, since tokens are only collected while the connection is open.
2. Watch topic subscriptions
If OpenAM debug logs or a WebSocket-aware proxy record subscription messages, flag:
- subscriptions to the session topic from any client that is not a known agent
- subscriptions to topics outside the
/agent/namespace, which the fixed release refuses and which are abnormal on a vulnerable instance
3. Watch legacy Liberty ID FF endpoints
- Baseline requests to
/openam/preLogin,/openam/postLoginand related ID FF paths. In deployments without ID FF, any request deserves review. - Correlate these requests with a notification WebSocket connection from the same source around the same time. That pairing fits the documented bypass chain.
- Review ID FF requests whose destination or relay parameters point to hosts outside your domains, which relates to the token-leaking redirect path when cookieless URL rewriting is enabled.
4. Watch for administrative post-compromise activity
- Scripting engine changes: alert on any change to the Groovy or JavaScript scripting service configuration, especially loosening of the security manager allow list or new scripts, and reconcile against change tickets.
- Child processes: treat any process spawned by the OpenAM service account (for example a shell) as high severity.
- Administrative REST activity: review admin REST calls from IP ranges an administrator never uses, or shortly after a suspicious notification socket was opened.
5. Scope exposure
Inventory OpenAM deployments on 14.0.0 through 16.1.3. Software composition analysis can flag the affected Maven artifacts under org.openidentityplatform.openam. Check whether org.forgerock.openam.notifications.agents.enabled is left at its default of enabled, and whether /openam/notifications or the ID FF endpoints are reachable beyond agent hosts. Because token theft leaves little trace, hunting should include reviewing past session activity, not only new alerts.
Affected systems and versions
- Product: OpenAM by Open Identity Platform (NVD vendor: OpenIdentityPlatform)
- Vulnerable: versions 14.0.0 through 16.1.3 (NVD and VulnCheck: 14.0.0 up to, but not including, 16.1.4)
- Fixed: 16.1.4
- Affected Maven artifacts (each vulnerable at
>= 14.0.0, <= 16.1.3, patched in 16.1.4):openam-server-onlyopenam-federation-libraryopenam-notifications-websocket
- Vulnerable configuration: agent notifications enabled via
org.forgerock.openam.notifications.agents.enabled, which is the default. No separate federation, self-service or agent feature configuration is required. - Not affected: releases before 14.0.0, which have no notification WebSocket.
- Partially fixed risk: 16.1.4 installations using a customized
web.xmlthat lacks the new dispatcher declarations remain exposed to the bypass. - Backports: none published for older branches.
Vendor security history
Open Identity Platform has published several substantive security fixes for OpenAM in 2026:
- OpenAM 16.1.1 addressed LDAP injection, session hijacking via CDSSO and Session Service RPC, and conditional code execution through WebAuthn deserialization. The release notes do not indicate these were exploited in the wild.
- OpenAM 16.1.4 fixed this notification WebSocket issue alongside acceptance of unsigned SAML v2.0 assertions in some bindings and a self-registration flaw that could let an anonymous user create an administrator account.
The repository publishes a security support policy and asks reporters to open a draft security advisory. The CVE record credits DauHoangTai as reporter, maximthomas as remediation developer, and tsujiguchitky and vharseko as remediation reviewers. The sources do not establish discovery-to-patch times or independent audit results, so we draw no conclusion on response speed.
References
- NVD: CVE-2026-123551
- CVE Record: CVE-2026-123551
- GitHub Security Advisory GHSA-5c3q-hp86-xjr8
- GHSA-5c3q-hp86-xjr8 via GitHub API
- VulnCheck Advisory: OpenAM 14.0.0 before 16.1.4 Session Token Disclosure via Notification WebSocket
- OpenAM 16.1.4 Release (GitHub API)
- PR #1133: Run the security filters on every dispatch type
- PR #1133 Changed Files
- OpenAM 16.1.4 Released, Open Identity Platform
- OpenAM 16.1.1 Released, Open Identity Platform
- OpenAM Product Page
- ForgeRock Alternative and Migration Path, Open Identity Platform
- OpenAM Security Advisories on GitHub
- OpenAM Security Overview on GitHub
- StackFlag: CVE-2026-123551
- VulDB: CVE-2026-123551



