OpenAM, an open-source IAM platform, has a server-side request forgery (SSRF) vulnerability in its /sessionservice endpoint. Authenticated users can register URLs for session event notifications without sufficient restrictions, allowing outbound requests to attacker-controlled destinations. This may expose session-related data. The vulnerability affects versions prior to 16.1.1 and has a high severity score of 8.6. A fix is available in version 16.1.1.
OpenAM, an open-source identity and access management platform, has an LDAP injection vulnerability in its REST API. The flaw exists in the `_queryId` HTTP query parameter used in user and group query endpoints, where input is not properly escaped before being incorporated into LDAP filter strings. This allows authenticated attackers to inject LDAP metacharacters, potentially enabling user enumeration and blind LDAP injection attacks. The vulnerability affects OpenAM versions prior to 16.1.1 and has a high severity rating with a CVSS score of 8.7. A fix is available in version 16.1.1.
# Vulnerability
`SearchFirstActiveDirectoryRealm.findUserDn()` substitutes the user-supplied username from the login form into an LDAP search filter template (default `cn={0}`) **without escaping RFC 4515 filter metacharacters** (`*`, `(`, `)`, `\`, NUL). Combined with `SearchControls.setCountLimit(1)` on the same call site, this allows three distinct attack primitives:
1. **Authentication confusion** — typing username `*` causes the realm to construct filter `cn=*`, return the first directory entry (typically a privileged account in AD ordering), and attempt bind against that DN with the attacker's password.
2. **Audit log evasion** — payload `bob)(uid=alice` is recorded verbatim in audit logs while the realm searches with the malformed filter, breaking accountability/compliance (SOX, PCI-DSS, ISO 27001).
3. **Directory enumeration** — wildcards and timing differences allow reconnaissance of OU structure and admin group membership.
A repo-wide search for any LDAP escape helper (`escapeLdap`, `encodeFilter`, `escapeFilter`, `ldapEscape`) returns **zero hits** — the defense is not just missing, it was never added.
> **Applicability note:** This realm is opt-in. The shipped default LDAP example (`dist/src/conf/shiro.example.ldap.ini`) uses Shiro's `DefaultLdapRealm` with `userDnTemplate` and is **NOT** affected. However, the realm exists precisely to support Active Directory environments where users log in via `sAMAccountName` and the realm must search for the DN first — the canonical LINE corporate AD-backed SSO scenario. Internal deployments using AD-backed login almost certainly select this realm.
---
## Evidence
**File:** `server-auth/shiro/src/main/java/com/linecorp/centraldogma/server/auth/shiro/realm/SearchFirstActiveDirectoryRealm.java`
**Lines 148–176** on branch `main` @ commit `d64a5151`:
```java
@Nullable
protected String findUserDn(LdapContextFactory ldapContextFactory, String username)
throws NamingException {
LdapContext ctx = null;
try {
ctx = ldapContextFactory.getSystemLdapContext();
final SearchControls ctrl = new SearchControls();
ctrl.setCountLimit(1); // line 156 — returns FIRST match only
ctrl.setSearchScope(SearchControls.SUBTREE_SCOPE);
ctrl.setTimeLimit(searchTimeoutMillis);
final String filter =
searchFilter != null ? USERNAME_PLACEHOLDER.matcher(searchFilter)
.replaceAll(username) // line 162 — RAW SUBSTITUTION
: username; // line 163
final NamingEnumeration result = ctx.search(searchBase, filter, ctrl);
...
```
`USERNAME_PLACEHOLDER = Pattern.compile("\\{0}")`. Default `searchFilter = "cn={0}"`.
### Data flow from HTTP login to vulnerable substitution
| Step | Component |
|------|-----------|
| HTTP login form | `POST /api/v1/login` form field `username` |
| `ShiroLoginService.usernamePassword()` (lines 198–223) | applies `loginNameNormalizer` (Unicode lowercase only — **NOT** LDAP escape) |
| `Subject.login(new UsernamePasswordToken(username, password))` | Shiro hand-off |
| `ActiveDirectoryRealm.doGetAuthenticationInfo` (Shiro core) | calls `queryForAuthenticationInfo0` |
| `SearchFirstActiveDirectoryRealm.findUserDn(factory, upToken.getUsername())` | username flows in **verbatim** |
### Repository-wide escape helper grep
| Search term | Hits |
|-------------|------|
| `escapeLdap` | 0 |
| `encodeFilter` | 0 |
| `escapeFilter` | 0 |
| `ldapEscape` | 0 |
---
## PoC
Self-contained JUnit 5 test using UnboundID `InMemoryDirectoryServer` (in-process, no external LDAP required). Drop into `server-auth/shiro/src/test/java/com/linecorp/centraldogma/server/auth/shiro/realm/LdapInjectionPoCTest.java` and add `com.unboundid:unboundid-ldapsdk:7.0.0` as a test dependency.
> The PoC works by subclassing the realm and overriding `findUserDn()` to capture the actual LDAP filter string sent to the directory — the captured filter is the structural evidence, independent of LDAP server strictness about bind outcomes.
```java
/*
* Copyright 2026 LINE Corporation
*
* SECURITY PoC — NOT FOR MERGE INTO THE MAIN TEST SUITE.
*
* This JUnit class demonstrates the LDAP filter injection in
* SearchFirstActiveDirectoryRealm. Drop into
* server-auth/shiro/src/test/java/com/linecorp/centraldogma/server/auth/shiro/realm/
* Adds the UnboundID LDAP SDK as a test dep.
*/
package com.linecorp.centraldogma.server.auth.shiro.realm;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import javax.naming.directory.SearchControls;
import javax.naming.ldap.LdapContext;
import org.apache.shiro.realm.ldap.JndiLdapContextFactory;
import org.apache.shiro.realm.ldap.LdapContextFactory;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
## Vulnerability
`ZooKeeperReplicationConfig.secret()` silently substitutes the hard-coded constant `"ch4n63m3"` (leetspeak for "change me") whenever the operator omits `replication.secret`. The same secret is wired into both the **client-facing SASL context** and the **quorum/learner SASL contexts** of the embedded ZooKeeper. The constant is in OSS source on GitHub and is discoverable via code search in seconds.
### Three Reinforcing Defects
1. **OSS-public credential** — `DEFAULT_SECRET` is in `line/centraldogma` source.
2. **Silent fallback** — `firstNonNull(convertValue(...), DEFAULT_SECRET)` substitutes the default with no log, no warning, no startup banner. The only sanity check `checkArgument(!secret().isEmpty(), ...)` passes because the getter substitutes the literal before the emptiness check runs.
3. **Dual-purpose secret** — used for both ZK client-port super auth and inter-peer quorum SASL. A single leaked password authenticates against both surfaces.
### Architecture Context (Important)
Central Dogma does **NOT** connect to an external ZooKeeper ensemble. Each replica embeds a `QuorumPeer` (`EmbeddedZooKeeper extends QuorumPeer`) inside its own JVM. The Central Dogma cluster **IS** the ZK ensemble. So the "ZK network" is the inter-replica network of the Central Dogma cluster itself.
### Applicability
| `replication.method` | ZK Started? | Applicable? |
|---|---|---|
| `NONE` (standalone, dev default) | No | **NOT applicable** |
| `ZOOKEEPER` (HA production) | Yes, embedded on every replica | **Fully applicable** — canonical production configuration |
---
## Evidence
**File:** `server/src/main/java/com/linecorp/centraldogma/server/ZooKeeperReplicationConfig.java`
**Branch:** `main` @ commit `d64a5151`
**Line 53** — the constant:
```java
private static final String DEFAULT_SECRET = "ch4n63m3";
```
**Lines 210–215** — the silent fallback:
```java
/**
* Returns the secret string used for authenticating the ZooKeeper peers.
*/
public String secret() {
return firstNonNull(convertValue(secret, "replication.secret"), DEFAULT_SECRET);
}
```
---
**File:** `server/src/main/java/com/linecorp/centraldogma/server/internal/replication/ZooKeeperCommandExecutor.java`
**Lines 586–607** — JAAS wiring (same secret on both surfaces):
```java
final String escapedSecret = jaasValueEscaper.escape(cfg.secret());
ImmutableList.of("Server", EmbeddedZooKeeper.SASL_SERVER_LOGIN_CONTEXT).forEach(name -> {
buf.append(name).append(" {").append(newline);
buf.append(DigestLoginModule.class.getName()).append(" required").append(newline);
buf.append("user_super=\"").append(escapedSecret).append("\";").append(newline);
buf.append("};").append(newline);
});
ImmutableList.of("Client", EmbeddedZooKeeper.SASL_LEARNER_LOGIN_CONTEXT).forEach(name -> {
buf.append(name).append(" {").append(newline);
buf.append(DigestLoginModule.class.getName()).append(" required").append(newline);
buf.append("username=\"super\"").append(newline);
buf.append("password=\"").append(escapedSecret).append("\";").append(newline);
buf.append("};").append(newline);
});
```
---
**File:** `server/src/main/java/com/linecorp/centraldogma/server/internal/replication/EmbeddedZooKeeper.java`
**Line 44** — proves CD embeds the ZK server:
```java
final class EmbeddedZooKeeper extends QuorumPeer {
```
**Lines 213–220** — client port binding (loopback only):
```java
private static ServerCnxnFactory createCnxnFactory(QuorumPeerConfig zkCfg) throws IOException {
final InetSocketAddress bindAddr = zkCfg.getClientPortAddress();
final ServerCnxnFactory cnxnFactory = ServerCnxnFactory.createFactory();
// Listen only on 127.0.0.1 because we do not want to expose ZooKeeper to others.
cnxnFactory.configure(new InetSocketAddress("127.0.0.1", bindAddr != null ? bindAddr.getPort() : 0),
zkCfg.getMaxClientCnxns());
return cnxnFactory;
}
```
> Quorum/election ports are **NOT** loopback-bound — they bind to `replication.servers[].host` as configured, exposed on the inter-replica network.
---
## PoC
Two attack surfaces, two scenarios. **Surface A** (client port, same-host) is implemented as a working read-only PoC. **Surface B** (quorum-port peer impersonation) is documented but intentionally not weaponized.
### Surface A — Same-Host Client Port (Loopback) PoC
Python + kazoo + pure-sasl. Authenticates as `super` over SASL DIGEST-MD5 with the leaked secret and reads the full Central Dogma replication log. Hardcoded to `127.0.0.1`, read-only, prints first 5 entries.
```python
#!/usr/bin/env python3
"""
C3 PoC -- ZooKeeper default-secret takeover (read-only, loopback only).
Demonstrates that a Central Dogma instance launched with a
ZooKeeper-replicated configuration but without `replication.secret` set
exposes its embedded ZooKeeper to anyone with local-host access, using
the well-known credential `super / ch4n63m3`.
SAFETY:
* Hardcoded to 127.0.0.1. Refuses any other targ
# Vulnerability
Central Dogma's Git mirror SSH client installs an Apache MINA SSHD `ServerKeyVerifier` lambda that returns `true` unconditionally for every outbound SSH connection used by `git+ssh://` mirrors. The accompanying lines disable the `known_hosts` and `~/.ssh/config` fallbacks, and a repo-wide search confirms that no host-key pinning mechanism (no `acceptedHostKeys`, `knownHosts`, `KnownHostsServerKeyVerifier`, `StaticServerKeyVerifier`, or `RequiredServerKeyVerifier`) exists anywhere in `server-mirror-git/`. Operators have no opt-in way to enable verification. Every outbound mirror connection blindly trusts whatever host key the remote presents.
## Evidence
File: `server-mirror-git/src/main/java/com/linecorp/centraldogma/server/internal/mirror/SshGitMirror.java`
Lines 143-160 (especially 149) on branch `main` @ commit `d64a5151`:
```java
private SshClient createSshClient() {
final ClientBuilder builder = ClientBuilder.builder();
// Do not use local file system.
builder.hostConfigEntryResolver(HostConfigEntryResolver.EMPTY); // line 146
builder.fileSystemFactory(NoneFileSystemFactory.INSTANCE); // line 147
// Do not verify the server key.
builder.serverKeyVerifier((clientSession, remoteAddress, serverKey) -> true); // line 149
...
}
```
Verification:
- Read confirmed on 2026-05-21 against `main` @ `d64a5151`.
- A multi-agent code audit verified that no operator-facing pinning field exists on `SshKeyCredential`, `PasswordCredential`, or `MirrorContext`.
- Exploit PoC reproduced locally with a `paramiko`-based fake SSH server bound to 127.0.0.1. The fake server presents an ephemeral RSA host key never seen before; the Central Dogma mirror client accepts the connection and proceeds to authentication, logging the offered username and public-key fingerprint. A correctly hardened SSH client would refuse the connection before reaching the authentication phase.
- Full PoC artifacts (read-only, loopback-only) at `~/centraldogma-poc/C1_ssh_hostkey_bypass/` on the reporter's workstation.
## Impact
Threat model: An on-path attacker on the corporate network — ARP spoofing on the LAN, internal DNS poisoning, malicious internal DNS overriding `github.com` or the configured internal git hostname, BGP hijack, sidecar/CNI compromise in Kubernetes, or any process able to answer TCP on the resolved IP. No Central Dogma account required; only network position.
1. **Direction `LOCAL_TO_REMOTE`**: the attacker impersonating the remote git server receives the entire mirrored repository contents over the SSH session. Central Dogma is a configuration store, so this typically exfiltrates DB credentials, third-party API keys, certificates, feature flags, and any other secret configuration committed to mirrored repositories.
2. **Direction `REMOTE_TO_LOCAL`**: the attacker can serve arbitrary commits which Central Dogma materializes into the local repo and then broadcasts to every subscribing microservice via the watch API. This is a supply-chain root-of-trust compromise across all downstream services consuming Central Dogma configuration.
3. **Credential theft chain with finding H2** (mirror credentials are not bound to a hostname): an SSH key or access token configured for `github.com` can be captured by the attacker's fake server and replayed against the real upstream, extending impact beyond Central Dogma itself.
Scope is `Changed` (CVSS) because exploitation alters trust assumptions of every downstream client of Central Dogma, not just Central Dogma itself.
## How to fix
1. Add an `acceptedHostKeys: List<String>` field to `SshKeyCredential` and `PasswordCredential` (or to `MirrorContext`). Values are SHA-256 fingerprints of trusted remote SSH server host keys, e.g. `SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8`.
2. Replace the accept-all lambda at `SshGitMirror.java:149` with a verifier that computes the SHA-256 fingerprint of the presented host key and compares it against the credential's allowlist using a constant-time comparison.
3. Refuse to connect when `acceptedHostKeys` is empty — fail-closed. Do not implement implicit TOFU.
4. Optionally provide an admin-only `dogma mirror probe-host-key <remote>` tool that performs a single audited connection, prints the server's fingerprint, and prompts the operator to add it to the credential. This makes TOFU an explicit, audited operation.
5. Update `SshGitMirrorTest.java` and `it/mirror/*` tests to pin a test fingerprint or use the explicit trust-once tool, so the regression cannot silently return.
An authenticated user can perform XSS.
This issue affects Apache Atlas versions 2.4.0 and earlier.
Users are recommended to upgrade to version 2.5.0, which fixes the issue.
Apache NiFi 0.0.1 through 2.9.0 support building qualified URLs from one of several HTTP request headers that provide an alternative to the standard Host header without validating the values provided. Apache NiFi 1.6.0 introduced a configurable application property to restrict values provided in the HTTP Host header, but did not apply the validation to alternative Proxy and Forwarded headers. The absence of proxy host header validation allowed a client to instruct Apache NiFi web services to construct invalid qualified URLs for redirection or data references. Upgrading to Apache NiFi 2.10.0 is the recommended mitigation, which implements validation for the X-ProxyHost and X-Forwarded-Host HTTP request headers based on the nifi.web.proxy.host property. Enabling header validation requires configuring the application with HTTPS. Reverse proxy servers in front of Apache NiFi are responsible for filtering input request headers and providing allowed values to the application.
Apache NiFi 1.12.0 through 2.9.0 are missing authorization when replacing Process Groups that include extension components with specific Required Permissions based on the Restricted annotation. The Restricted annotation indicates additional privileges required, but framework authorization did not check restricted status when handling requests to replace Process Groups. The missing authorization permits a user with general write access to add components with Restricted status. Apache NiFi installations that do not implement specific authorization for Restricted components are not subject to this vulnerability because the framework enforces write permissions as the security boundary. Upgrading to Apache NiFi 2.9.0 is the recommended mitigation, which removes the implementation of Restricted status authorization from the framework.
Authorization handling for component configuration verification requests in Apache NiFi 1.15.0 through 2.9.0 allows clients with read access to submit proposed configuration properties. The proposed properties override current configuration, enabling users with read access to invoke predefined verification methods with alternative settings. Apache NiFi installations that do not implement different levels of authorization for viewing and modifying component configuration are not subject to this vulnerability. Upgrading to Apache NiFi 2.10.0 is the recommended mitigation, requiring write access to submit configuration verification requests.
Quarkus is a Java framework for building cloud-native applications. Prior to versions 3.37.0, 3.36.3, 3.33.2.1, 3.33.3, 3.27.4.1, 3.27.5, and 3.20.6.2, Quarkus HTTP path-based authorization policies can be bypassed using encoded semicolons (%3B) to smuggle matrix parameters past the security layer, and using encoded slashes (%2F) or backslashes (%5C) to access protected static resources. This is a distinct issue from CVE-2026-39852, which addressed only literal semicolon stripping. Versions 3.37.0, 3.36.3, 3.33.2.1, 3.33.3, 3.27.4.1, 3.27.5, and 3.20.6.2 contain a patch.
Apache CXF versions prior to 4.2.2 and 4.1.7 contain a vulnerability in the JwsJsonContainerRequestFilter where metadata from an unvalidated first signature entry is trusted. This flaw allows the processing of unauthenticated metadata, potentially bypassing assumptions about the authenticity of Content-Type or protected HTTP-header metadata. This can affect downstream JAX-RS entity parsing or signed-header consistency checks. The issue is fixed in versions 4.2.2 and 4.1.7.
CVE-2026-50632 is a high-severity vulnerability in Apache CXF related to improper input validation and deserialization of untrusted JMS configuration data. It stems from an incomplete fix of a previous issue (CVE-2026-44417) and allows untrusted users who can configure JMS to achieve arbitrary code execution, potentially leading to full system compromise. The vulnerability affects multiple Apache CXF versions prior to fixed releases 4.2.2, 4.1.7, and 3.6.12. Mitigation involves restricting JMS configuration access to trusted administrators only. Official patches are available in the specified fixed versions.
An authentication bypass vulnerability exists in the OAuth2 TokenIntrospectionService of Apache CXF due to a missing 'throw' keyword in the security context check. This flaw allows unauthenticated network attackers to access the introspection endpoint if authentication is not properly enabled. The issue is fixed in Apache CXF versions 4.2.2 and 4.1.7.
A CRLF injection vulnerability in Apache CXF OAuth2 AuthorizationUtils allows injection of arbitrary HTTP headers or response splitting via the 'realm' parameter in the WWW-Authenticate header. Versions prior to 4.2.2 and before 4.1.7 are affected. The issue is fixed in versions 4.2.2 and 4.1.7.
A race condition vulnerability in Apache CXF OAuth2 AbstractOAuthDataProvider allows concurrent use of the same refresh token to generate multiple valid access tokens when 'recycleRefreshTokens' is set to false. This bypasses the intended single-use refresh token semantics. The issue is fixed in versions 4.2.2 and 4.1.7.
CVE-2026-49875 is an information disclosure vulnerability in Apache CXF caused by improper XML parser configuration that allows out-of-band external entity resolution. This flaw affects the EndpointReferenceUtils and W3CMultiSchemaFactory classes, enabling remote attackers to disclose sensitive information without user interaction. The vulnerability is addressed in Apache CXF versions 4.2.2, 4.1.7, and 3.6.12. Red Hat products bundling Apache CXF are also affected, but currently no effective mitigation or fix meeting Red Hat's criteria is available for those products.
Apache CXF versions prior to 4.1.7, 4.2.2, and 3.6.12 allow an unlimited number of attachment headers during message deserialization. This lack of restriction can lead to uncontrolled resource consumption, potentially causing denial of service (DoS) conditions. The issue is addressed by imposing a default maximum of 500 attachments per message in the fixed versions.
A vulnerability in the Netty HAProxy PROXY protocol v2 codec causes a memory leak when processing nested PP2_TYPE_SSL TLVs at depth two or greater. This leak occurs during normal parsing without exceptions, leading to permanent retention of the underlying cumulation buffer. The issue can result in denial of service due to resource exhaustion. Fixed versions are 4.2.15.Final and 4.1.135.Final.
A vulnerability in netty-codec-http2's DelegatingDecompressorFrameListener can cause a ByteBuf reference-count leak leading to memory exhaustion. A remote attacker can send specially crafted HTTP/2 frames that trigger a resource leak, potentially causing an Out Of Memory Error (OOME) and resulting in a denial of service by crashing the Java Virtual Machine (JVM).