Vulnerability: Jenkins before 1.551 and LTS before 1.532.2 does not invalidate the API token when a user is deleted, which allows remote authenticated users to retain access via the token.
Vulnerability ID: CVE-2014-2062
CWE: CWE-287
Severity score: 6.4
Project: https://github.com/jenkinsci/jenkins
Published: 2014-10-17
File: core/src/main/java/jenkins/security/ApiTokenFilter.java
Commit message: [FIXED SECURITY-89] When checking an API token, verify that the user actually exists.
Commit author: Jesse Glick

Vulnerable version (before fix):
  import hudson.model.User; import hudson.security.ACL; import hudson.util.Scrambler; import org.acegisecurity.context.SecurityContext; import org.acegisecurity.context.SecurityContextHolder;  import javax.servlet.Filter; import javax.servlet.FilterChain; public void doFilter(ServletRequest request, ServletResponse response, FilterCha             int idx = uidpassword.indexOf(':');             if (idx >= 0) {                 String username = uidpassword.substring(0, idx);                 String password = uidpassword.substring(idx+1);                  // attempt to authenticate as API token

Fixed version (after fix):
  import hudson.model.User; import hudson.security.ACL; import hudson.security.UserMayOrMayNotExistException; import hudson.util.Scrambler; import jenkins.model.Jenkins; import org.acegisecurity.context.SecurityContext; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.userdetails.UsernameNotFoundException; import org.springframework.dao.DataAccessException;  import javax.servlet.Filter; import javax.servlet.FilterChain; public void doFilter(ServletRequest request, ServletResponse response, FilterCha             int idx = uidpassword.indexOf(':');             if (idx >= 0) {                 String username = uidpassword.substring(0, idx);                 try {                     Jenkins.getInstance().getSecurityRealm().loadUserByUsername(username);                 } catch (UserMayOrMayNotExistException x) {                     // OK, give them the benefit of the doubt.                 } catch (UsernameNotFoundException x) {                     // Not/no longer a user; deny the API token. (But do not leak the information that this happened.)                     chain.doFilter(request, response);                     return;                 } catch (DataAccessException x) {                     throw new ServletException(x);                 }                 String password = uidpassword.substring(idx+1);                  // attempt to authenticate as API token

Patch:
patch: @@ -2,9 +2,13 @@
 
 import hudson.model.User;
 import hudson.security.ACL;
+import hudson.security.UserMayOrMayNotExistException;
 import hudson.util.Scrambler;
+import jenkins.model.Jenkins;
 import org.acegisecurity.context.SecurityContext;
 import org.acegisecurity.context.SecurityContextHolder;
+import org.acegisecurity.userdetails.UsernameNotFoundException;
+import org.springframework.dao.DataAccessException;
 
 import javax.servlet.Filter;
 import javax.servlet.FilterChain;
@@ -41,6 +45,17 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha
             int idx = uidpassword.indexOf(':');
             if (idx >= 0) {
                 String username = uidpassword.substring(0, idx);
+                try {
+                    Jenkins.getInstance().getSecurityRealm().loadUserByUsername(username);
+                } catch (UserMayOrMayNotExistException x) {
+                    // OK, give them the benefit of the doubt.
+                } catch (UsernameNotFoundException x) {
+                    // Not/no longer a user; deny the API token. (But do not leak the information that this happened.)
+                    chain.doFilter(request, response);
+                    return;
+                } catch (DataAccessException x) {
+                    throw new ServletException(x);
+                }
                 String password = uidpassword.substring(idx+1);
 
                 // attempt to authenticate as API token
path: core/src/main/java/jenkins/security/ApiTokenFilter.java