VYPR
High severityNVD Advisory· Published Jan 22, 2025· Updated Mar 18, 2025

CVE-2025-24399

CVE-2025-24399

Description

Jenkins OpenId Connect Authentication Plugin 4.452.v2849b_d3945fa_ and earlier, except 4.438.440.v3f5f201de5dc, treats usernames as case-insensitive, allowing attackers on Jenkins instances configured with a case-sensitive OpenID Connect provider to log in as any user by providing a username that differs only in letter case, potentially gaining administrator access to Jenkins.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Jenkins OpenId Connect Authentication Plugin mishandles case sensitivity, letting attackers log in as any user by casing the username differently.

Vulnerability

Overview

Jenkins OpenId Connect Authentication Plugin versions 4.452.v2849b_d3945fa_ and earlier, except for the patched version 4.438.440.v3f5f201de5dc, incorrectly treats usernames as case-insensitive. This flaw exists in the plugin's authentication handling, which fails to respect the case sensitivity of the OpenID Connect provider. When a Jenkins instance is configured with a case-sensitive OpenID Connect provider, the plugin normalizes usernames to lowercase during login, allowing an attacker to authenticate as any user by simply providing a username that differs only in letter casing [1][2].

Exploitation

Method

To exploit this vulnerability, an attacker must have access to the Jenkins login page and know a valid username (or be able to guess one). The attacker can then log in by submitting the username with different casing (e.g., 'Admin' instead of 'admin'). Because the plugin treats the username as case-insensitive, it successfully authenticates the attacker as the targeted user. No special privileges or network position is required beyond being able to reach the Jenkins login interface [1][2].

Impact

Successful exploitation allows the attacker to log in as any user on the Jenkins instance, including users with administrative privileges. Given the high severity (CVSS High) and the potential for full administrative control, this vulnerability can lead to complete compromise of the Jenkins server, enabling data exfiltration, configuration changes, and further attacks [1][2].

Mitigation

Administrators should upgrade to version 4.438.440.v3f5f201de5dc or later, which introduces proper case-sensitive handling via the IdStrategy mechanism [3][4]. The fix ensures that usernames are compared exactly as returned by the OpenID Connect provider, preserving case sensitivity. No workaround is available; upgrading the plugin is the only remediation [1].

AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.jenkins-ci.plugins:oic-authMaven
< 4.453.v4d7765c854f44.453.v4d7765c854f4

Affected products

3

Patches

1
4d7765c854f4

SECURITY-3461

15 files changed · +341 7
  • src/main/java/org/jenkinsci/plugins/oic/monitor/OicIdStrategyMonitor.java+55 0 added
    @@ -0,0 +1,55 @@
    +package org.jenkinsci.plugins.oic.monitor;
    +
    +import com.google.common.annotations.VisibleForTesting;
    +import hudson.Extension;
    +import hudson.ExtensionList;
    +import hudson.model.AdministrativeMonitor;
    +import hudson.security.SecurityRealm;
    +import java.io.IOException;
    +import jenkins.model.Jenkins;
    +import org.jenkinsci.plugins.oic.Messages;
    +import org.jenkinsci.plugins.oic.OicSecurityRealm;
    +import org.kohsuke.accmod.Restricted;
    +import org.kohsuke.accmod.restrictions.NoExternalUse;
    +import org.kohsuke.stapler.HttpResponse;
    +import org.kohsuke.stapler.HttpResponses;
    +import org.kohsuke.stapler.interceptor.RequirePOST;
    +
    +@Extension
    +@Restricted(NoExternalUse.class)
    +public class OicIdStrategyMonitor extends AdministrativeMonitor {
    +
    +    // if null, means not evaluated yet
    +    Boolean missingIdStrategy;
    +
    +    public OicIdStrategyMonitor() {}
    +
    +    @VisibleForTesting
    +    protected static OicIdStrategyMonitor get() {
    +        return ExtensionList.lookupSingleton(OicIdStrategyMonitor.class);
    +    }
    +
    +    @Override
    +    public String getDisplayName() {
    +        return Messages.OicSecurityRealm_monitor_DisplayName();
    +    }
    +
    +    @Override
    +    public boolean isActivated() {
    +        if (!Boolean.FALSE.equals(missingIdStrategy)) {
    +            SecurityRealm securityRealm = Jenkins.get().getSecurityRealm();
    +            if (securityRealm instanceof OicSecurityRealm) {
    +                missingIdStrategy = ((OicSecurityRealm) securityRealm).isMissingIdStrategy();
    +            } else {
    +                missingIdStrategy = Boolean.FALSE;
    +            }
    +        }
    +        return missingIdStrategy;
    +    }
    +
    +    @RequirePOST
    +    public HttpResponse doForward() throws IOException {
    +        Jenkins.get().checkPermission(Jenkins.ADMINISTER);
    +        return HttpResponses.redirectViaContextPath("configureSecurity");
    +    }
    +}
    
  • src/main/java/org/jenkinsci/plugins/oic/OicSecurityRealm.java+54 1 modified
    @@ -41,6 +41,7 @@
     import edu.umd.cs.findbugs.annotations.NonNull;
     import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
     import hudson.Extension;
    +import hudson.ExtensionList;
     import hudson.Util;
     import hudson.model.Descriptor;
     import hudson.model.Descriptor.FormException;
    @@ -88,6 +89,8 @@
     import java.util.logging.Logger;
     import java.util.regex.Pattern;
     import javax.annotation.PostConstruct;
    +import jenkins.model.IdStrategy;
    +import jenkins.model.IdStrategyDescriptor;
     import jenkins.model.Jenkins;
     import jenkins.security.ApiTokenProperty;
     import jenkins.security.FIPS140;
    @@ -151,6 +154,8 @@ public class OicSecurityRealm extends SecurityRealm implements Serializable {
         private static final long serialVersionUID = 1L;
     
         private static final Logger LOGGER = Logger.getLogger(OicSecurityRealm.class.getName());
    +    private IdStrategy userIdStrategy;
    +    private IdStrategy groupIdStrategy;
     
         public static enum TokenAuthMethod {
             client_secret_basic(ClientAuthenticationMethod.CLIENT_SECRET_BASIC),
    @@ -316,7 +321,9 @@ public OicSecurityRealm(
                 String clientId,
                 Secret clientSecret,
                 OicServerConfiguration serverConfiguration,
    -            Boolean disableSslVerification)
    +            Boolean disableSslVerification,
    +            IdStrategy userIdStrategy,
    +            IdStrategy groupIdStrategy)
                 throws IOException, FormException {
             // Needed in DataBoundSetter
             this.disableSslVerification = Util.fixNull(disableSslVerification, Boolean.FALSE);
    @@ -327,6 +334,8 @@ public OicSecurityRealm(
             this.clientId = clientId;
             this.clientSecret = clientSecret;
             this.serverConfiguration = serverConfiguration;
    +        this.userIdStrategy = userIdStrategy;
    +        this.groupIdStrategy = groupIdStrategy;
         }
     
         @SuppressWarnings("deprecated")
    @@ -420,6 +429,20 @@ public String getUserNameField() {
             return userNameField;
         }
     
    +    @Restricted(NoExternalUse.class)
    +    public boolean isMissingIdStrategy() {
    +        return userIdStrategy == null || groupIdStrategy == null;
    +    }
    +
    +    @Override
    +    public IdStrategy getUserIdStrategy() {
    +        if (userIdStrategy != null) {
    +            return userIdStrategy;
    +        } else {
    +            return IdStrategy.CASE_INSENSITIVE;
    +        }
    +    }
    +
         public String getTokenFieldToCheckKey() {
             return tokenFieldToCheckKey;
         }
    @@ -440,6 +463,15 @@ public String getGroupsFieldName() {
             return groupsFieldName;
         }
     
    +    @Override
    +    public IdStrategy getGroupIdStrategy() {
    +        if (groupIdStrategy != null) {
    +            return groupIdStrategy;
    +        } else {
    +            return IdStrategy.CASE_INSENSITIVE;
    +        }
    +    }
    +
         public boolean isDisableSslVerification() {
             return disableSslVerification;
         }
    @@ -1628,5 +1660,26 @@ public Descriptor<OicServerConfiguration> getDefaultServerConfigurationType() {
             public boolean isFipsEnabled() {
                 return FIPS140.useCompliantAlgorithms();
             }
    +
    +        @Restricted(NoExternalUse.class)
    +        public List<IdStrategyDescriptor> getIdStrategyDescriptors() {
    +            return ExtensionList.lookup(IdStrategyDescriptor.class);
    +        }
    +
    +        /**
    +         * The default username strategy for new OicSecurityRealm
    +         */
    +        @Restricted(NoExternalUse.class)
    +        public IdStrategy defaultUsernameIdStrategy() {
    +            return new IdStrategy.CaseSensitive();
    +        }
    +
    +        /**
    +         * The default group strategy for new OicSecurityRealm
    +         */
    +        @Restricted(NoExternalUse.class)
    +        public IdStrategy defaultGroupIdStrategy() {
    +            return new IdStrategy.CaseSensitive();
    +        }
         }
     }
    
  • src/main/resources/org/jenkinsci/plugins/oic/Messages.properties+1 0 modified
    @@ -27,3 +27,4 @@ OicSecurityRealm.DisableSslVerificationFipsMode = SSL verification can not be di
     OicSecurityRealm.DisableTokenVerificationFipsMode = Token verification can not be disabled in FIPS mode
     OicServerWellKnownConfiguration.DisplayName = Discovery via well-known endpoint
     OicServerManualConfiguration.DisplayName = Manual entry
    +OicSecurityRealm.monitor.DisplayName= Openid Connect Id Strategy Configuration
    \ No newline at end of file
    
  • src/main/resources/org/jenkinsci/plugins/oic/monitor/OicIdStrategyMonitor/description.jelly+4 0 added
    @@ -0,0 +1,4 @@
    +<?jelly escape-by-default='true'?>
    +<j:jelly xmlns:j="jelly:core" xmlns:l="/lib/layout" xmlns:f="/lib/form" xmlns:i="jelly:fmt" xmlns:st="jelly:stapler">
    +    ${%blurb}
    +</j:jelly>
    
  • src/main/resources/org/jenkinsci/plugins/oic/monitor/OicIdStrategyMonitor/description.properties+1 0 added
    @@ -0,0 +1 @@
    +blurb=The OpenId Connect Security Realm's "Username case sensitivity" and "Group name case sensitivity" options have not been configured.
    
  • src/main/resources/org/jenkinsci/plugins/oic/monitor/OicIdStrategyMonitor/message.jelly+14 0 added
    @@ -0,0 +1,14 @@
    +<?jelly escape-by-default='true'?>
    +<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form" xmlns:l="/lib/layout">
    +<div class="alert alert-warning">
    +    <l:isAdmin>
    +        <form method="post" action="${rootURL}/${it.url}/forward">
    +            <f:submit value="${%configureSecurityRealm}"/>
    +        </form>
    +    </l:isAdmin>
    +    <j:set var="actionAnchor">
    +        <a href="${rootURL}/configure">${%actionUrlContent}</a>
    +    </j:set>
    +    ${%blurb}
    +</div>
    +</j:jelly>
    
  • src/main/resources/org/jenkinsci/plugins/oic/monitor/OicIdStrategyMonitor/message.properties+6 0 added
    @@ -0,0 +1,6 @@
    +blurb=\
    +  <p>The Openid Connect Security Realm was configured before the introduction of the "Username case sensitivity" and "Group name case sensitivity" options.</p> \
    +  <p>As a result, the current configuration treats these values as case-insensitive, whereas the default for new configurations is case-sensitive.</p> \
    +  <p>This difference could introduce a security vulnerability depending on your specific use case. For further information, refer to the <a href="https://www.jenkins.io/security/advisory/2025-01-22/#SECURITY-3461">security advisory</a>. Please review and select the appropriate case sensitivity settings for your environment, then save the updated security realm configuration.</p> \
    +  <p>Warning: Switching from case-insensitive to case-sensitive behavior can be a lossy operation if there are mixed-case usernames or group names. Users with externally-defined mixed-case names will effectively be treated as new users they next time they log in, and will lose their existing user preferences. Group-related configurations in Jenkins for externally-defined groups with mixed case names will no longer apply to members of those external groups. Users with mixed-case names previously defined in groups in Jenkins will also no longer be considered members of those groups after the switch.</p>
    +configureSecurityRealm=Configure the Security Realm
    
  • src/main/resources/org/jenkinsci/plugins/oic/OicSecurityRealm/config.jelly+6 0 modified
    @@ -16,6 +16,9 @@
           <f:entry title="${%UsernameFieldName}" field="userNameField">
             <f:textbox/>
           </f:entry>
    +      <f:entry>
    +        <f:dropdownDescriptorSelector title="${%UsernameIdStrategy}" field="userIdStrategy" default="${descriptor.defaultUsernameIdStrategy()}" descriptors="${descriptor.idStrategyDescriptors}"/>
    +      </f:entry>
           <f:entry title="${%FullnameFieldName}" field="fullNameFieldName">
             <f:textbox/>
           </f:entry>
    @@ -25,6 +28,9 @@
           <f:entry title="${%GroupsFieldName}" field="groupsFieldName">
             <f:textbox/>
           </f:entry>
    +      <f:entry>
    +        <f:dropdownDescriptorSelector title="${%GroupIdStrategy}" field="groupIdStrategy" default="${descriptor.defaultGroupIdStrategy()}" descriptors="${descriptor.idStrategyDescriptors}"/>
    +      </f:entry>
         </f:advanced>
         <f:entry title="${%LogoutFromOpenIDProvider}" field="logoutFromOpenidProvider">
           <f:checkbox id="logoutFromIDP"/>
    
  • src/main/resources/org/jenkinsci/plugins/oic/OicSecurityRealm/config.properties+2 0 modified
    @@ -26,3 +26,5 @@ UserFields=User fields
     Username=Username
     UsernameFieldName=User name field name
     WellknownConfigurationEndpoint=Well-known configuration endpoint
    +UsernameIdStrategy=Username case sensitivity
    +GroupIdStrategy=Group name case sensitivity
    
  • src/test/java/org/jenkinsci/plugins/oic/monitor/OicStrategyMonitorTest.java+58 0 added
    @@ -0,0 +1,58 @@
    +package org.jenkinsci.plugins.oic.monitor;
    +
    +import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
    +import com.github.tomakehurst.wiremock.junit.WireMockRule;
    +import jenkins.model.IdStrategy;
    +import jenkins.model.Jenkins;
    +import org.jenkinsci.plugins.oic.TestRealm;
    +import org.junit.Rule;
    +import org.junit.Test;
    +import org.jvnet.hudson.test.Issue;
    +import org.jvnet.hudson.test.JenkinsSessionRule;
    +
    +import static org.junit.Assert.assertFalse;
    +import static org.junit.Assert.assertTrue;
    +
    +public class OicStrategyMonitorTest {
    +
    +    @Rule
    +    public JenkinsSessionRule sessions = new JenkinsSessionRule();
    +
    +    @Rule
    +    public WireMockRule wireMockRule = new WireMockRule(new WireMockConfiguration().dynamicPort(), true);
    +
    +    @Test
    +    @Issue("SECURITY-3461")
    +    public void smokes_caseInsensitive() throws Throwable {
    +        sessions.then(r -> {
    +            TestRealm realm = new TestRealm(wireMockRule);
    +            Jenkins.get().setSecurityRealm(realm);
    +            assertTrue(OicIdStrategyMonitor.get().isActivated());
    +        });
    +        sessions.then(r -> {
    +            assertTrue(OicIdStrategyMonitor.get().isActivated());
    +            TestRealm realm = new TestRealm(new TestRealm.Builder(wireMockRule)
    +                    .WithMinimalDefaults()
    +                            .WithGroupIdStrategy(IdStrategy.CASE_INSENSITIVE)
    +                            .WithUserIdStrategy(IdStrategy.CASE_INSENSITIVE));
    +            Jenkins.get().setSecurityRealm(realm);
    +            assertFalse(OicIdStrategyMonitor.get().isActivated());
    +        });
    +        sessions.then(r -> {
    +            assertFalse(OicIdStrategyMonitor.get().isActivated());
    +        });
    +    }
    +
    +    @Test
    +    @Issue("SECURITY-3461")
    +    public void smokes_noChange() throws Throwable {
    +        sessions.then(r -> {
    +            TestRealm realm = new TestRealm(wireMockRule);
    +            Jenkins.get().setSecurityRealm(realm);
    +            assertTrue(OicIdStrategyMonitor.get().isActivated());
    +        });
    +        sessions.then(r -> {
    +            assertTrue(OicIdStrategyMonitor.get().isActivated());
    +        });
    +    }
    +}
    
  • src/test/java/org/jenkinsci/plugins/oic/OicSecurityRealmFipsTest.java+2 2 modified
    @@ -37,10 +37,10 @@ public class OicSecurityRealmFipsTest {
         @Test
         @WithoutJenkins
         public void settingNonCompliantValuesNotAllowedTest() throws IOException, Descriptor.FormException {
    -        OicSecurityRealm realm = new OicSecurityRealm("clientId", Secret.fromString("secret"), null, false);
    +        OicSecurityRealm realm = new OicSecurityRealm("clientId", Secret.fromString("secret"), null, false, null, null);
             Descriptor.FormException ex = assertThrows(
                     Descriptor.FormException.class,
    -                () -> new OicSecurityRealm("clientId", Secret.fromString("secret"), null, true));
    +                () -> new OicSecurityRealm("clientId", Secret.fromString("secret"), null, true, null, null));
             assertThat(
                     "Exception contains the reason",
                     ex.getMessage(),
    
  • src/test/java/org/jenkinsci/plugins/oic/OicSecurityRealmIdStrategyTest.java+117 0 added
    @@ -0,0 +1,117 @@
    +package org.jenkinsci.plugins.oic;
    +
    +import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
    +import com.github.tomakehurst.wiremock.junit.WireMockRule;
    +import hudson.model.User;
    +import hudson.security.SecurityRealm;
    +import jenkins.model.IdStrategy;
    +import jenkins.model.Jenkins;
    +import org.junit.Rule;
    +import org.junit.Test;
    +import org.jvnet.hudson.test.Issue;
    +import org.jvnet.hudson.test.JenkinsSessionRule;
    +
    +import static org.hamcrest.MatcherAssert.assertThat;
    +import static org.hamcrest.core.IsInstanceOf.instanceOf;
    +import static org.junit.Assert.assertEquals;
    +import static org.junit.Assert.assertFalse;
    +import static org.junit.Assert.assertNotEquals;
    +import static org.junit.Assert.assertNotNull;
    +import static org.junit.Assert.assertTrue;
    +
    +public class OicSecurityRealmIdStrategyTest {
    +
    +    @Rule
    +    public JenkinsSessionRule sessions = new JenkinsSessionRule();
    +
    +    @Rule
    +    public WireMockRule wireMockRule = new WireMockRule(new WireMockConfiguration().dynamicPort(), true);
    +
    +    @Test
    +    @Issue("SECURITY-3461")
    +    public void testUserIdStrategy_caseInsensitive() throws Throwable {
    +        sessions.then(r -> {
    +            TestRealm realm = new TestRealm(new TestRealm.Builder(wireMockRule)
    +                    .WithMinimalDefaults().WithUserIdStrategy(IdStrategy.CASE_INSENSITIVE));
    +            Jenkins.get().setSecurityRealm(realm);
    +            User testuser = User.getById("testuser", true);
    +            assertNotNull(testuser);
    +            assertEquals("testuser", testuser.getDisplayName());
    +            testuser.save();
    +
    +            User testUSER = User.getById("testUSER", true);
    +            assertNotNull(testUSER);
    +            assertEquals("testuser", testUSER.getDisplayName());
    +            testUSER.save();
    +
    +            assertEquals(testuser, testUSER);
    +        });
    +        sessions.then(r -> {
    +            User testuser = User.getById("testuser", false);
    +            assertNotNull(testuser);
    +            assertEquals("testuser", testuser.getDisplayName());
    +
    +            User testUSER = User.getById("testUSER", false);
    +            assertNotNull(testUSER);
    +            assertEquals("testuser", testUSER.getDisplayName());
    +            assertEquals(testuser, testUSER);
    +        });
    +    }
    +
    +    @Test
    +    @Issue("SECURITY-3461")
    +    public void testUserIdStrategy_caseSensitive() throws Throwable {
    +        sessions.then(r -> {
    +            TestRealm realm = new TestRealm(new TestRealm.Builder(wireMockRule)
    +                    .WithMinimalDefaults().WithUserIdStrategy(new IdStrategy.CaseSensitive()));
    +            Jenkins.get().setSecurityRealm(realm);
    +            User testuser = User.getById("testuser", true);
    +            assertNotNull(testuser);
    +            assertEquals("testuser", testuser.getDisplayName());
    +            testuser.save();
    +
    +            User testUSER = User.getById("testUSER", true);
    +            assertNotNull(testUSER);
    +            assertEquals("testUSER", testUSER.getDisplayName());
    +            testUSER.save();
    +
    +            assertNotEquals(testuser, testUSER);
    +        });
    +        sessions.then(r -> {
    +            User testuser = User.getById("testuser", false);
    +            assertNotNull(testuser);
    +            assertEquals("testuser", testuser.getDisplayName());
    +
    +            User testUSER = User.getById("testUSER", false);
    +            assertNotNull(testUSER);
    +            assertEquals("testUSER", testUSER.getDisplayName());
    +
    +            assertNotEquals(testuser, testUSER);
    +        });
    +    }
    +
    +    @Test
    +    @Issue("SECURITY-3461")
    +    public void testUserIdStrategy_default() throws Throwable {
    +        sessions.then(r -> {
    +            TestRealm realm = new TestRealm(wireMockRule);
    +            Jenkins.get().setSecurityRealm(realm);
    +        });
    +        sessions.then(r -> {
    +            // when restarting, ensure the default case-insensitive is used
    +            SecurityRealm securityRealm = Jenkins.get().getSecurityRealm();
    +            assertThat(securityRealm, instanceOf(OicSecurityRealm.class));
    +            OicSecurityRealm oicSecurityRealm = (OicSecurityRealm) securityRealm;
    +            assertTrue(oicSecurityRealm.isMissingIdStrategy());
    +            assertEquals(IdStrategy.CASE_INSENSITIVE, securityRealm.getUserIdStrategy());
    +            assertEquals(IdStrategy.CASE_INSENSITIVE, securityRealm.getGroupIdStrategy());
    +
    +            TestRealm realm = new TestRealm(new TestRealm.Builder(wireMockRule)
    +                    .WithMinimalDefaults()
    +                            .WithUserIdStrategy(IdStrategy.CASE_INSENSITIVE)
    +                            .WithGroupIdStrategy(IdStrategy.CASE_INSENSITIVE));
    +            Jenkins.get().setSecurityRealm(realm);
    +            assertFalse(realm.isMissingIdStrategy());
    +        });
    +    }
    +}
    
  • src/test/java/org/jenkinsci/plugins/oic/SecurityRealmConfigurationFIPSTest.java+3 3 modified
    @@ -15,19 +15,19 @@ public class SecurityRealmConfigurationFIPSTest {
     
         @Test(expected = Descriptor.FormException.class)
         public void escapeHatchThrowsException() throws Exception {
    -        new OicSecurityRealm("clientId", null, null, null).setEscapeHatchEnabled(true);
    +        new OicSecurityRealm("clientId", null, null, null, null, null).setEscapeHatchEnabled(true);
         }
     
         @Test
         public void escapeHatchToFalse() throws Exception {
    -        OicSecurityRealm oicSecurityRealm = new OicSecurityRealm("clientId", null, null, null);
    +        OicSecurityRealm oicSecurityRealm = new OicSecurityRealm("clientId", null, null, null, null, null);
             oicSecurityRealm.setEscapeHatchEnabled(false);
             assertThat(oicSecurityRealm.isEscapeHatchEnabled(), is(false));
         }
     
         @Test
         public void readresolve() throws Exception {
    -        OicSecurityRealm oicSecurityRealm = new OicSecurityRealm("clientId", null, null, null);
    +        OicSecurityRealm oicSecurityRealm = new OicSecurityRealm("clientId", null, null, null, null, null);
             oicSecurityRealm.setEscapeHatchEnabled(false);
             assertThat(oicSecurityRealm.isEscapeHatchEnabled(), is(false));
             oicSecurityRealm.readResolve();
    
  • src/test/java/org/jenkinsci/plugins/oic/TestRealm.java+16 1 modified
    @@ -8,6 +8,7 @@
     import java.io.IOException;
     import java.io.ObjectStreamException;
     import java.text.ParseException;
    +import jenkins.model.IdStrategy;
     import org.kohsuke.stapler.StaplerRequest2;
     import org.kohsuke.stapler.StaplerResponse2;
     import org.pac4j.core.context.FrameworkParameters;
    @@ -53,6 +54,8 @@ public static class Builder {
             public String escapeHatchGroup = null;
             public boolean automanualconfigure = false;
             public boolean disableTokenValidation = true; // opt in for some specific tests
    +        public IdStrategy userIdStrategy;
    +        public IdStrategy groupIdStrategy;
     
             public Builder(WireMockRule wireMockRule, boolean useTLS) throws IOException {
                 this(
    @@ -149,6 +152,16 @@ public Builder WithDisableSslVerification(boolean disableSslVerification) {
                 return this;
             }
     
    +        public Builder WithUserIdStrategy(IdStrategy userIdStrategy) {
    +            this.userIdStrategy = userIdStrategy;
    +            return this;
    +        }
    +
    +        public Builder WithGroupIdStrategy(IdStrategy groupIdStrategy) {
    +            this.groupIdStrategy = groupIdStrategy;
    +            return this;
    +        }
    +
             public TestRealm build() throws Exception {
                 return new TestRealm(this);
             }
    @@ -184,7 +197,9 @@ public TestRealm(Builder builder) throws Exception {
                     builder.clientId,
                     builder.clientSecret,
                     builder.buildServerConfiguration(),
    -                builder.disableSslVerification);
    +                builder.disableSslVerification,
    +                builder.userIdStrategy,
    +                builder.groupIdStrategy);
             this.setUserNameField(builder.userNameField);
             this.setTokenFieldToCheckKey(builder.tokenFieldToCheckKey);
             this.setTokenFieldToCheckValue(builder.tokenFieldToCheckValue);
    
  • src/test/resources/org/jenkinsci/plugins/oic/ConfigurationAsCodeExport.yml+2 0 modified
    @@ -5,6 +5,7 @@ escapeHatchEnabled: true
     escapeHatchGroup: "escapeHatchGroup"
     escapeHatchUsername: "escapeHatchUsername"
     fullNameFieldName: "fullNameFieldName"
    +groupIdStrategy: "caseInsensitive"
     groupsFieldName: "groupsFieldName"
     nonceDisabled: true
     pkceEnabled: true
    @@ -17,4 +18,5 @@ serverConfiguration:
         jwksServerUrl: "http://localhost/jwks"
         scopes: "scopes"
         tokenServerUrl: "http://localhost/token"
    +userIdStrategy: "caseInsensitive"
     userNameField: "userNameField"
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

1