From 0082a8c10caf0561a96f7e2e892cf5c6120a2e8d Mon Sep 17 00:00:00 2001 From: sergioperezcheco Date: Mon, 27 Jul 2026 08:21:21 +0800 Subject: [PATCH] Fix NPE in SCIM PATCH when request body contains "schemas": null ScimResourceTypeResource.patch() calls request.getSchemas().contains() without a null check. When a client sends a PATCH request body with "schemas": null, Jackson overwrites the default Set.of(SCHEMA) initializer in PatchRequest with null, and the .contains() call throws a NullPointerException resulting in HTTP 500 instead of a proper 400 Bad Request. Add a null check so a missing schemas set is treated the same as a schemas set without the PATCH op schema, returning invalidSyntax (400). Adds a test that sends a PATCH with a null schemas set and asserts the 400 response. Fixes #51156 Signed-off-by: sergioperezcheco --- .../keycloak/scim/services/ScimResourceTypeResource.java | 4 +++- .../test/java/org/keycloak/tests/scim/tck/UserTest.java | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/scim/services/src/main/java/org/keycloak/scim/services/ScimResourceTypeResource.java b/scim/services/src/main/java/org/keycloak/scim/services/ScimResourceTypeResource.java index 1a68a2037625..f7480896f44a 100644 --- a/scim/services/src/main/java/org/keycloak/scim/services/ScimResourceTypeResource.java +++ b/scim/services/src/main/java/org/keycloak/scim/services/ScimResourceTypeResource.java @@ -3,6 +3,7 @@ import java.io.InputStream; import java.time.Instant; import java.util.List; +import java.util.Set; import java.util.function.BiFunction; import java.util.stream.Stream; @@ -223,7 +224,8 @@ public Response patch(@PathParam("id") String id, PatchRequest request) { return resourceNotFound(id); } - if (!request.getSchemas().contains(Scim.PATCH_OP_CORE_SCHEMA)) { + Set schemas = request.getSchemas(); + if (schemas == null || !schemas.contains(Scim.PATCH_OP_CORE_SCHEMA)) { return invalidSyntax("No PATCH op schema provided in request"); } diff --git a/scim/tests/base/src/test/java/org/keycloak/tests/scim/tck/UserTest.java b/scim/tests/base/src/test/java/org/keycloak/tests/scim/tck/UserTest.java index 418ad760afa9..56ad49ef4af4 100644 --- a/scim/tests/base/src/test/java/org/keycloak/tests/scim/tck/UserTest.java +++ b/scim/tests/base/src/test/java/org/keycloak/tests/scim/tck/UserTest.java @@ -25,6 +25,8 @@ import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.representations.userprofile.config.UPAttribute; import org.keycloak.representations.userprofile.config.UPAttributePermissions; +import org.keycloak.OAuth2Constants; +import org.keycloak.representations.AccessTokenResponse; import org.keycloak.representations.userprofile.config.UPAttributeRequired; import org.keycloak.representations.userprofile.config.UPConfig; import org.keycloak.scim.client.ResourceFilter; @@ -50,6 +52,11 @@ import org.keycloak.testframework.util.ApiUtil; import org.keycloak.userprofile.config.UPConfigUtils; +import org.apache.http.HttpHeaders; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpPatch; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; import com.fasterxml.jackson.annotation.JsonProperty; import org.apache.http.client.HttpClient; import org.apache.http.entity.ContentType;