Skip to content

Fix NPE in SCIM PATCH when request body contains "schemas": null - #51173

Open
sergioperezcheco wants to merge 1 commit into
keycloak:mainfrom
sergioperezcheco:fix/scim-patch-null-schemas-npe
Open

Fix NPE in SCIM PATCH when request body contains "schemas": null#51173
sergioperezcheco wants to merge 1 commit into
keycloak:mainfrom
sergioperezcheco:fix/scim-patch-null-schemas-npe

Conversation

@sergioperezcheco

Copy link
Copy Markdown

Sending a SCIM PATCH request whose body explicitly sets "schemas": null causes a NullPointerException and an HTTP 500 instead of the expected 400. Jackson deserializes the field as null, overwriting the default Set.of(SCHEMA) initializer in PatchRequest, and ScimResourceTypeResource.patch() then calls request.getSchemas().contains(Scim.PATCH_OP_CORE_SCHEMA) on the null set.

This adds a null check so a missing schemas set is treated identically to a schemas set lacking the PATCH op schema — both return invalidSyntax (400). Added a test that issues a PATCH with a null schemas set and asserts the 400 response.

Fixes #51156

@sergioperezcheco
sergioperezcheco requested a review from a team as a code owner July 27, 2026 00:21
Copilot AI review requested due to automatic review settings July 27, 2026 00:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Prevents SCIM PATCH requests with null schemas from causing HTTP 500 errors.

Changes:

  • Adds null-safe PATCH schema validation.
  • Adds regression coverage for null schemas.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
ScimResourceTypeResource.java Returns invalid-syntax HTTP 400 for null schemas.
UserTest.java Adds regression test, but serialization omits the null field.

PatchRequest request = PatchRequest.create()
.add("active", "false")
.build();
request.setSchemas(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 keycloak#51156

Signed-off-by: sergioperezcheco <checo520@outlook.com>
Copilot AI review requested due to automatic review settings July 28, 2026 00:38
@sergioperezcheco
sergioperezcheco force-pushed the fix/scim-patch-null-schemas-npe branch from 90ccc43 to bb7a5f5 Compare July 28, 2026 00:38
@sergioperezcheco

Copy link
Copy Markdown
Author

Good catch, thanks. You're right — PatchRequest has a class-level @JsonInclude(NON_NULL), so setSchemas(null) gets dropped during serialization and the server never sees the null. I've rewritten the test to send a raw PATCH with an explicit {"schemas": null, ...} JSON body over HTTP, so the deserialization path on the server side is actually exercised.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

Comment on lines +630 to +637
org.apache.http.client.methods.HttpPost tokenRequest = new org.apache.http.client.methods.HttpPost(tokenUrl);
tokenRequest.setHeader(HttpHeaders.CONTENT_TYPE, org.apache.http.entity.ContentType.APPLICATION_FORM_URLENCODED.getMimeType());
tokenRequest.setEntity(new StringEntity(tokenBody, org.apache.http.entity.ContentType.APPLICATION_FORM_URLENCODED));

String accessToken;
org.apache.http.HttpResponse tokenResponse = httpClient.execute(tokenRequest);
AccessTokenResponse atr = org.keycloak.util.JsonSerialization.readValue(tokenResponse.getEntity().getContent(), AccessTokenResponse.class);
accessToken = atr.getToken();
Comment on lines +627 to +629
String tokenBody = OAuth2Constants.GRANT_TYPE + "=" + OAuth2Constants.CLIENT_CREDENTIALS
+ "&" + OAuth2Constants.CLIENT_ID + "=scim-client"
+ "&" + OAuth2Constants.CLIENT_SECRET + "=secret";
Comment on lines +647 to +648
org.apache.http.HttpResponse response = httpClient.execute(patch);
assertEquals(400, response.getStatusLine().getStatusCode());
Comment on lines +227 to 230
Set<String> schemas = request.getSchemas();
if (schemas == null || !schemas.contains(Scim.PATCH_OP_CORE_SCHEMA)) {
return invalidSyntax("No PATCH op schema provided in request");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SCIM PATCH NPE when request body contains "schemas": null

2 participants