{
  "variant_id": "kc-cve-2026-11800-oidc-token-exchange-hs256-confusion",
  "created_at": "2026-07-05T16:00:00Z",
  "variant_summary": "Alternate trigger for CVE-2026-11800: JWT algorithm confusion (HS256 with RSA public key DER bytes as HMAC secret) against a hardcoded-public-key OIDC Identity Provider, reached via the OIDC external-internal token exchange (RFC 8693, grant_type=urn:ietf:params:oauth:grant-type:token-exchange, subject_token_type=urn:ietf:params:oauth:token-type:jwt, subject_issuer=<oidc-idp>) instead of the JWT Authorization Grant. This path goes through OIDCIdentityProvider.exchangeExternalImpl -> validateJwt -> verifySignature -> HardcodedPublicKeyLoader and does NOT pass through AbstractBaseJWTValidator.validateSignatureAlgorithm (the fix's Layer 1 algorithm-type gate); it is covered only by Layer 2 (HardcodedPublicKeyLoader HMAC-branch removal). Vulnerable 26.6.3 accepts the forged HS256 subject_token and issues an access token for the impersonated federated user; fixed 26.6.4 rejects with invalid_token. Alternate trigger, not a bypass.",
  "relation": "newer_version_sibling",
  "origin_kind": "pruva_variant",
  "repository": "https://github.com/keycloak/keycloak",
  "submitted_target": {
    "target_kind": "container_image",
    "version": "26.6.3",
    "ref": "quay.io/keycloak/keycloak:26.6.3",
    "display": "quay.io/keycloak/keycloak:26.6.3 (Red Hat Build of Keycloak, vulnerable; image ID sha256:9b0330756022422149aa6502eb2def8cd47c6e1b000c7c65cdb13e7c0133e992)"
  },
  "variant_target": {
    "target_kind": "container_image",
    "commit_sha": "d343c7373dcc7bfeb9dc14de2309836299c81837",
    "version": "26.6.4",
    "ref": "quay.io/keycloak/keycloak:26.6.4",
    "display": "quay.io/keycloak/keycloak:26.6.4 (fixed; image ID sha256:0aae0de7fca85525f727d3354df17896092de8bb26ae4c12d89c77e5df8cbce4). Upstream fix commit d343c7373dcc7bfeb9dc14de2309836299c81837 (PR #50374) is contained in this image; OCI image revision label be9ce7fa2cecc897d47e8922ba9e6b86cee881b0 (keycloak-rel release repo)."
  },
  "same_root_cause_confidence": "high",
  "same_surface_confidence": "medium",
  "claimed_surface": "Keycloak OIDC token endpoint (api_remote)",
  "validated_surface": "api_remote",
  "required_entrypoint_kind": "api_remote",
  "required_entrypoint_detail": "POST /realms/{realm}/protocol/openid-connect/token with grant_type=urn:ietf:params:oauth:grant-type:token-exchange, subject_token_type=urn:ietf:params:oauth:token-type:jwt, subject_issuer=<oidc-idp-alias>, requested_token_type=urn:ietf:params:oauth:token-type:access_token, subject_token=<forged HS256 JWT>, client credentials of a client authorized (v1 FGAP token-exchange permission) to exchange to a hardcoded-public-key OIDC IdP with validateSignature=true. Requires features token-exchange + admin-fine-grained-authz:v1 enabled.",
  "attacker_controlled_input": "Forged HS256 JWT subject_token (alg=HS256 in header; iss=IdP issuer, sub=target federated user subject, typ=Bearer in payload) signed with HMAC-SHA256 using the IdP's RSA public key DER (SubjectPublicKeyInfo) bytes as the HMAC secret, submitted as the subject_token of an external-internal token exchange.",
  "trigger_path": "TokenExchangeGrantType.process -> V1TokenExchangeProvider.tokenExchange -> exchangeExternalToken -> OIDCIdentityProvider.exchangeExternal -> exchangeExternalImpl -> validateJwt -> validateToken(ignoreAudience=true) -> verify -> verifySignature -> PublicKeyStorageManager.getIdentityProviderKeyWrapper -> HardcodedPublicKeyLoader(kid, base64PubKey, HS256) [vulnerable: HMAC branch -> Base64Url.decode -> DER -> SecretKey -> MacSignatureVerifierContext.verify succeeds]. No AbstractBaseJWTValidator.validateSignatureAlgorithm call on this path.",
  "observed_impact_class": "authz_bypass",
  "exploitability_confidence": "high",
  "evidence_scope": "production_path",
  "runtime_manifest_present": true,
  "end_to_end_target_reached": true,
  "inferred": false,
  "claim_block_reason": null,
  "blocking_mitigation": "Fixed version 26.6.4 rejects the forged HS256 subject_token with HTTP 400 invalid_token because HardcodedPublicKeyLoader no longer has the HMAC branch (returns null key for HS256 -> verifySignature fails). This is the fix's Layer 2; Layer 1 (algorithm-type gate) does not run on this path.",
  "file_path": "services/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProvider.java",
  "line_start": 946,
  "line_end": 1005,
  "secondary_anchors": [
    {
      "file_path": "services/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProvider.java",
      "line_start": 701,
      "line_end": 722
    },
    {
      "file_path": "services/src/main/java/org/keycloak/keys/loader/HardcodedPublicKeyLoader.java",
      "line_start": 30,
      "line_end": 70
    },
    {
      "file_path": "services/src/main/java/org/keycloak/keys/loader/PublicKeyStorageManager.java",
      "line_start": 70,
      "line_end": 95
    },
    {
      "file_path": "services/src/main/java/org/keycloak/authentication/authenticators/client/AbstractBaseJWTValidator.java",
      "line_start": 150,
      "line_end": 178
    }
  ],
  "review_scope_paths": [
    "services/src/main/java/org/keycloak/broker/oidc/OIDCIdentityProvider.java",
    "services/src/main/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProvider.java",
    "services/src/main/java/org/keycloak/keys/loader/HardcodedPublicKeyLoader.java",
    "services/src/main/java/org/keycloak/keys/loader/PublicKeyStorageManager.java",
    "services/src/main/java/org/keycloak/keys/loader/OIDCIdentityProviderPublicKeyLoader.java",
    "services/src/main/java/org/keycloak/authentication/authenticators/client/AbstractBaseJWTValidator.java",
    "services/src/main/java/org/keycloak/protocol/oidc/tokenexchange/V1TokenExchangeProvider.java",
    "services/src/main/java/org/keycloak/protocol/oidc/tokenexchange/AbstractTokenExchangeProvider.java"
  ],
  "artifact_refs": {
    "variant_manifest": "bundle/vuln_variant/variant_manifest.json",
    "validation_verdict": "bundle/vuln_variant/validation_verdict.json",
    "runtime_manifest": "bundle/vuln_variant/runtime_manifest.json",
    "repro_log": "bundle/logs/vuln_variant/exploit_run.log",
    "root_cause_equivalence": "bundle/vuln_variant/root_cause_equivalence.json",
    "reproducer": [
      "bundle/vuln_variant/reproduction_steps.sh",
      "bundle/vuln_variant/exploit_variant.py"
    ]
  }
}
