Skip to content

Commit 5169b69

Browse files
authored
JENKINS-63401 Harden looking up credentials (#350)
1 parent d48d03c commit 5169b69

File tree

2 files changed

+67
-9
lines changed

2 files changed

+67
-9
lines changed

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/api/credentials/BitbucketOAuthCredentialMatcher.java

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@
44
import com.cloudbees.plugins.credentials.CredentialsMatcher;
55
import com.cloudbees.plugins.credentials.common.UsernamePasswordCredentials;
66
import hudson.util.Secret;
7+
import java.util.logging.Level;
8+
import java.util.logging.Logger;
79

810
public class BitbucketOAuthCredentialMatcher implements CredentialsMatcher, CredentialsMatcher.CQL {
9-
private static int keyLenght = 18;
10-
private static int secretLenght = 32;
11+
private static int keyLength = 18;
12+
private static int secretLength = 32;
1113

1214
private static final long serialVersionUID = 6458784517693211197L;
15+
private static final Logger LOGGER = Logger.getLogger(BitbucketOAuthCredentialMatcher.class.getName());
1316

1417
/**
1518
* {@inheritDoc}
@@ -19,13 +22,18 @@ public boolean matches(Credentials item) {
1922
if (!(item instanceof UsernamePasswordCredentials))
2023
return false;
2124

22-
UsernamePasswordCredentials usernamePasswordCredential = ((UsernamePasswordCredentials) item);
23-
String username = usernamePasswordCredential.getUsername();
24-
boolean isEMail = username.contains(".") && username.contains("@");
25-
boolean validSecretLenght = Secret.toString(usernamePasswordCredential.getPassword()).length() == secretLenght;
26-
boolean validKeyLenght = username.length() == keyLenght;
25+
try {
26+
UsernamePasswordCredentials usernamePasswordCredential = ((UsernamePasswordCredentials) item);
27+
String username = usernamePasswordCredential.getUsername();
28+
boolean isEMail = username.contains(".") && username.contains("@");
29+
boolean validSecretLength = Secret.toString(usernamePasswordCredential.getPassword()).length() == secretLength;
30+
boolean validKeyLength = username.length() == keyLength;
2731

28-
return !isEMail && validKeyLenght && validSecretLenght;
32+
return !isEMail && validKeyLength && validSecretLength;
33+
} catch (RuntimeException e) {
34+
LOGGER.log(Level.FINE, "Caught exception validating credential", e);
35+
return false;
36+
}
2937
}
3038

3139
/**
@@ -35,7 +43,7 @@ public boolean matches(Credentials item) {
3543
public String describe() {
3644
return String.format(
3745
"(username.lenght == %d && password.lenght == %d && !(username CONTAINS \".\" && username CONTAINS \"@\")",
38-
keyLenght, secretLenght);
46+
keyLength, secretLength);
3947
}
4048

4149

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package com.cloudbees.jenkins.plugins.bitbucket.api.credentials;
2+
3+
import com.cloudbees.plugins.credentials.CredentialsDescriptor;
4+
import com.cloudbees.plugins.credentials.CredentialsScope;
5+
import com.cloudbees.plugins.credentials.common.UsernamePasswordCredentials;
6+
import edu.umd.cs.findbugs.annotations.NonNull;
7+
import hudson.util.Secret;
8+
import org.junit.Test;
9+
import org.jvnet.hudson.test.Issue;
10+
11+
import static org.junit.Assert.assertFalse;
12+
13+
public class BitbucketOAuthCredentialMatcherTest {
14+
15+
/**
16+
* Some plugins do remote work when getPassword is called and aren't expecting to just be randomly looked up
17+
* One example is GitHubAppCredentials
18+
*/
19+
@Test
20+
@Issue("JENKINS-63401")
21+
public void matches_returns_false_when_exception_getting_password() {
22+
assertFalse(new BitbucketOAuthCredentialMatcher().matches(new ExceptionalCredentials()));
23+
}
24+
25+
private static class ExceptionalCredentials implements UsernamePasswordCredentials {
26+
27+
@NonNull
28+
@Override
29+
public Secret getPassword() {
30+
throw new IllegalArgumentException("Failed authentication");
31+
}
32+
33+
@NonNull
34+
@Override
35+
public String getUsername() {
36+
return "dummy-username";
37+
}
38+
39+
@Override
40+
public CredentialsScope getScope() {
41+
return null;
42+
}
43+
44+
@NonNull
45+
@Override
46+
public CredentialsDescriptor getDescriptor() {
47+
return null;
48+
}
49+
}
50+
}

0 commit comments

Comments
 (0)