Repository: keycloak/keycloak (2025-06-24T12:36:40Z)

Issue:
Map iterators usage optimization. SAST
### Description

This method accesses the value of a Map entry, using a key that was retrieved from a `keySet` iterator. It is more efficient to use an iterator on the `entrySet` of the map, to avoid the `Map.get(key)` lookup.

### Discussion

_No response_

### Motivation

Perfomance optimization

### Details

Consider using `entrySet` instead of `keySet` at the following cases:
1. https://github.com/keycloak/keycloak/blob/309957033eb0da99860a8da9dad3643cc76f136a/saml-core/src/main/java/org/keycloak/saml/BaseSAML2BindingBuilder.java#L388-L390

2. https://github.com/keycloak/keycloak/blob/309957033eb0da99860a8da9dad3643cc76f136a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/StatementUtil.java#L83-L134

3. https://github.com/keycloak/keycloak/blob/309957033eb0da99860a8da9dad3643cc76f136a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/BaseWriter.java#L161-L176

4. https://github.com/keycloak/keycloak/blob/309957033eb0da99860a8da9dad3643cc76f136a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/NamespaceContext.java#L63-L71

5. https://github.com/keycloak/keycloak/blob/309957033eb0da99860a8da9dad3643cc76f136a/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java#L1542-L1557

6. https://github.com/keycloak/keycloak/blob/309957033eb0da99860a8da9dad3643cc76f136a/server-spi-private/src/main/java/org/keycloak/userprofile/DefaultAttributes.java#L413-L427

---

Found by [Linux Verification Center](https://portal.linuxtesting.ru/) with SVACE

---

More similar cases:

https://github.com/keycloak/keycloak/issues/40064#issuecomment-3004357840 - Thanks to @akbar1214 for his report


Discussion:
@Anchels, there are a few more places where `Iteration over keySet can be improved`. Should I address those as well, if you are fine adding those to the above list? I can provide the list of code fragments where it can be improved.
@akbar1214, that would be great!
- https://github.com/keycloak/keycloak/blob/6cc8d653f3984e7fc1d33ec0968531d3b4afd424/testsuite/utils/src/main/java/org/keycloak/testsuite/util/cli/AbstractSessionCacheCommand.java#L230-L237
- https://github.com/keycloak/keycloak/blob/01f5a8c1c3e97944f8919c11338b1cebed9056ee/tests/utils/src/main/java/org/keycloak/tests/utils/Assert.java#L171-L174
- https://github.com/keycloak/keycloak/blob/479e6bc86b5110945297074d94d10ddc709d1aa1/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/Assert.java#L170-L173
- https://github.com/keycloak/keycloak/blob/08bac045be0f90019a91daa5bb79000e04751c81/services/src/main/java/org/keycloak/protocol/oidc/grants/ciba/CibaGrantType.java#L216-L218
- https://github.com/keycloak/keycloak/blob/9f5f8e017ea61ce9cec5ba95167d3dfd06c222fa/services/src/main/java/org/keycloak/partialimport/ClientRolesPartialImport.java#L117-L138
- https://github.com/keycloak/keycloak/blob/808738220f1eebb6ab474c255e68df272fcba211/services/src/main/java/org/keycloak/services/managers/CodeGenerateUtil.java#L62-L66
- https://github.com/keycloak/keycloak/blob/025b2ba4421547cb65c8c727957fdba075c7f5df/model/storage-private/src/main/java/org/keycloak/storage/datastore/DefaultMigrationManager.java#L232-L236
- https://github.com/keycloak/keycloak/blob/34ad2806658309de42db99e89905e39699bdd1ad/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/exportimport/ExportImportUtil.java#L528-L531
- https://github.com/keycloak/keycloak/blob/34ad2806658309de42db99e89905e39699bdd1ad/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/exportimport/ExportImportUtil.java#L541-L544
- https://github.com/keycloak/keycloak/blob/535bba57928c1313d964b15d7578bf22f02114b3/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/FailableHardcodedStorageProvider.java#L196-L200
- https://github.com/keycloak/keycloak/blob/e1fdd1dab69f8c1fe6a4119f9f2e5babd50a92e5/tests/base/src/test/java/org/keycloak/tests/admin/client/InstallationTest.java#L399-L401
- https://github.com/keycloak/keycloak/blob/ab7edb0d01b1636c07125cc638cbfba491dd96af/common/src/main/java/org/keycloak/common/Profile.java#L470-L478
- https://github.com/keycloak/keycloak/blob/0be34d64e71cd80f6a72382b63ec454adaac5dc4/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/config/RealmConfigData.java#L182-L189
- https://github.com/keycloak/keycloak/blob/f42185b3199e6f4027bd9f78debe3c5921af2579/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/registration/cli/ReflectionUtil.java#L373-L379
- https://github.com/keycloak/keycloak/blob/9f5f8e017ea61ce9cec5ba95167d3dfd06c222fa/services/src/main/java/org/keycloak/partialimport/RolesPartialImport.java#L140-L144
- https://github.com/keycloak/keycloak/blob/9f5f8e017ea61ce9cec5ba95167d3dfd06c222fa/services/src/main/java/org/keycloak/partialimport/RolesPartialImport.java#L165-L171
- https://github.com/keycloak/keycloak/blob/9f5f8e017ea61ce9cec5ba95167d3dfd06c222fa/services/src/main/java/org/keycloak/partialimport/RolesPartialImport.java#L194-L198
- https://github.com/keycloak/keycloak/blob/9f5f8e017ea61ce9cec5ba95167d3dfd06c222fa/services/src/main/java/org/keycloak/partialimport/RolesPartialImport.java#L204-L209
- https://github.com/keycloak/keycloak/blob/9f5f8e017ea61ce9cec5ba95167d3dfd06c222fa/services/src/main/java/org/keycloak/partialimport/RolesPartialImport.java#L241-L249
- https://github.com/keycloak/keycloak/blob/c1c147cb17897aee537ec2781eef819cd684e074/common/src/test/java/org/keycloak/common/util/StringPropertyReplacerTest.java#L72-L78
- https://github.com/keycloak/keycloak/blob/f61937f3d99f03941b69eb33dd818194bc45d34d/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/Timer.java#L106-L112
- https://github.com/keycloak/keycloak/blob/4ad4a8d37b719353eb200ef4085cd7641d5ccd89/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java#L214-L219
- https://github.com/keycloak/keycloak/blob/08bac045be0f90019a91daa5bb79000e04751c81/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenIntrospectionEndpoint.java#L153-L157
- https://github.com/keycloak/keycloak/blob/08bac045be0f90019a91daa5bb79000e04751c81/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenRevocationEndpoint.java#L249-L253
- https://github.com/keycloak/keycloak/blob/aceb123242c60d608e5247d73169143b753d6779/services/src/test/java/org/keycloak/vault/VaultTranscriberTest.java#L77-L99
- https://github.com/keycloak/keycloak/blob/aceb123242c60d608e5247d73169143b753d6779/services/src/test/java/org/keycloak/vault/VaultTranscriberTest.java#L166-L188
- https://github.com/keycloak/keycloak/blob/aceb123242c60d608e5247d73169143b753d6779/services/src/test/java/org/keycloak/vault/VaultTranscriberTest.java#L252-L264



Patch:
diff --git a/common/src/main/java/org/keycloak/common/Profile.java b/common/src/main/java/org/keycloak/common/Profile.java
index 1c356f17b437..6fcdcfcc9bfb 100755
--- a/common/src/main/java/org/keycloak/common/Profile.java
+++ b/common/src/main/java/org/keycloak/common/Profile.java
@@ -467,8 +467,9 @@ public enum ProfileName {
     }
 
     private static void verifyConfig(Map<Feature, Boolean> features) {
-        for (Feature f : features.keySet()) {
-            if (features.get(f) && f.getDependencies() != null) {
+        for (Map.Entry<Feature, Boolean> entry : features.entrySet()) {
+            Feature f = entry.getKey();
+            if (entry.getValue() && f.getDependencies() != null) {
                 for (Feature d : f.getDependencies()) {
                     if (!features.get(d)) {
                         throw new ProfileException("Feature " + f.getKey() + " depends on disabled feature " + d.getKey());
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/config/RealmConfigData.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/config/RealmConfigData.java
index 6e1a73d0183d..fdffa42e56d0 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/config/RealmConfigData.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/config/RealmConfigData.java
@@ -179,8 +179,9 @@ private void mergeClients(RealmConfigData source) {
             if (clients == null) {
                 clients = source.clients;
             } else {
-                for (String key: source.clients.keySet()) {
-                    String val = source.clients.get(key);
+                for (var entry : source.clients.entrySet()) {
+                    String key = entry.getKey();
+                    String val = entry.getValue();
                     if (!"".equals(val)) {
                         clients.put(key, val);
                     } else {
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/registration/cli/ReflectionUtil.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/registration/cli/ReflectionUtil.java
index 1e884884d0ff..0f959e0a9062 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/registration/cli/ReflectionUtil.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/registration/cli/ReflectionUtil.java
@@ -370,8 +370,7 @@ public static <T> void merge(T source, T dest) {
         // use setter on dest, and getter on source to copy value over
         Map<String, Field> fieldMap = getAttrFieldsForType(source.getClass());
         try {
-            for (String attrName : fieldMap.keySet()) {
-                Field field = fieldMap.get(attrName);
+            for (Field field : fieldMap.values()) {
                 Object localValue = field.get(source);
                 if (localValue != null) {
                     field.set(dest, localValue);
diff --git a/model/storage-private/src/main/java/org/keycloak/storage/datastore/DefaultMigrationManager.java b/model/storage-private/src/main/java/org/keycloak/storage/datastore/DefaultMigrationManager.java
index c2df3353f4d9..46d40b7ae7e6 100644
--- a/model/storage-private/src/main/java/org/keycloak/storage/datastore/DefaultMigrationManager.java
+++ b/model/storage-private/src/main/java/org/keycloak/storage/datastore/DefaultMigrationManager.java
@@ -229,9 +229,9 @@ public void migrate(RealmModel realm, RealmRepresentation rep, boolean skipUserD
 
     public static ModelVersion convertRHSSOVersionToKeycloakVersion(String version) {
         // look for the keycloakVersion pattern to identify it as RH SSO
-        for (Pattern pattern : PATTERN_MATCHER.keySet()) {
-            if (pattern.matcher(version).find()) {
-                return PATTERN_MATCHER.get(pattern);
+        for (var entry : PATTERN_MATCHER.entrySet()) {
+            if (entry.getKey().matcher(version).find()) {
+                return entry.getValue();
             }
         }
         // chceck if the version is in format for CD releases, e.g.: "keycloakVersion": "6"
diff --git a/saml-core/src/main/java/org/keycloak/saml/BaseSAML2BindingBuilder.java b/saml-core/src/main/java/org/keycloak/saml/BaseSAML2BindingBuilder.java
index 516ef4f79c1c..48a4db3801be 100755
--- a/saml-core/src/main/java/org/keycloak/saml/BaseSAML2BindingBuilder.java
+++ b/saml-core/src/main/java/org/keycloak/saml/BaseSAML2BindingBuilder.java
@@ -385,8 +385,8 @@ public String buildHtmlForm(String actionUrl, Map<String, String> inputTypes) {
 
         builder.append("<p>Redirecting, please wait.</p>");
 
-        for (String key: inputTypes.keySet()) {
-            builder.append("<INPUT TYPE=\"HIDDEN\" NAME=\"").append(key).append("\"").append(" VALUE=\"").append(escapeAttribute(inputTypes.get(key))).append("\"/>");
+        for (var entry : inputTypes.entrySet()) {
+            builder.append("<INPUT TYPE=\"HIDDEN\" NAME=\"").append(entry.getKey()).append("\"").append(" VALUE=\"").append(escapeAttribute(entry.getValue())).append("\"/>");
         }
 
         builder.append("<NOSCRIPT>")
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/StatementUtil.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/StatementUtil.java
index deb9bdbe9970..32f9cd5c3f6f 100755
--- a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/StatementUtil.java
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/util/StatementUtil.java
@@ -85,8 +85,8 @@ public static AttributeStatementType createAttributeStatement(Map<String, Object
 
         int i = 0;
 
-        Set<String> keys = attributes.keySet();
-        for (String key : keys) {
+        for (var entry : attributes.entrySet()) {
+            String key = entry.getKey();
             if (i == 0) {
                 // Deal with the X500 Profile of SAML2
                 attrStatement = new AttributeStatementType();
@@ -95,14 +95,14 @@ public static AttributeStatementType createAttributeStatement(Map<String, Object
 
             // if the attribute contains roles, add each role as an attribute.
             if (AttributeConstants.ROLES.equalsIgnoreCase(key)) {
-                Object value = attributes.get(key);
+                Object value = entry.getValue();
                 if (value instanceof Collection<?>) {
                     Collection<?> roles = (Collection<?>) value;
                     attrStatement = createAttributeStatement(new ArrayList(roles));
                 }
             } else {
                 AttributeType att;
-                Object value = attributes.get(key);
+                Object value = entry.getValue();
 
                 String uri = X500SAMLProfileConstants.getOID(key);
                 if (StringUtil.isNotNull(uri)) {
@@ -233,4 +233,4 @@ private static AttributeType getX500Attribute(String name) {
         att.setNameFormat(JBossSAMLURIConstants.ATTRIBUTE_FORMAT_URI.get());
         return att;
     }
-}
\ No newline at end of file
+}
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/BaseWriter.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/BaseWriter.java
index c5ca05eceeaf..8f39dafe9632 100755
--- a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/BaseWriter.java
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/BaseWriter.java
@@ -162,15 +162,14 @@ public void writeAttributeTypeWithoutRootTag(AttributeType attributeType) throws
         if (otherAttribs != null) {
             List<String> nameSpacesDealt = new ArrayList<>();
 
-            Iterator<QName> keySet = otherAttribs.keySet().iterator();
-            while (keySet != null && keySet.hasNext()) {
-                QName qname = keySet.next();
+            for (var entry : otherAttribs.entrySet()) {
+                QName qname = entry.getKey();
                 String ns = qname.getNamespaceURI();
                 if (!nameSpacesDealt.contains(ns)) {
                     StaxUtil.writeNameSpace(writer, qname.getPrefix(), ns);
                     nameSpacesDealt.add(ns);
                 }
-                String attribValue = otherAttribs.get(qname);
+                String attribValue = entry.getValue();
                 StaxUtil.writeAttribute(writer, qname, attribValue);
             }
         }
@@ -392,4 +391,4 @@ private void write(SubjectConfirmationDataType subjectConfirmationData) throws P
     private void write(BaseIDAbstractType baseId) throws ProcessingException {
         throw logger.notImplementedYet("Method not implemented.");
     }
-}
\ No newline at end of file
+}
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/NamespaceContext.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/NamespaceContext.java
index a5842866a6c6..807ac8e356de 100755
--- a/saml-core/src/main/java/org/keycloak/saml/processing/core/util/NamespaceContext.java
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/util/NamespaceContext.java
@@ -61,10 +61,10 @@ public String getNamespaceURI(String prefix) {
      * @see javax.xml.namespace.NamespaceContext#getPrefix(java.lang.String)
      */
     public String getPrefix(String namespaceURI) {
-        for (String key : nsMap.keySet()) {
-            String value = nsMap.get(key);
+        for (var entry : nsMap.entrySet()) {
+            String value = entry.getValue();
             if (value.equals(namespaceURI)) {
-                return key;
+                return entry.getKey();
             }
         }
         return null;
diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index 0fb03847329d..4968590b242e 100755
--- a/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -1539,9 +1539,8 @@ public static Resource toModel(ResourceRepresentation resource, ResourceServer r
             Map<String, List<String>> attributes = resource.getAttributes();
 
             if (attributes != null) {
-                Set<String> existingAttrNames = existing.getAttributes().keySet();
 
-                for (String name : existingAttrNames) {
+                for (String name : existing.getAttributes().keySet()) {
                     if (attributes.containsKey(name)) {
                         existing.setAttribute(name, attributes.get(name));
                         attributes.remove(name);
@@ -1550,8 +1549,8 @@ public static Resource toModel(ResourceRepresentation resource, ResourceServer r
                     }
                 }
 
-                for (String name : attributes.keySet()) {
-                    existing.setAttribute(name, attributes.get(name));
+                for (var entry : attributes.entrySet()) {
+                    existing.setAttribute(entry.getKey(), entry.getValue());
                 }
             }
 
diff --git a/server-spi-private/src/main/java/org/keycloak/userprofile/DefaultAttributes.java b/server-spi-private/src/main/java/org/keycloak/userprofile/DefaultAttributes.java
index f96271155e42..d54be7b2e6e5 100644
--- a/server-spi-private/src/main/java/org/keycloak/userprofile/DefaultAttributes.java
+++ b/server-spi-private/src/main/java/org/keycloak/userprofile/DefaultAttributes.java
@@ -411,13 +411,14 @@ private Map<String, List<String>> normalizeAttributes(Map<String, ?> attributes)
         }
 
         // the profile should always hold all attributes defined in the config
-        for (String attributeName : metadataByAttribute.keySet()) {
+        for (var entry : metadataByAttribute.entrySet()) {
+            String attributeName = entry.getKey();
             if (!isSupportedAttribute(attributeName) || newAttributes.containsKey(attributeName)) {
                 continue;
             }
 
             List<String> values = EMPTY_VALUE;
-            AttributeMetadata metadata = metadataByAttribute.get(attributeName);
+            AttributeMetadata metadata = entry.getValue();
 
             if (user != null && isIncludeAttributeIfNotProvided(metadata)) {
                 values = normalizeAttributeValues(attributeName, user.getAttributes().getOrDefault(attributeName, EMPTY_VALUE));
diff --git a/services/src/main/java/org/keycloak/partialimport/ClientRolesPartialImport.java b/services/src/main/java/org/keycloak/partialimport/ClientRolesPartialImport.java
index b9b0ced5b3a0..76334762dbb7 100644
--- a/services/src/main/java/org/keycloak/partialimport/ClientRolesPartialImport.java
+++ b/services/src/main/java/org/keycloak/partialimport/ClientRolesPartialImport.java
@@ -114,14 +114,15 @@ public void prepare(PartialImportRepresentation partialImportRep, RealmModel rea
         Map<String, List<RoleRepresentation>> repList = getRepList(partialImportRep);
         if (repList == null || repList.isEmpty()) return;
 
-        for (String clientId : repList.keySet()) {
+        for (var entry : repList.entrySet()) {
+            String clientId = entry.getKey();
             if (!clientExists(partialImportRep, realm, clientId)) {
                 throw noClientFound(clientId);
             }
 
             toOverwrite.put(clientId, new HashSet<>());
             toSkip.put(clientId, new HashSet<>());
-            for (RoleRepresentation roleRep : repList.get(clientId)) {
+            for (RoleRepresentation roleRep : entry.getValue()) {
                 if (exists(realm, session, clientId, roleRep)) {
                     switch (partialImportRep.getPolicy()) {
                         case SKIP:
diff --git a/services/src/main/java/org/keycloak/partialimport/RolesPartialImport.java b/services/src/main/java/org/keycloak/partialimport/RolesPartialImport.java
index bbd127feb5f2..b56e2c0338c2 100644
--- a/services/src/main/java/org/keycloak/partialimport/RolesPartialImport.java
+++ b/services/src/main/java/org/keycloak/partialimport/RolesPartialImport.java
@@ -137,8 +137,8 @@ private void setUniqueIds(List<RoleRepresentation> realmRoles) {
     }
 
     private void setUniqueIds(Map<String, List<RoleRepresentation>> clientRoles) {
-        for (String clientId : clientRoles.keySet()) {
-            for (RoleRepresentation clientRole : clientRoles.get(clientId)) {
+        for (List<RoleRepresentation> roleRepresentations : clientRoles.values()) {
+            for (RoleRepresentation clientRole : roleRepresentations) {
                 clientRole.setId(KeycloakModelUtils.generateId());
             }
         }
@@ -162,8 +162,9 @@ private void removeClientRoleSkips(PartialImportResults results,
                                        RealmModel realm) {
         if (isEmpty(clientRolesToSkip)) return;
 
-        for (String clientId : clientRolesToSkip.keySet()) {
-            for (RoleRepresentation roleRep : clientRolesToSkip.get(clientId)) {
+        for (var entry : clientRolesToSkip.entrySet()) {
+            String clientId = entry.getKey();
+            for (RoleRepresentation roleRep : entry.getValue()) {
                 rep.getRoles().getClient().get(clientId).remove(roleRep);
                 String modelId = clientRolesPI.getModelId(realm, clientId);
                 results.addResult(clientRolesPI.skipped(clientId, modelId, roleRep));
@@ -191,9 +192,9 @@ private void addResultsForOverwrittenRealmRoles(PartialImportResults results, Re
     private void deleteClientRoleOverwrites(RealmModel realm) {
         if (isEmpty(clientRolesToOverwrite)) return;
 
-        for (String clientId : clientRolesToOverwrite.keySet()) {
-            for (RoleRepresentation roleRep : clientRolesToOverwrite.get(clientId)) {
-                clientRolesPI.deleteRole(realm, clientId, roleRep);
+        for (var entry : clientRolesToOverwrite.entrySet()) {
+            for (RoleRepresentation roleRep : entry.getValue()) {
+                clientRolesPI.deleteRole(realm, entry.getKey(), roleRep);
             }
         }
     }
@@ -201,8 +202,9 @@ private void deleteClientRoleOverwrites(RealmModel realm) {
     private void addResultsForOverwrittenClientRoles(PartialImportResults results, RealmModel realm) {
         if (isEmpty(clientRolesToOverwrite)) return;
 
-        for (String clientId : clientRolesToOverwrite.keySet()) {
-            for (RoleRepresentation roleRep : clientRolesToOverwrite.get(clientId)) {
+        for (var entry : clientRolesToOverwrite.entrySet()) {
+            String clientId = entry.getKey();
+            for (RoleRepresentation roleRep : entry.getValue()) {
                 String modelId = clientRolesPI.getModelId(realm, clientId);
                 results.addResult(clientRolesPI.overwritten(clientId, modelId, roleRep));
             }
@@ -238,8 +240,9 @@ private void clientRoleAdds(PartialImportResults results,
         if (!rep.hasClientRoles()) return;
 
         Map<String, List<RoleRepresentation>> repList = clientRolesPI.getRepList(rep);
-        for (String clientId : repList.keySet()) {
-            for (RoleRepresentation roleRep : repList.get(clientId)) {
+        for (var entry : repList.entrySet()) {
+            String clientId = entry.getKey();
+            for (RoleRepresentation roleRep : entry.getValue()) {
                 if (clientRolesToOverwrite.get(clientId).contains(roleRep)) continue;
                 if (clientRolesToSkip.get(clientId).contains(roleRep)) continue;
 
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java
index f8a0ac6e5c44..897dc7c4af9f 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenEndpoint.java
@@ -211,8 +211,8 @@ private CorsErrorResponseException newUnsupportedGrantTypeException() {
     }
 
     private void checkParameterDuplicated() {
-        for (String key : formParams.keySet()) {
-            if (formParams.get(key).size() != 1 && !grant.getSupportedMultivaluedRequestParameters().contains(key)) {
+        for (var entry : formParams.entrySet()) {
+            if (entry.getValue().size() != 1 && !grant.getSupportedMultivaluedRequestParameters().contains(entry.getKey())) {
                 throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_REQUEST, "duplicated parameter",
                         Response.Status.BAD_REQUEST);
             }
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenIntrospectionEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenIntrospectionEndpoint.java
index 908381a06cff..9c4e13b7c349 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenIntrospectionEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenIntrospectionEndpoint.java
@@ -40,6 +40,8 @@
 import jakarta.ws.rs.core.Response;
 import jakarta.ws.rs.core.Response.Status;
 
+import java.util.List;
+
 /**
  * A token introspection endpoint based on RFC-7662.
  *
@@ -150,8 +152,8 @@ private void checkRealm() {
 
 
     private void checkParameterDuplicated(MultivaluedMap<String, String> formParams) {
-        for (String key : formParams.keySet()) {
-            if (formParams.get(key).size() != 1) {
+        for (List<String> strings : formParams.values()) {
+            if (strings.size() != 1) {
                 throw throwErrorResponseException(Errors.INVALID_REQUEST, "duplicated parameter", Status.BAD_REQUEST);
             }
         }
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenRevocationEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenRevocationEndpoint.java
index 79438475a896..8f7cbf8e3253 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenRevocationEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenRevocationEndpoint.java
@@ -246,8 +246,8 @@ private void checkUser() {
     }
 
     private void checkParameterDuplicated(MultivaluedMap<String, String> formParams) {
-        for (String key : formParams.keySet()) {
-            if (formParams.get(key).size() != 1) {
+        for (List<String> strings : formParams.values()) {
+            if (strings.size() != 1) {
                 throw new CorsErrorResponseException(cors, Errors.INVALID_REQUEST, "duplicated parameter", Response.Status.BAD_REQUEST);
             }
         }
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/grants/ciba/CibaGrantType.java b/services/src/main/java/org/keycloak/protocol/oidc/grants/ciba/CibaGrantType.java
index b8537ec2f982..680250361f91 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/grants/ciba/CibaGrantType.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/grants/ciba/CibaGrantType.java
@@ -213,8 +213,8 @@ private UserSessionModel createUserSession(CIBAAuthenticationRequest request, Ma
         authSession.setClientNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(session.getContext().getUri().getBaseUri(), realm.getName()));
         authSession.setClientNote(OIDCLoginProtocol.SCOPE_PARAM, request.getScope());
         if (additionalParams != null) {
-            for (String paramName : additionalParams.keySet()) {
-                authSession.setClientNote(ADDITIONAL_CALLBACK_PARAMS_PREFIX + paramName, additionalParams.get(paramName));
+            for (var entry : additionalParams.entrySet()) {
+                authSession.setClientNote(ADDITIONAL_CALLBACK_PARAMS_PREFIX + entry.getKey(), entry.getValue());
             }
         }
         if (request.getOtherClaims() != null) {
diff --git a/services/src/main/java/org/keycloak/services/managers/CodeGenerateUtil.java b/services/src/main/java/org/keycloak/services/managers/CodeGenerateUtil.java
index 776c336a0c35..ea9e3320b142 100644
--- a/services/src/main/java/org/keycloak/services/managers/CodeGenerateUtil.java
+++ b/services/src/main/java/org/keycloak/services/managers/CodeGenerateUtil.java
@@ -59,9 +59,9 @@ class CodeGenerateUtil {
 
 
     static <CS extends CommonClientSessionModel> ClientSessionParser<CS> getParser(Class<CS> clientSessionClass) {
-        for (Class<?> c : PARSERS.keySet()) {
-            if (c.isAssignableFrom(clientSessionClass)) {
-                return PARSERS.get(c).get();
+        for (var entry : PARSERS.entrySet()) {
+            if (entry.getKey().isAssignableFrom(clientSessionClass)) {
+                return entry.getValue().get();
             }
         }
         return null;


Test patch:
diff --git a/common/src/test/java/org/keycloak/common/util/StringPropertyReplacerTest.java b/common/src/test/java/org/keycloak/common/util/StringPropertyReplacerTest.java
index f2854766e872..37c7eac87380 100644
--- a/common/src/test/java/org/keycloak/common/util/StringPropertyReplacerTest.java
+++ b/common/src/test/java/org/keycloak/common/util/StringPropertyReplacerTest.java
@@ -69,10 +69,10 @@ public void testStackOverflow() {
     public void testEnvironmentVariables() throws NoSuchAlgorithmException {
         Map<String, String> env = System.getenv();
 
-        for (String key : env.keySet()) {
-            String value = env.get(key);
+        for (Map.Entry<String, String> entry : env.entrySet()) {
+            String value = entry.getValue();
             if ( !(value == null || "".equals(value)) ) {
-                Assert.assertEquals("foo-" + value, replaceProperties("foo-${env." + key + "}"));
+                Assert.assertEquals("foo-" + value, replaceProperties("foo-${env." + entry.getKey() + "}"));
                 break;
             }
         }
diff --git a/services/src/test/java/org/keycloak/vault/VaultTranscriberTest.java b/services/src/test/java/org/keycloak/vault/VaultTranscriberTest.java
index 8fab2de9684a..586b8b250087 100644
--- a/services/src/test/java/org/keycloak/vault/VaultTranscriberTest.java
+++ b/services/src/test/java/org/keycloak/vault/VaultTranscriberTest.java
@@ -74,9 +74,9 @@ public void testGetRawSecretUsingValidExpressions() {
 
         // attempt to obtain a secret using a proper vault expressions. The key may or may not exist in the vault, so we
         // check both cases using the returned optional and comparing against the expected secret.
-        for (String key : validExpressions.keySet()) {
-            String expectedSecret = validExpressions.get(key);
-            try (VaultRawSecret secret = transcriber.getRawSecret(key)) {
+        for (var entry : validExpressions.entrySet()) {
+            String expectedSecret = entry.getValue();
+            try (VaultRawSecret secret = transcriber.getRawSecret(entry.getKey())) {
                 Optional<ByteBuffer> optional = secret.get();
                 Optional<byte[]> optionalArray = secret.getAsArray();
                 if (expectedSecret != null) {
@@ -163,9 +163,9 @@ public void testGetCharSecretUsingValidExpressions() {
 
         // attempt to obtain a secret using a proper vault expressions. The key may or may not exist in the vault, so we
         // check both cases using the returned optional and comparing against the expected secret.
-        for (String key : validExpressions.keySet()) {
-            String expectedSecret = validExpressions.get(key);
-            try (VaultCharSecret secret = transcriber.getCharSecret(key)) {
+        for (var entry : validExpressions.entrySet()) {
+            String expectedSecret = entry.getValue();
+            try (VaultCharSecret secret = transcriber.getCharSecret(entry.getKey())) {
                 Optional<CharBuffer> optional = secret.get();
                 Optional<char[]> optionalArray = secret.getAsArray();
                 if (expectedSecret != null) {
@@ -249,9 +249,9 @@ public void testGetStringSecretUsingValidExpressions() {
 
         // attempt to obtain a secret using a proper vault expressions. The key may or may not exist in the vault, so we
         // check both cases using the returned optional and comparing against the expected secret.
-        for (String key : validExpressions.keySet()) {
-            String expectedSecret = validExpressions.get(key);
-            try (VaultStringSecret secret = transcriber.getStringSecret(key)) {
+        for (var entry : validExpressions.entrySet()) {
+            String expectedSecret = entry.getValue();
+            try (VaultStringSecret secret = transcriber.getStringSecret(entry.getKey())) {
                 Optional<String> optional = secret.get();
                 if (expectedSecret != null) {
                     Assert.assertTrue(optional.isPresent());
@@ -348,4 +348,4 @@ public void close() {
             // nothing to do
         }
     }
-}
\ No newline at end of file
+}
diff --git a/tests/base/src/test/java/org/keycloak/tests/admin/client/InstallationTest.java b/tests/base/src/test/java/org/keycloak/tests/admin/client/InstallationTest.java
index f8f851839fbc..b3c469964664 100644
--- a/tests/base/src/test/java/org/keycloak/tests/admin/client/InstallationTest.java
+++ b/tests/base/src/test/java/org/keycloak/tests/admin/client/InstallationTest.java
@@ -396,8 +396,8 @@ private void assertElements(Document doc, String tagNamespace, String tagName, M
         Node element = elementsByTagName.item(0);
 
         if (attrNamesAndValues != null) {
-            for (String attrName : attrNamesAndValues.keySet()) {
-                assertThat(element.getAttributes().getNamedItem(attrName).getNodeValue(), containsString(attrNamesAndValues.get(attrName)));
+            for (var entry : attrNamesAndValues.entrySet()) {
+                assertThat(element.getAttributes().getNamedItem(entry.getKey()).getNodeValue(), containsString(entry.getValue()));
             }
         }
     }
diff --git a/tests/utils/src/main/java/org/keycloak/tests/utils/Assert.java b/tests/utils/src/main/java/org/keycloak/tests/utils/Assert.java
index efb264756b89..7d785eaf2cef 100644
--- a/tests/utils/src/main/java/org/keycloak/tests/utils/Assert.java
+++ b/tests/utils/src/main/java/org/keycloak/tests/utils/Assert.java
@@ -168,9 +168,10 @@ public static void assertExpiration(long actual, long expected, long deviation)
 
     public static void assertRoleAttributes(Map<String, List<String>> expected, Map<String, List<String>> actual) {
         MatcherAssert.assertThat(actual.keySet(), equalTo(expected.keySet()));
-        for (String expectedKey : expected.keySet()) {
-            MatcherAssert.assertThat(actual.get(expectedKey).size(), is(equalTo(expected.get(expectedKey).size())));
-            MatcherAssert.assertThat(actual.get(expectedKey), containsInAnyOrder(expected.get(expectedKey).toArray()));
+        for (var entry : expected.entrySet()) {
+            String expectedKey = entry.getKey();
+            MatcherAssert.assertThat(actual.get(expectedKey).size(), is(equalTo(entry.getValue().size())));
+            MatcherAssert.assertThat(actual.get(expectedKey), containsInAnyOrder(entry.getValue().toArray()));
         }
     }
 }
diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/FailableHardcodedStorageProvider.java b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/FailableHardcodedStorageProvider.java
index 90e52bbe524c..2a6df132d88b 100644
--- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/FailableHardcodedStorageProvider.java
+++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/src/main/java/org/keycloak/testsuite/federation/FailableHardcodedStorageProvider.java
@@ -193,10 +193,10 @@ public UserModel getUserByUsername(RealmModel realm, String uname) {
         local.setLastName(last);
         local.setEmail(email);
         local.setFederationLink(model.getId());
-        for (String key : attributes.keySet()) {
-            List<String> values = attributes.get(key);
+        for (var entry : attributes.entrySet()) {
+            List<String> values = entry.getValue();
             if (values == null) continue;
-            local.setAttribute(key, values);
+            local.setAttribute(entry.getKey(), values);
         }
         return new Delegate(local);
     }
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/Timer.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/Timer.java
index a625aad9d1a2..50378c8be177 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/Timer.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/Timer.java
@@ -103,12 +103,12 @@ public void clearStats() {
     public void clearStats(boolean logStats, boolean saveData, boolean saveCharts) {
         if (logStats) {
             log.info("Timer Statistics:");
-            for (String op : stats.keySet()) {
+            for (var entry : stats.entrySet()) {
                 long sum = 0;
-                for (Long duration : stats.get(op)) {
+                for (Long duration : entry.getValue()) {
                     sum += duration;
                 }
-                log.info(String.format("Operation '%s' average: %s ms", op, sum / stats.get(op).size()));
+                log.info(String.format("Operation '%s' average: %s ms", entry.getKey(), sum / entry.getValue().size()));
             }
         }
         if (PROJECT_BUILD_DIRECTORY.exists()) {
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/Assert.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/Assert.java
index d84f94de6b75..52badde8df99 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/Assert.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/Assert.java
@@ -167,9 +167,10 @@ public static void assertExpiration(long actual, long expected, long deviation)
 
     public static void assertRoleAttributes(Map<String, List<String>> expected, Map<String, List<String>> actual) {
         MatcherAssert.assertThat(actual.keySet(), equalTo(expected.keySet()));
-        for (String expectedKey : expected.keySet()) {
-            MatcherAssert.assertThat(actual.get(expectedKey).size(), is(equalTo(expected.get(expectedKey).size())));
-            MatcherAssert.assertThat(actual.get(expectedKey), containsInAnyOrder(expected.get(expectedKey).toArray()));
+        for (var entry : expected.entrySet()) {
+            String expectedKey = entry.getKey();
+            MatcherAssert.assertThat(actual.get(expectedKey).size(), is(equalTo(entry.getValue().size())));
+            MatcherAssert.assertThat(actual.get(expectedKey), containsInAnyOrder(entry.getValue().toArray()));
         }
     }
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/exportimport/ExportImportUtil.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/exportimport/ExportImportUtil.java
index a2320af29f48..629ef53afaa8 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/exportimport/ExportImportUtil.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/exportimport/ExportImportUtil.java
@@ -525,8 +525,8 @@ private static List<RoleRepresentation> clientScopeMappings(ClientResource clien
         Map<String, ClientMappingsRepresentation> clientRoles = client.getScopeMappings().getAll().getClientMappings();
         if (clientRoles == null) return clientScopeMappings;
 
-        for (String clientKey : clientRoles.keySet()) {
-            List<RoleRepresentation> clientRoleScopeMappings = clientRoles.get(clientKey).getMappings();
+        for (ClientMappingsRepresentation clientMappingsRepresentation : clientRoles.values()) {
+            List<RoleRepresentation> clientRoleScopeMappings = clientMappingsRepresentation.getMappings();
             if (clientRoleScopeMappings != null) clientScopeMappings.addAll(clientRoleScopeMappings);
         }
 
@@ -538,8 +538,8 @@ private static List<RoleRepresentation> clientScopeMappings(ClientScopeResource
         Map<String, ClientMappingsRepresentation> clientRoles = client.getScopeMappings().getAll().getClientMappings();
         if (clientRoles == null) return clientScopeMappings;
 
-        for (String clientKey : clientRoles.keySet()) {
-            List<RoleRepresentation> clientRoleScopeMappings = clientRoles.get(clientKey).getMappings();
+        for (ClientMappingsRepresentation clientMappingsRepresentation : clientRoles.values()) {
+            List<RoleRepresentation> clientRoleScopeMappings = clientMappingsRepresentation.getMappings();
             if (clientRoleScopeMappings != null) clientScopeMappings.addAll(clientRoleScopeMappings);
         }
 
diff --git a/testsuite/utils/src/main/java/org/keycloak/testsuite/util/cli/AbstractSessionCacheCommand.java b/testsuite/utils/src/main/java/org/keycloak/testsuite/util/cli/AbstractSessionCacheCommand.java
index 1b83c4308fe9..708d040f2f86 100644
--- a/testsuite/utils/src/main/java/org/keycloak/testsuite/util/cli/AbstractSessionCacheCommand.java
+++ b/testsuite/utils/src/main/java/org/keycloak/testsuite/util/cli/AbstractSessionCacheCommand.java
@@ -227,13 +227,13 @@ public String getName() {
 
         @Override
         protected void doRunCacheCommand(KeycloakSession session, Cache<String, SessionEntityWrapper> cache) {
-            for (String id : cache.keySet()) {
-                SessionEntity entity = cache.get(id).getEntity();
+            for (var entry : cache.entrySet()) {
+                SessionEntity entity = entry.getValue().getEntity();
                 if (!(entity instanceof UserSessionEntity)) {
                     continue;
                 }
-                UserSessionEntity userSession = (UserSessionEntity) cache.get(id).getEntity();
-                log.info("list: key=" + id + ", value=" + toString(userSession));
+                UserSessionEntity userSession = (UserSessionEntity) entry.getValue().getEntity();
+                log.info("list: key=" + entry.getKey() + ", value=" + toString(userSession));
             }
         }
     }