diff --git a/its/autoscan/src/test/resources/autoscan/diffs/diff_S6437.json b/its/autoscan/src/test/resources/autoscan/diffs/diff_S6437.json
index 608dbff770f..0962a59b2b9 100644
--- a/its/autoscan/src/test/resources/autoscan/diffs/diff_S6437.json
+++ b/its/autoscan/src/test/resources/autoscan/diffs/diff_S6437.json
@@ -1,6 +1,6 @@
{
"ruleKey": "S6437",
"hasTruePositives": true,
- "falseNegatives": 63,
+ "falseNegatives": 62,
"falsePositives": 0
}
diff --git a/its/ruling/src/test/resources/jboss-ejb3-tutorial/java-S2068.json b/its/ruling/src/test/resources/jboss-ejb3-tutorial/java-S2068.json
deleted file mode 100644
index 28e6d4dee9d..00000000000
--- a/its/ruling/src/test/resources/jboss-ejb3-tutorial/java-S2068.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-"jboss-ejb3-tutorial:interceptor/src/org/jboss/tutorial/interceptor/bean/EmailSystemBean.java": [
-49
-]
-}
diff --git a/its/ruling/src/test/resources/regex-examples/java-S2068.json b/its/ruling/src/test/resources/regex-examples/java-S2068.json
index 9e11e919170..68d1fe631f6 100644
--- a/its/ruling/src/test/resources/regex-examples/java-S2068.json
+++ b/its/ruling/src/test/resources/regex-examples/java-S2068.json
@@ -1,9 +1,5 @@
{
-"org.regex-examples:regex-examples:src/main/java/org/regex/examples/RegexDatabase1.java": [
-749
-],
"org.regex-examples:regex-examples:src/main/java/org/regex/examples/RegexDatabase8.java": [
-727,
-1257
+727
]
}
diff --git a/java-checks-aws/pom.xml b/java-checks-aws/pom.xml
index 66175d83e48..08e5bc28e67 100644
--- a/java-checks-aws/pom.xml
+++ b/java-checks-aws/pom.xml
@@ -62,6 +62,10 @@
commons-io
test
+
+ org.sonarsource.analyzer-commons
+ sonar-analyzer-commons
+
org.sonarsource.analyzer-commons
sonar-analyzer-recognizers
diff --git a/java-checks-aws/src/main/java/org/sonar/java/checks/security/HardCodedCredentialsShouldNotBeUsedCheck.java b/java-checks-aws/src/main/java/org/sonar/java/checks/security/HardCodedCredentialsShouldNotBeUsedCheck.java
index 4e3046bf7bc..3a463607b95 100644
--- a/java-checks-aws/src/main/java/org/sonar/java/checks/security/HardCodedCredentialsShouldNotBeUsedCheck.java
+++ b/java-checks-aws/src/main/java/org/sonar/java/checks/security/HardCodedCredentialsShouldNotBeUsedCheck.java
@@ -28,7 +28,9 @@
import org.sonar.java.annotations.VisibleForTesting;
import org.sonar.java.checks.helpers.CredentialMethod;
import org.sonar.java.checks.helpers.CredentialMethodsLoader;
+import org.sonar.java.checks.helpers.ExpressionsHelper;
import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
+import org.sonarsource.analyzer.commons.appsec.SecretClassifier;
import org.sonar.plugins.java.api.JavaFileScannerContext;
import org.sonar.plugins.java.api.semantic.MethodMatchers;
import org.sonar.plugins.java.api.tree.Arguments;
@@ -108,6 +110,10 @@ private void checkArguments(Arguments arguments, CredentialMethod method) {
ExpressionTree argument = arguments.get(targetArgumentIndex);
var secondaryLocations = new ArrayList();
if (isExpressionDerivedFromPlainText(argument, secondaryLocations, new HashSet<>())) {
+ String value = ExpressionsHelper.getConstantValueAsString(argument).value();
+ if (value != null && SecretClassifier.isKnownNonSecret(value)) {
+ continue;
+ }
reportIssue(argument, ISSUE_MESSAGE, secondaryLocations, null);
}
}
diff --git a/java-checks-test-sources/aws/src/main/java/checks/security/HardCodedCredentialsShouldNotBeUsedCheckSample.java b/java-checks-test-sources/aws/src/main/java/checks/security/HardCodedCredentialsShouldNotBeUsedCheckSample.java
index 05196aa4f6d..8db986123e4 100644
--- a/java-checks-test-sources/aws/src/main/java/checks/security/HardCodedCredentialsShouldNotBeUsedCheckSample.java
+++ b/java-checks-test-sources/aws/src/main/java/checks/security/HardCodedCredentialsShouldNotBeUsedCheckSample.java
@@ -32,10 +32,11 @@
import static java.lang.System.getProperty;
public class HardCodedCredentialsShouldNotBeUsedCheckSample {
- static final String FINAL_SECRET_STRING = "hunter2";
-// ^^^^^^^^^>
- static final byte[] FINAL_SECRET_BYTE_ARRAY = FINAL_SECRET_STRING.getBytes(StandardCharsets.UTF_8);
-// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^>
+ static final String FINAL_SECRET_STRING = "hunter2"; // Compliant, fake value filter
+ static final String FINAL_SECRET_STRING_2 = "xvxf6_gaa";
+// ^^^^^^^^^^^>
+ static final byte[] FINAL_SECRET_BYTE_ARRAY = FINAL_SECRET_STRING_2.getBytes(StandardCharsets.UTF_8);
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^>
private static String secretStringField = "hunter2";
private static byte[] secretByteArrayField = new byte[]{0xC, 0xA, 0xF, 0xE};
private static char[] secretCharArrayField = new char[]{0xC, 0xA, 0xF, 0xE};
@@ -54,39 +55,44 @@ public static void nonCompliant(byte[] message, boolean condition, Charset encod
// ^^^
SHA256.getHMAC(effectivelyConstantString.getBytes(), message); // Noncompliant
SHA256.getHMAC("anotherS3cr37".getBytes(), message); // Noncompliant
+ // FINAL_SECRET_STRING.getBytes() cannot be resolved to the value "hunter2" that should be filtered -> FPs
SHA256.getHMAC(FINAL_SECRET_STRING.getBytes(), message); // Noncompliant
SHA256.getHMAC(FINAL_SECRET_STRING.getBytes(StandardCharsets.UTF_8), message); // Noncompliant
SHA256.getHMAC(FINAL_SECRET_STRING.getBytes("UTF-8"), message); // Noncompliant
SHA256.getHMAC((FINAL_SECRET_STRING).getBytes("UTF-8"), message); // Noncompliant
- SHA256.getHMAC(new byte[]{(byte) 0xC, (byte) 0xA, (byte) 0xF, (byte) 0xE}, message); // Noncompliant
+ // FP should be filtered as short string value
+ SHA256.getHMAC(new byte[]{(byte) 0xC, (byte) 0xA, (byte) 0xF, (byte) 0xE}, message); // Noncompliant
// String based
HttpServletRequest request = new HttpServletRequestWrapper(null);
- request.login("user", "password"); // Noncompliant
+ request.login("user", "password"); // Compliant, fake value filter
+ request.login("user", "xvxf6_gaa"); // Noncompliant
request.login("user", effectivelyConstantString); // Noncompliant
// ^^^^^^^^^^^^^^^^^^^^^^^^^
- request.login("user", FINAL_SECRET_STRING); // Noncompliant
-// ^^^^^^^^^^^^^^^^^^^
- String plainTextSecret = new String("BOOM");
-// ^^^^^^^^^^^^^^^^^^>
- request.login("user", plainTextSecret); // Noncompliant
-// ^^^^^^^^^^^^^^^
+ request.login("user", FINAL_SECRET_STRING); // Compliant, fake values filter
+ request.login("user", FINAL_SECRET_STRING_2); // Noncompliant
+// ^^^^^^^^^^^^^^^^^^^^^
+ String plainTextSecret = new String("BOOM"); // Compliant, short values filter
+ String plainTextSecret2 = new String("BOOMBOOM");
+// ^^^^^^^^^^^^^^^^^^^^^^>
+ request.login("user", plainTextSecret2); // Noncompliant
+// ^^^^^^^^^^^^^^^^
request.login("user", new String("secret")); // Noncompliant
request.login("user", new String(FINAL_SECRET_BYTE_ARRAY, 0, 7)); // Noncompliant
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^@37<
-// ^^^^^^^^^@35<
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^@38<
+// ^^^^^^^^^^^@36<
request.login("user", new String(FINAL_SECRET_BYTE_ARRAY, encoding)); // Noncompliant
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^@37<
-// ^^^^^^^^^@35<
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^@38<
+// ^^^^^^^^^^^@36<
- String conditionalButPredictable = condition ? FINAL_SECRET_STRING : plainTextSecret;
-// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^>
+ String conditionalButPredictable = condition ? FINAL_SECRET_STRING_2 : plainTextSecret2;
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^>
request.login("user", conditionalButPredictable); // Noncompliant
// ^^^^^^^^^^^^^^^^^^^^^^^^^
-// ^^^^^^^^^@35<
-// ^^^^^^^^^^^^^^^^^^@70<
+// ^^^^^^^^^^^@36<
+// ^^^^^^^^^^^^^^^^^^^^^^@76<
request.login("user", Json.MEDIA_TYPE); // Noncompliant
// ^^^^^^^^^^^^^^^
String concatenatedPassword = "abc" + true + ":" + 12 + ":" + 43L + ":" + 'a' + ":" + 0.2f + ":" + 0.2d;
@@ -95,7 +101,8 @@ public static void nonCompliant(byte[] message, boolean condition, Charset encod
// ^^^^^^^^^^^^^^^^^^^^
jakarta.servlet.http.HttpServletRequest requestJakarta = new jakarta.servlet.http.HttpServletRequestWrapper(null);
- requestJakarta.login("user", "password"); // Noncompliant
+ requestJakarta.login("user", "password"); // Compliant
+ requestJakarta.login("user", "xvxf6_gaa"); // Noncompliant
KeyStore store = KeyStore.getInstance(null);
store.getKey("", new char[]{0xC, 0xA, 0xF, 0xE}); // Noncompliant
@@ -118,30 +125,42 @@ public static void nonCompliant(byte[] message, boolean condition, Charset encod
Encryptors.delux(effectivelyConstantString.subSequence(0, effectivelyConstantString.length()), effectivelyConstantString); // Noncompliant
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ // "password".subSequence(0, 0) cannot be resolved to the value "password" that should be filtered -> FPs
Encryptors.delux("password".subSequence(0, 0), "salt"); // Noncompliant
+ // TP
+ Encryptors.delux("xvxf6_gaa".subSequence(0, 0), "salt"); // Noncompliant
- new Pbkdf2PasswordEncoder("secret"); // Noncompliant
- new Pbkdf2PasswordEncoder(("secret")); // Noncompliant
+ new Pbkdf2PasswordEncoder("secret"); // Compliant, fake value filter
+ new Pbkdf2PasswordEncoder("xvxf6_gaa"); // Noncompliant
+ new Pbkdf2PasswordEncoder(("xvxf6_gaa")); // Noncompliant
+
String notInitialized;
notInitialized = "abc";
- new Pbkdf2PasswordEncoder(notInitialized); // Noncompliant
+ new Pbkdf2PasswordEncoder(notInitialized); // Compliant, short value filter
+
+ String notInitialized2;
+ notInitialized2 = "xvxf6_gaa";
+ new Pbkdf2PasswordEncoder(notInitialized2); // Noncompliant
- String longString = "abcdefghiklmnop";
+ String longString = "abcdefghiklmnop"; // Cpmpliant fake value contains 'abcd'
+ // longString.substring(2) cannot be resolved to the value "abcdefghiklmnop" that should be filtered -> FPs
new Pbkdf2PasswordEncoder(longString.substring(2)); // Noncompliant
- new Pbkdf2PasswordEncoder(longString.substring(0, 2)); // Noncompliant
- new Pbkdf2PasswordEncoder(longString.trim()); // Noncompliant
- new Pbkdf2PasswordEncoder(longString.strip()); // Noncompliant
- new Pbkdf2PasswordEncoder(longString.stripIndent()); // Noncompliant
- new Pbkdf2PasswordEncoder(longString.stripLeading()); // Noncompliant
- new Pbkdf2PasswordEncoder(longString.stripTrailing()); // Noncompliant
- new Pbkdf2PasswordEncoder(longString.translateEscapes()); // Noncompliant
- new Pbkdf2PasswordEncoder(longString.intern()); // Noncompliant
- new Pbkdf2PasswordEncoder(longString.toLowerCase()); // Noncompliant
- new Pbkdf2PasswordEncoder(longString.toLowerCase(Locale.ROOT)); // Noncompliant
- new Pbkdf2PasswordEncoder(longString.toUpperCase()); // Noncompliant
- new Pbkdf2PasswordEncoder(longString.toUpperCase(Locale.ROOT)); // Noncompliant
- new Pbkdf2PasswordEncoder(longString.toString()); // Noncompliant
+ String longString2 = "67uLmZeieGxDtp!cUm324D*7vji294";
+ new Pbkdf2PasswordEncoder(longString2.substring(2)); // Noncompliant
+ new Pbkdf2PasswordEncoder(longString2.substring(0, 2)); // Noncompliant
+ new Pbkdf2PasswordEncoder(longString2.trim()); // Noncompliant
+ new Pbkdf2PasswordEncoder(longString2.strip()); // Noncompliant
+ new Pbkdf2PasswordEncoder(longString2.stripIndent()); // Noncompliant
+ new Pbkdf2PasswordEncoder(longString2.stripLeading()); // Noncompliant
+ new Pbkdf2PasswordEncoder(longString2.stripTrailing()); // Noncompliant
+ new Pbkdf2PasswordEncoder(longString2.translateEscapes()); // Noncompliant
+ new Pbkdf2PasswordEncoder(longString2.intern()); // Noncompliant
+ new Pbkdf2PasswordEncoder(longString2.toLowerCase()); // Noncompliant
+ new Pbkdf2PasswordEncoder(longString2.toLowerCase(Locale.ROOT)); // Noncompliant
+ new Pbkdf2PasswordEncoder(longString2.toUpperCase()); // Noncompliant
+ new Pbkdf2PasswordEncoder(longString2.toUpperCase(Locale.ROOT)); // Noncompliant
+ new Pbkdf2PasswordEncoder(longString2.toString()); // Noncompliant
Object stringAsObject = "abc";
new Pbkdf2PasswordEncoder(stringAsObject.toString()); // Noncompliant
@@ -149,7 +168,9 @@ public static void nonCompliant(byte[] message, boolean condition, Charset encod
java.util.function.Consumer lambda = (arg) -> {
new Pbkdf2PasswordEncoder(arg);
String variableWithNullOwner = "abc";
- new Pbkdf2PasswordEncoder(variableWithNullOwner); // Noncompliant
+ new Pbkdf2PasswordEncoder(variableWithNullOwner); // Compliant, short value filter
+ String variableWithNullOwner2 = "xvxf6_gaa";
+ new Pbkdf2PasswordEncoder(variableWithNullOwner2); // Noncompliant
};
byte[] secretBytes = FINAL_SECRET_STRING.getBytes("UTF-8");
@@ -163,7 +184,7 @@ public static void nonCompliant(byte[] message, boolean condition, Charset encod
.signWith(paremSignatureAlgorithm, secretBytes); // Noncompliant
Jwts.builder()
- .signWith(SignatureAlgorithm.HS256, FINAL_SECRET_STRING); // Noncompliant
+ .signWith(SignatureAlgorithm.HS256, FINAL_SECRET_STRING); // Compliant, "hunter2" rejected by the fake value filter
Jwts.builder()
.signWith(SignatureAlgorithm.HS256, TextCodec.BASE64.encode(FINAL_SECRET_STRING)); // Noncompliant
diff --git a/java-checks-test-sources/default/src/main/files/non-compiling/checks/HardCodedPasswordCheckSample.java b/java-checks-test-sources/default/src/main/files/non-compiling/checks/HardCodedPasswordCheckSample.java
index 38b75557e2b..703b2d2bf4e 100644
--- a/java-checks-test-sources/default/src/main/files/non-compiling/checks/HardCodedPasswordCheckSample.java
+++ b/java-checks-test-sources/default/src/main/files/non-compiling/checks/HardCodedPasswordCheckSample.java
@@ -8,8 +8,8 @@
class HardCodedPasswordCheckSample {
private void a(char[] pwd, String var) throws SQLException {
- MyUnknownClass.myUnknownMethod("password", "xxxxx"); // Noncompliant
- MyUnknownClass.myUnknownMethod("other", "xxxxx"); // Compliant
+ MyUnknownClass.myUnknownMethod("password", "xvxf6_gaa"); // Noncompliant
+ MyUnknownClass.myUnknownMethod("other", "xvxf6_gaa"); // Compliant
}
}
diff --git a/java-checks-test-sources/default/src/main/java/checks/HardCodedPasswordCheckCustom.java b/java-checks-test-sources/default/src/main/java/checks/HardCodedPasswordCheckCustom.java
index e5478812b7a..d5cb02e696b 100644
--- a/java-checks-test-sources/default/src/main/java/checks/HardCodedPasswordCheckCustom.java
+++ b/java-checks-test-sources/default/src/main/java/checks/HardCodedPasswordCheckCustom.java
@@ -8,35 +8,40 @@ class HardCodedPasswordCheckCustom {
String fieldNameWithBazookaInIt;
private void a(char[] pwd, String var) {
- String variable2 = "login=a&password=xxx"; // Compliant
- String variable3 = "login=a&passwd=xxx"; // Compliant
- String variable4 = "login=a&pwd=xxx"; // Compliant
- String variable5 = "login=a&marmalade=xxx"; // Noncompliant {{'marmalade' detected in this expression, review this potentially hard-coded password.}}
-// ^^^^^^^^^^^^^^^^^^^^^^^
- String variable6 = "login=a&bazooka=xxx "; // Noncompliant
-
- String variableNameWithBazookaInIt = "xxx"; // Noncompliant
-// ^^^^^^^^^^^^^^^^^^^^^^^^^^^
- String variableNameWithmarMalAdeInIt = "xxx"; // Noncompliant
+ String variable2 = "login=a&password=xvxf6_gaa"; // Compliant
+ String variable3 = "login=a&passwd=xvxf6_gaa"; // Compliant
+ String variable4 = "login=a&pwd=xvxf6_gaa"; // Compliant
+ String variable5 = "login=a&marmalade=xxx"; // Compliant, short value filter
+ String variable5_2 = "login=a&marmalade=xvxf6_gaa"; // Noncompliant {{'marmalade' detected in this expression, review this potentially hard-coded password.}}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ String variable6 = "login=a&bazooka=xxx"; // Compliant, short value filter
+ String variable6_2 = "login=a&bazooka=xvxf6_gaa"; // Noncompliant
+
+ String variableNameWithBazookaInIt = "xxx"; // Compliant, short value filter
+ String variableNameWithBazookaInIt_2 = "xvxf6_gaa"; // Noncompliant
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- String variableNameWithPwdInIt = "xxx"; // Compliant
+ String variableNameWithmarMalAdeInIt = "xvxf6_gaa"; // Noncompliant
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ String variableNameWithPwdInIt = "xvxf6_gaa"; // Compliant
String otherVariableNameWithPasswordInIt;
- fieldNameWithPasswordInIt = "xx"; // Compliant
- this.fieldNameWithBazookaInIt = "xx"; // Noncompliant
+ fieldNameWithPasswordInIt = "xx";
+ this.fieldNameWithBazookaInIt = "xx"; // Compliant, , short value filter
HardCodedPasswordCheckCustom myA = new HardCodedPasswordCheckCustom();
- myA.setProperty("marmalade", "xxxxx"); // Noncompliant
- myA.setProperty("passwd", "xxxxx"); //Compliant
- myA.setProperty("pwd", "xxxxx"); // Compliant
+ myA.setProperty("marmalade", "xxxxx"); // Compliant, short value filter
+ myA.setProperty("marmalade", "xvxf6_gaa"); // Noncompliant
+ myA.setProperty("marmalade", "marmalade"); // Compliant
+ myA.setProperty("passwd", "xvxf6_gaa"); //Compliant
+ myA.setProperty("pwd", "xvxf6_gaa"); // Compliant
- new PasswordAuthentication("userName", "1234".toCharArray()); // Compliant, handled by S6437
+ new PasswordAuthentication("userName", "xvxf6_gaa".toCharArray()); // Compliant, handled by S6437
new PasswordAuthentication("userName", pwd); // Compliant
new PasswordAuthentication("userName", getPwd(var)); // Compliant
new PasswordAuthentication("userName", var.toCharArray()); // Compliant
- new OtherPasswordAuthentication("userName", "1234".toCharArray()); // Compliant
+ new OtherPasswordAuthentication("userName", "xvxf6_gaa".toCharArray()); // Compliant
}
private void setProperty(Object property, Object Value) { }
diff --git a/java-checks-test-sources/default/src/main/java/checks/HardCodedPasswordCheckSample.java b/java-checks-test-sources/default/src/main/java/checks/HardCodedPasswordCheckSample.java
index 52b0500fe6d..4d4c81b1436 100644
--- a/java-checks-test-sources/default/src/main/java/checks/HardCodedPasswordCheckSample.java
+++ b/java-checks-test-sources/default/src/main/java/checks/HardCodedPasswordCheckSample.java
@@ -28,30 +28,33 @@ private void a(char[] pwd, String var) throws SQLException {
// ========== 1. String literal ==========
// The variable name does not influence the issue, only the string is considered.
String variable1 = "blabla";
- String variable2 = "login=a&password=xxx"; // Noncompliant {{'password' detected in this expression, review this potentially hard-coded password.}}
-// ^^^^^^^^^^^^^^^^^^^^^^
- String variable3 = "login=a&passwd=xxx"; // Noncompliant
- String variable4 = "login=a&pwd=xxx"; // Noncompliant
+ String variable2 = "login=a&password=xxx"; // Compliant, short value filter
+ String variable2_2 = "login=a&password=xvxf6_gaa"; // Noncompliant {{'password' detected in this expression, review this potentially hard-coded password.}}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ String variable3 = "login=a&passwd=xxx"; // Compliant: short value filter
+ String variable3_2 = "login=a&passwd=xvxf6_gaa"; // Noncompliant {{'passwd' detected in this expression, review this potentially hard-coded password.}}
+ String variable4 = "login=a&pwd=xxx"; // Compliant, short value filter
+ String variable4_2 = "login=a&pwd=xvxf6_gaa"; // Noncompliant {{'pwd' detected in this expression, review this potentially hard-coded password.}}
String variable5 = "login=a&password=";
String variable6 = "login=a&password= ";
- String params = "user=admin&password=Password123"; // Noncompliant
+ String params = "user=admin&password=Password123"; // Compliant, value contains the keyword password
+ String params2 = "user=admin&password=sonar123"; // Noncompliant
String sqlserver = "pgsql:host=localhost port=5432 dbname=test user=postgres password=postgres"; // Noncompliant
- // Password starting with "?" are ignored
- String query1 = "password=?hard-to-find"; // Compliant
+ String query1 = "password=?hard-to-find"; // Noncompliant
String query1_1 = "password=???"; // Compliant
// Password starting with "\"" are ignored
String query7 = "\"password=\""; // Compliant
- // Password starting with ":" are ignored
- String query2 = "password=:password"; // Compliant
- String query3 = "password=:param"; // Compliant
+ // Password starting with ":" are reported
+ String query2 = "password=:password"; // Noncompliant
+ String query3 = "password=:param"; // Noncompliant
// Password containing "%s" are ignored
String query5 = "password=%s"; // Compliant
String query6 = "password=\"%s\""; // Compliant
// Password shorter than 2 characters are ignored
String query1_2 = "password=X"; // Compliant
- // "anonymous" is explicitly ignored
- String query1_3 = "password=anonymous"; // Compliant
+ // "anonymous" is not explicitly ignored any more
+ String query1_3 = "password=anonymous"; // Noncompliant
// Not hardcoded
String query4 = "password='" + pwd + "'"; // Compliant
@@ -60,22 +63,25 @@ private void a(char[] pwd, String var) throws SQLException {
// Password are correctly extracted
String query10 = "password=something&user=user"; // Noncompliant
- String query11 = "password=anonymous&user=user"; // Compliant, the password is the excluded "anonymous" and not "anonymous&user=user"
- String query17 = "password=anonymous,user=user"; // Compliant
- String query18 = "password=anonymous|user=user"; // Compliant
- String query12 = "password=anonymous user=user"; // Compliant
- String query121 = "password=anonymous;user=user"; // Compliant
- String query122 = "password=anonymous#user=user"; // Compliant
- String query13 = "password=anonymous\tuser=user"; // Compliant
- String query14 = "password=anonymous\nuser=user"; // Compliant
+ // "anonymous" is not explicitly ignored any more
+ String query11 = "password=anonymous&user=user"; // Noncompliant
+ String query17 = "password=anonymous,user=user"; // Noncompliant
+ String query18 = "password=anonymous|user=user"; // Noncompliant
+ String query12 = "password=anonymous user=user"; // Noncompliant
+ String query121 = "password=anonymous;user=user"; // Noncompliant
+ String query122 = "password=anonymous#user=user"; // Noncompliant
+ String query13 = "password=anonymous\tuser=user"; // Noncompliant
+ String query14 = "password=anonymous\nuser=user"; // Noncompliant
String query15 = "password=something&user=user%s"; // Noncompliant
- String query16 = "passwordProtected password=:notAPassword"; // Compliant, the password is starting with ":" and therefore excluded
+ // Password starting with ":" are reported
+ String query16 = "passwordProtected password=:notAPassword"; // Noncompliant
// ========== 1.2 Urls ==========
- // No exclusion is made when the password if found in an url
+ // Exclusions also apply when the password if found in an url
String[] urls = {
- "http://user:123456@server.com/path", // Noncompliant {{Review this hard-coded URL, which may contain a password.}}
-// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ "http://user:123456@server.com/path", // Compliant, fake value filter
+ "http://user:xvxf6_gaa@server.com/path", // Noncompliant {{Review this hard-coded URL, which may contain a password.}}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
"ftp://anonymous:anonymous@wustl.edu", // OK, user == password
"ftp://:anonymous@wustl.edu", // Noncompliant
"http://admin:admin@server.com/path", // OK, user == password
@@ -83,7 +89,8 @@ private void a(char[] pwd, String var) throws SQLException {
"http://user@server.com/path", // OK, no password
"https://server:80/path", // OK, no user and password
"http://server.com/path", // OK, no user and password
- "http://:123456@server.com/path", // Noncompliant
+ "http://:123456@server.com/path", // Compliant, fake value filter
+ "http://:xvxf6_gaa@server.com/path", // Noncompliant
"HTTPS://:token0932448209@server.com", // Noncompliant
"https://invalid::url::format",
"too-long-url-scheme://user:123456@server.com",
@@ -91,25 +98,29 @@ private void a(char[] pwd, String var) throws SQLException {
// ========== 2. Variable declaration ==========
// The variable name should contain a password word
- final String MY_PASSWORD = "1234"; // Noncompliant
- String variableNameWithPasswordInIt = "xxx"; // Noncompliant {{'Password' detected in this expression, review this potentially hard-coded password.}}
-// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- String variableNameWithPassphraseInIt = "xxx"; // Noncompliant {{'Passphrase' detected in this expression, review this potentially hard-coded password.}}
-// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- String variableNameWithPasswdInIt = "xxx"; // Noncompliant {{'Passwd' detected in this expression, review this potentially hard-coded password.}}
-// ^^^^^^^^^^^^^^^^^^^^^^^^^^
- String variableNameWithPwdInIt = "xxx"; // Noncompliant {{'Pwd' detected in this expression, review this potentially hard-coded password.}}
-// ^^^^^^^^^^^^^^^^^^^^^^^
+ final String MY_PASSWORD = "1234"; // Compliant, fake value filter
+ final String MY_PASSWORD_2 = "xvxf6_gaa"; // Noncompliant
+ String variableNameWithPasswordInIt = "1234"; // Compliant, fake value filter
+ String variableNameWithPasswordInIt2 = "xvxf6_gaa"; // Noncompliant {{'Password' detected in this expression, review this potentially hard-coded password.}}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ String variableNameWithPassphraseInIt = "xxx"; // Compliant, short value filter
+ String variableNameWithPassphraseInIt2 = "xvxf6_gaa"; // Noncompliant {{'Passphrase' detected in this expression, review this potentially hard-coded password.}}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ String variableNameWithPasswdInIt = "xxx"; // Compliant, short value filter
+ String variableNameWithPasswdInIt2 = "xvxf6_gaa"; // Noncompliant {{'Passwd' detected in this expression, review this potentially hard-coded password.}}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ String variableNameWithPwdInIt = "xxx"; // Compliant, short value filter
+ String variableNameWithPwdInIt2 = "xvxf6_gaa"; // Noncompliant {{'Pwd' detected in this expression, review this potentially hard-coded password.}}
+// ^^^^^^^^^^^^^^^^^^^^^^^^
String passwordToString = "SuperSecure".toString(); // Compliant, FN, but will be reported when we remove "toString()"
// Same constraints when "toCharArray" is called on the password
char[] passwordToChar = "SuperSecure".toCharArray(); // Noncompliant
// ^^^^^^^^^^^^^^
- // Password with less than 2 characters are ignored
- String variableNameWithPasswordInItEmpty = "";
- String variableNameWithPasswordInItOneChar = "X";
+ // Short passwords are ignored
+ String variableNameWithPasswordInItEmpty = ""; // Compliant
+ String variableNameWithPasswordInItOneChar = "X"; // Compliant
char[] smallPasswordToChar = "x".toCharArray(); // Compliant
- // "anonymous" is explicitly ignored
- String variableNameWithPasswordInItAnonymous = "anonymous";
+
// When the password contains a password word, we consider it as constant used to avoid duplicated string
String passwordConst = "Password"; // Compliant
String pwds = "pwd"; // Compliant
@@ -131,50 +142,58 @@ private void a(char[] pwd, String var) throws SQLException {
// ========== 3. Assignment ==========
// The variable name should contain a password word
- fieldNameWithPasswordInIt = "xx"; // Noncompliant {{'Password' detected in this expression, review this potentially hard-coded password.}}
+
+ fieldNameWithPasswordInIt = "xx"; // Compliant, short value filter
+ fieldNameWithPasswordInIt = "xvxf6_gaa"; // Noncompliant {{'Password' detected in this expression, review this potentially hard-coded password.}}
// ^^^^^^^^^^^^^^^^^^^^^^^^^
- this.fieldNameWithPasswordInIt = "xx"; // Noncompliant
- // Password with less than 2 characters are ignored
+ this.fieldNameWithPasswordInIt = "xx"; // Compliant, short value filter
+ this.fieldNameWithPasswordInIt = "xvxf6_gaa"; // Noncompliant
+ // Short password are ignored
fieldNameWithPasswordInIt = "X";
- // "anonymous" is explicitly ignored
- fieldNameWithPasswordInIt = "anonymous";
+ // "anonymous" is not explicitly ignored any more
+ fieldNameWithPasswordInIt = "anonymous"; // Noncompliant
// Not a hardcoded password
fieldNameWithPasswordInIt = retrievePassword();
this.fieldNameWithPasswordInIt = retrievePassword();
// Not a password name
variable1 = "xx";
// Same constraint when "toCharArray" is called on the password
- char[] passphrase = "whatever".toCharArray(); // Noncompliant
- passphrase = "whatever".toCharArray(); // Noncompliant
+ char[] passphrase = "whatever".toCharArray(); // Compliant, fake value filter
+ passphrase = "xvxf6_gaa".toCharArray(); // Noncompliant
+ passphrase = "whatever".toCharArray(); // Compliant, fake value filter
+ passphrase = "xvxf6_gaa".toCharArray(); // Noncompliant
passphrase = PASSED.toCharArray(); // Noncompliant
passphrase = "".toCharArray();
passphrase = "X".toCharArray();
- passphrase = "anonymous".toCharArray();
- // Unlike variable declaration, when the password contains a password word, it is not a constant, we still report an issue.
- fieldNameWithPasswordInIt = "password"; // Noncompliant
+ // Contains a fake password keyword: password
+ fieldNameWithPasswordInIt = "password"; // Compliant
// ========== 4. Method invocations ==========
// ========== 4.1 Equals ==========
// When one side of the equals contains a password word, report an issue
- String password = "123"; // Noncompliant
- if(password.equals("whatever")) { // Noncompliant
-// ^^^^^^^^
+ String password = "123"; // Compliant, short value filter
+ if(password.equals("whatever")) { // Compliant, fake value filter
+
+ }
+ String password2 = "xvxf6_gaa"; // Noncompliant
+ if(password2.equals("xvxf6_gaa")) { // Noncompliant
+// ^^^^^^^^^
}
- if("whatever".equals(password)) { // Noncompliant
-// ^^^^^^^^
+ if("whatever".equals(password)) { // Compliant, fake value filter
+
+ }
+ if("xvxf6_gaa".equals(password)) { // Noncompliant
+// ^^^^^^^^
}
if(PASSED.equals(password)) { // Noncompliant
}
- // Password with less than 2 characters are ignored
+ // Short password are ignored
if(password.equals("X")) {
}
if(password.equals("")) {
}
if("".equals(password)) {
}
- // "anonymous" is explicitly ignored
- if(password.equals("anonymous")) {
- }
// When the actual password contains a password word, we don't report an issue
if(password.equals("password")) {
}
@@ -197,19 +216,23 @@ private void a(char[] pwd, String var) throws SQLException {
conn = DriverManager.getConnection("jdbc:mysql://xxx/", "root", PASSED); // Compliant, handled by S6437
conn = DriverManager.getConnection("jdbc:mysql://xxx/");
// Password not set as argument, but it is still detected in the string itself is detected thanks to (1.)
- conn = DriverManager.getConnection("jdbc:db2://myhost:5021/mydb:user=dbadm;password=foo"); // Noncompliant
-// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ conn = DriverManager.getConnection("jdbc:db2://myhost:5021/mydb:user=dbadm;password=foo"); // Compliant, short value filter
+ conn = DriverManager.getConnection("jdbc:db2://myhost:5021/mydb:user=dbadm;password=xvxf6_gaa"); // Noncompliant
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// ========== 4.3 Setting password ==========
// When a method call has two arguments potentially containing String, we report an issue the same way we would with a variable declaration
A myA = new A();
- myA.setProperty("password", "xxxxx"); // Noncompliant
- myA.setProperty("passwd", "xxxxx"); // Noncompliant
- myA.setProperty("pwd", "xxxxx"); // Noncompliant
- // Password with less than 2 characters are ignored
+ myA.setProperty("password", "xxxxx"); /// Compliant, short value filter
+ myA.setProperty("password", "xvxf6_gaa"); // Noncompliant
+ myA.setProperty("passwd", "xxxxx"); // Compliant, short value filter
+ myA.setProperty("passwd", "xvxf6_gaa"); // Noncompliant
+ myA.setProperty("pwd", "xxxxx"); // Compliant, short value filter
+ myA.setProperty("pwd", "xvxf6_gaa"); // Noncompliant
+ // Short password are ignored
myA.setProperty("pwd", "X");
- // "anonymous" is explicitly ignored
- myA.setProperty("pwd", "anonymous");
+ // "anonymous" is not explicitly ignored any more
+ myA.setProperty("pwd", "anonymous"); // Noncompliant
// Not hardcoded
myA.setProperty("password", new Object());
// We only consider the second argument as containing a password
@@ -220,19 +243,23 @@ private void a(char[] pwd, String var) throws SQLException {
// Other test cases
myA.setProperty(12, "xxxxx");
myA.setProperty(new Object(), new Object());
- myA.setProperty("something", "else").setProperty("password", "xxxxx"); // Noncompliant
+ myA.setProperty("something", "else").setProperty("password", "xxxxx"); // Compliant, short value filter
+ myA.setProperty("something", "else").setProperty("password", "xvxf6_gaa"); // Noncompliant
// ^^^^^^^^^^^
// Same for code not user defined
java.util.Properties props = new java.util.Properties();
- props.put(Context.SECURITY_CREDENTIALS, "1234"); // Noncompliant
+ props.put(Context.SECURITY_CREDENTIALS, "1234"); // Compliant, short value filter
+ props.put(Context.SECURITY_CREDENTIALS, "xvxf6_gaa"); // Noncompliant
// ^^^
- props.put("java.naming.security.credentials", "1234"); // Noncompliant
+ props.put("java.naming.security.credentials", "1234"); // Compliant, short value filter
+ props.put("java.naming.security.credentials", "xvxf6_gaa"); // Noncompliant
props.put("password", "whateverpassword"); // Compliant
java.util.Hashtable env = new java.util.Hashtable<>();
- env.put(Context.SECURITY_CREDENTIALS, "1234"); // Noncompliant
- env.put("", "1234");
+ env.put(Context.SECURITY_CREDENTIALS, "1234"); // Compliant, short value filter
+ env.put(Context.SECURITY_CREDENTIALS, "xvxf6_gaa"); // Noncompliant
+ env.put("", "xvxf6_gaa");
env.put(Context.SECURITY_CREDENTIALS, "");
env.put("password", "whateverpassword"); // Compliant
@@ -242,6 +269,7 @@ private void a(char[] pwd, String var) throws SQLException {
// ========== 5. Constructors ==========
// Second argument of "PasswordAuthentication" is setting explicitly a password
PasswordAuthentication pa;
+
pa = new PasswordAuthentication("userName", "1234".toCharArray()); // Compliant, handled by S6437
// Not hardcoded
pa = new PasswordAuthentication("userName", var.toCharArray());
diff --git a/java-checks-test-sources/default/src/main/java/checks/HardCodedSecretCheckCustom.java b/java-checks-test-sources/default/src/main/java/checks/HardCodedSecretCheckCustom.java
index de3033ae536..3ecd72fac3c 100644
--- a/java-checks-test-sources/default/src/main/java/checks/HardCodedSecretCheckCustom.java
+++ b/java-checks-test-sources/default/src/main/java/checks/HardCodedSecretCheckCustom.java
@@ -2,8 +2,9 @@
class HardCodedSecretCheckCustom {
private void test() {
- String variable2 = "login=a&secret=aaaaaaaaaaaaaabcdefg"; // Compliant
- String variable5 = "login=a&marmalade=aaaaaaaaaaaaaabcdefg"; // Noncompliant {{'marmalade' detected in this expression, review this potentially hard-coded secret.}}
-// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ String variable2 = "login=a&secret=sk_live_xf2fh0Hu3LqXlqqUg2DEWhEz"; // Compliant
+ String variable5 = "login=a&marmalade=aaaaaaaaaaaaaabcdefg"; // Compliant, fake value filter
+ String variable5_2 = "login=a&marmalade=sk_live_xf2fh0Hu3LqXlqqUg2DEWhEz"; // Noncompliant {{'marmalade' detected in this expression, review this potentially hard-coded secret.}}
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
}
diff --git a/java-checks-test-sources/default/src/main/java/checks/HardCodedSecretCheckSample.java b/java-checks-test-sources/default/src/main/java/checks/HardCodedSecretCheckSample.java
index 366b054468e..a05cea71d25 100644
--- a/java-checks-test-sources/default/src/main/java/checks/HardCodedSecretCheckSample.java
+++ b/java-checks-test-sources/default/src/main/java/checks/HardCodedSecretCheckSample.java
@@ -15,43 +15,43 @@ class HardCodedSecretCheckSample {
String fieldNameWithSecretInIt = retrieveSecret();
- private static final String PASSED = "abcdefghijklmnopqrs"; // compliant nothing to do with secrets
+ private static final String PASSED = "bacdefghijklmnopqrs"; // compliant nothing to do with secrets
private static final String EMPTY = "";
private void a(char[] secret, String var) throws SQLException {
// ========== 1. String literal ==========
// The variable name does not influence the issue, only the string is considered.
String variable1 = "blabla";
- String variable2 = "login=a&secret=abcdefghijklmnopqrs"; // Noncompliant {{'secret' detected in this expression, review this potentially hard-coded secret.}}
+ String variable2 = "login=a&secret=bacdefghijklmnopqrs"; // Noncompliant {{'secret' detected in this expression, review this potentially hard-coded secret.}}
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- String variable3 = "login=a&token=abcdefghijklmnopqrs"; // Noncompliant
- String variable4 = "login=a&api_key=abcdefghijklmnopqrs"; // Noncompliant
- String variable5 = "login=a&api.key=abcdefghijklmnopqrs"; // Noncompliant
- String variable6 = "login=a&api-key=abcdefghijklmnopqrs"; // Noncompliant
- String variable7 = "login=a&credential=abcdefghijklmnopqrs"; // Noncompliant
- String variable8 = "login=a&auth=abcdefghijklmnopqrs"; // Noncompliant
+ String variable3 = "login=a&token=bacdefghijklmnopqrs"; // Noncompliant
+ String variable4 = "login=a&api_key=bacdefghijklmnopqrs"; // Noncompliant
+ String variable5 = "login=a&api.key=bacdefghijklmnopqrs"; // Noncompliant
+ String variable6 = "login=a&api-key=bacdefghijklmnopqrs"; // Noncompliant
+ String variable7 = "login=a&credential=bacdefghijklmnopqrs"; // Noncompliant
+ String variable8 = "login=a&auth=bacdefghijklmnopqrs"; // Noncompliant
String variable9 = "login=a&secret=";
String variableA = "login=a&secret= ";
- String variableB = "secret=&login=abcdefghijklmnopqrs"; // Compliant
+ String variableB = "secret=&login=bacdefghijklmnopqrs"; // Compliant
String variableC = "Okapi-key=42, Okapia Johnstoni, Forest/Zebra Giraffe"; // Compliant
- String variableD = "gran-papi-key=Known by everybody in the world like PWD123456"; // Compliant
+ String variableD = "gran-papi-key=Known by everybody in the world like PWD213456"; // Compliant
String variableE = """
login=a
- secret=abcdefghijklmnopqrs
+ secret=bacdefghijklmnopqrs
"""; // false-negative, we should support text block lines, report precise location inside
String variableF = """
-
-
"""; // false-negative, we should support text block lines and several issues inside
- // Secrets starting with "?", ":", "\"", containing "%s" or with less than 2 characters are ignored
- String query1 = "secret=?abcdefghijklmnopqrs"; // Compliant
+ // Secrets starting with "?", ":", "\"", containing "%s" or with short lenght
+ String query1 = "secret=?bacdefghijklmnopqrs"; // Noncompliant
String query1_1 = "secret=???"; // Compliant
String query1_2 = "secret=X"; // Compliant
String query1_3 = "secret=anonymous"; // Compliant
@@ -62,72 +62,71 @@ private void a(char[] secret, String var) throws SQLException {
String query6 = "secret=\"%s\""; // Compliant
String query7 = "\"secret=\""; // Compliant
- String params1 = "user=admin&secret=Secret0123456789012345678"; // Noncompliant
- String params2 = "secret=no\nuser=admin0123456789"; // Compliant
- String sqlserver1= "pgsql:host=localhost port=5432 dbname=test user=postgres secret=abcdefghijklmnopqrs"; // Noncompliant
- String sqlserver2 = "pgsql:host=localhost port=5432 dbname=test secret=no user=abcdefghijklmnopqrs"; // Compliant
+ String params1 = "user=admin&secret=Secret1023456789021345678"; // Noncompliant
+ String params2 = "secret=no\nuser=admin0213456789"; // Compliant
+ String sqlserver1= "pgsql:host=localhost port=5432 dbname=test user=postgres secret=bacdefghijklmnopqrs"; // Noncompliant
+ String sqlserver2 = "pgsql:host=localhost port=5432 dbname=test secret=no user=bacdefghijklmnopqrs"; // Compliant
// Spaces and & are not included into the token, it shows us the end of the token.
- String params3 = "token=abcdefghijklmnopqrs user=admin"; // Noncompliant
- String params4 = "token=abcdefghijklmnopqrs&user=admin"; // Noncompliant
+ String params3 = "token=bacdefghijklmnopqrs user=admin"; // Noncompliant
+ String params4 = "token=bacdefghijklmnopqrs&user=admin"; // Noncompliant
- String params5 = "token=123456&abcdefghijklmnopqrs"; // Compliant, FN, even if "&" is accepted in a password, it also indicates a cut in a string literal
- String params6 = "token=123456:abcdefghijklmnopqrs"; // Noncompliant
+ String params5 = "token=213456&bacdefghijklmnopqrs"; // Compliant, FN, even if "&" is accepted in a password, it also indicates a cut in a string literal
+ String params6 = "token=213456:bacdefghijklmnopqrs"; // Noncompliant
// URLs are reported by S2068 only.
String[] urls = {
- "http://user:123456@server.com/path", // Compliant
+ "http://user:213456@server.com/path", // Compliant
};
// ========== 2. Variable declaration ==========
// The variable name should contain a secret word
- final String MY_SECRET = "abcdefghijklmnopqrs"; // Noncompliant
- String variableNameWithSecretInIt = "abcdefghijklmnopqrs"; // Noncompliant
+ final String MY_SECRET = "bacdefghijklmnopqrs"; // Noncompliant
+ String variableNameWithSecretInIt = "bacdefghijklmnopqrs"; // Noncompliant
// ^^^^^^^^^^^^^^^^^^^^^^^^^^
- String variableNameWithSecretaryInIt = "abcdefghijklmnopqrs"; // Noncompliant
- String variableNameWithAuthorshipInIt = "abcdefghijklmnopqrs"; // Noncompliant
- String variableNameWithTokenInIt = "abcdefghijklmnopqrs"; // Noncompliant
- String variableNameWithApiKeyInIt = "abcdefghijklmnopqrs"; // Noncompliant
+ String variableNameWithSecretaryInIt = "bacdefghijklmnopqrs"; // Noncompliant
+ String variableNameWithAuthorshipInIt = "bacdefghijklmnopqrs"; // Noncompliant
+ String variableNameWithTokenInIt = "bacdefghijklmnopqrs"; // Noncompliant
+ String variableNameWithApiKeyInIt = "bacdefghijklmnopqrs"; // Noncompliant
// ^^^^^^^^^^^^^^^^^^^^^^^^^^
- String variableNameWithCredentialInIt = "abcdefghijklmnopqrs"; // Noncompliant
+ String variableNameWithCredentialInIt = "bacdefghijklmnopqrs"; // Noncompliant
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- String variableNameWithAuthInIt = "abcdefghijklmnopqrs"; // Noncompliant
+ String variableNameWithAuthInIt = "bacdefghijklmnopqrs"; // Noncompliant
// ^^^^^^^^^^^^^^^^^^^^^^^^
- // Secrets with less than 2 characters, explicitly "anonymous", are ignored
+ // Shtrong strings are ignored
String variableNameWithSecretInItEmpty = "";
String variableNameWithSecretInItOneChar = "X";
- String variableNameWithSecretInItAnonymous = "anonymous";
String otherVariableNameWithAuthInIt;
// Secret containing words and random characters should be filtered
String secret001 = "sk_live_xf2fh0Hu3LqXlqqUg2DEWhEz"; // Noncompliant
String secret002 = "examples/commit/16ad89c4172c259f15bce56e";
- String secret003 = "examples/commit/8e1d746900f5411e9700fea0"; // Noncompliant
+ String secret003 = "examples/commit/8e1d746900f5411e9700fea0"; // Compliant, excluded by the classifier (matches the "example" substring), not by the human-language check
String secret004 = "examples/commit/revision/469001e9700fea0";
String secret005 = "xml/src/main/java/org/xwiki/xml/html/file";
- String secret006 = "abcdefghijklmnop"; // Compliant
- String secret007 = "abcdefghijklmnopq"; // Noncompliant
- String secret008 = "0123456789abcdef0"; // Noncompliant
- String secret009 = "012345678901234567890123456789"; // Noncompliant
- String secret010 = "abcdefghijklmnopabcdefghijkl"; // Noncompliant
- String secret011 = "012345670123456701234567012345";
- String secret012 = "012345678012345678012345678012"; // Noncompliant
- String secret013 = "234.167.076.123";
+ String secret006 = "bacdefghijklmnop"; // Compliant
+ String secret007 = "bacdefghijklmnopq"; // Noncompliant
+ String secret008 = "0213456789bacdef0"; // Noncompliant
+ String secret009 = "021345678902134567890213456789"; // Noncompliant
+ String secret010 = "bacdefghijklmnopbacdefghijkl"; // Noncompliant
+ String secret011 = "021345670213456702134567021345";
+ String secret012 = "021345678021345678021345678012"; // Noncompliant
+ String secret013 = "234.167.076.213";
String ip_secret1 = "bfee:e3e1:9a92:6617:02d5:256a:b87a:fbcc"; // Compliant: ipv6 format
String ip_secret2 = "2001:db8:1::ab9:C0A8:102"; // Compliant: ipv6 format
String ip_secret3 = "::ab9:C0A8:102"; // Compliant: ipv6 format
String secret015 = "org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH";
// Example of Telegram bot token
- String secret016 = "bot123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"; // Noncompliant
+ String secret016 = "bot213456:BAC-DEF2134ghIkl-zyx57W2v1u213ew11"; // Noncompliant
// Secret with "&"
- String secret017 = "012&345678012345678012345&678012"; // Noncompliant
- String secret018 = "&12&345678012345678012345&67801&"; // Noncompliant
+ String secret017 = "012&345678021345678021345&678012"; // Noncompliant
+ String secret018 = "&12&345678021345678021345&67801&"; // Noncompliant
// Don't filter when the secret is containing any of the secret word.
- String secretConst = "Secret_0123456789012345678"; // Noncompliant
- String secrets = "secret_0123456789012345678"; // Noncompliant
- final String SECRET = "Secret_0123456789012345678"; // Noncompliant
+ String secretConst = "Secret_0213456789021345678"; // Noncompliant
+ String secrets = "secret_0213456789021345678"; // Noncompliant
+ final String SECRET = "Secret_0213456789021345678"; // Noncompliant
// Simple constants will be filtered thanks to the entropy check
final String SECRET_INPUT = "[id='secret']"; // Compliant
final String SECRET_PROPERTY = "custom.secret"; // Compliant
@@ -143,44 +142,39 @@ private void a(char[] secret, String var) throws SQLException {
String CA_SECRET = "ca-secret"; // Compliant
String caSecret = CA_SECRET; // Compliant
- // Backslashes are filtered further:
- // \n, \t, \r, \" are excluded
- String secretWithBackSlashes = "abcdefghij\nklmnopqrs"; // Compliant
- String secretWithBackSlashes2 = "abcdefghij\tklmnopqrs"; // Compliant
- String secretWithBackSlashes3 = "abcdefghij\rklmnopqrs"; // Compliant
- String secretWithBackSlashes4 = "abcdefghij\"klmnopqrs"; // Compliant
- // When the secret is starting or ending with a backslash
- String secretWithBackSlashes5 = "\\abcdefghijklmnopqrs"; // Compliant
- String secretWithBackSlashes6 = "abcdefghijklmnopqrs\\"; // Compliant
- // When the secret is starting with =
- String secretWithBackSlashes7 = "=abcdefghijklmnopqrs";
- // = in the middle or end is okay
- String secretWithBackSlashes8 = "abcdefghijklmnopqrs="; // Noncompliant
- String secretWithBackSlashes9 = "abcdefghijklmnopqrs=="; // Noncompliant
- String secretWithBackSlashes10 = "abcdefghij=klmnopqrs"; // Noncompliant
-
- // Only [a-zA-Z0-9_.+/~$-] are accepted as secrets characters
- String OkapiKeyboard = "what a strange QWERTY keyboard for animals"; // Compliant
- String OKAPI_KEYBOARD = "what a strange QWERTY keyboard for animals"; // Compliant
+ // Backslashed, \n, \t, \r, \" not excluded
+ String secretWithBackSlashes = "bacdefghij\nklmnopqrs"; // Noncompliant
+ String secretWithBackSlashes2 = "bacdefghij\tklmnopqrs"; // Noncompliant
+ String secretWithBackSlashes3 = "bacdefghij\rklmnopqrs"; // Noncompliant
+ String secretWithBackSlashes4 = "bacdefghij\"klmnopqrs"; // Noncompliant
+ String secretWithBackSlashes5 = "\\bacdefghijklmnopqrs"; // Noncompliant
+ String secretWithBackSlashes6 = "bacdefghijklmnopqrs\\"; // Noncompliant
+ // Starting or containing =
+ String secretWithBackSlashes7 = "=bacdefghijklmnopqrs"; // Noncompliant
+ String secretWithBackSlashes8 = "bacdefghijklmnopqrs="; // Noncompliant
+ String secretWithBackSlashes9 = "bacdefghijklmnopqrs=="; // Noncompliant
+ String secretWithBackSlashes10 = "bacdefghij=klmnopqrs"; // Noncompliant
+
+ // Long strings but low entropy
+ String OkapiKeyboard = "what a strange keyboard for animals"; // Compliant
+ String OKAPI_KEYBOARD = "what a strange keyboard for animals"; // Compliant
String okApiKeyValue = "Spaces are UNEXPECTED 012 345 678"; // Compliant
String tokenism = "(Queen's Partner's Stored Knowledge is a Minimal Sham)"; // Compliant
- String tokenWithExcludedCharacters2 = "abcdefghij|klmnopqrs"; // Compliant
+ String tokenWithExcludedCharacters2 = "bacdefghij|klmnopqrs"; // Noncompliant
// ========== 3. Assignment ==========
- fieldNameWithSecretInIt = "abcdefghijklmnopqrs"; // Noncompliant
- this.fieldNameWithSecretInIt = "abcdefghijklmnopqrs"; // Noncompliant
- // Secrets with less than 2 chars are explicitly ignored
+ fieldNameWithSecretInIt = "bacdefghijklmnopqrs"; // Noncompliant
+ this.fieldNameWithSecretInIt = "bacdefghijklmnopqrs"; // Noncompliant
+ // Short lenght strings are explicitly ignored
fieldNameWithSecretInIt = "X";
- // "anonymous" is explicitly ignored
- fieldNameWithSecretInIt = "anonymous";
// Not hardcoded
fieldNameWithSecretInIt = retrieveSecret();
this.fieldNameWithSecretInIt = retrieveSecret();
- variable1 = "abcdefghijklmnopqrs";
+ variable1 = "bacdefghijklmnopqrs";
// Same constraints apply to "toCharArray" called on a String
- char[] credential = "abcdefghijklmnopqrs".toCharArray(); // Noncompliant
- credential = "abcdefghijklmnopqrs".toCharArray(); // Noncompliant
+ char[] credential = "bacdefghijklmnopqrs".toCharArray(); // Noncompliant
+ credential = "bacdefghijklmnopqrs".toCharArray(); // Noncompliant
credential = PASSED.toCharArray(); // Noncompliant
credential = "".toCharArray();
credential = "X".toCharArray();
@@ -188,10 +182,10 @@ private void a(char[] secret, String var) throws SQLException {
// ========== 4. Method invocations ==========
// ========== 4.1 Equals ==========
- String auth = "abcdefghijklmnopqrs"; // Noncompliant
- if(auth.equals("abcdefghijklmnopqrs")) { // Noncompliant
+ String auth = "bacdefghijklmnopqrs"; // Noncompliant
+ if(auth.equals("bacdefghijklmnopqrs")) { // Noncompliant
}
- if("abcdefghijklmnopqrs".equals(auth)) { // Noncompliant
+ if("bacdefghijklmnopqrs".equals(auth)) { // Noncompliant
}
if(PASSED.equals(auth)) { // Noncompliant
}
@@ -203,7 +197,7 @@ private void a(char[] secret, String var) throws SQLException {
}
if("password".equals(auth)) {
}
- if(auth.equals("password-1234")) {
+ if(auth.equals("password-2134")) {
}
if(auth.equals("")) {
}
@@ -222,21 +216,21 @@ private void a(char[] secret, String var) throws SQLException {
// ========== 4.2 Setting secrets ==========
// When a method call has two arguments potentially containing String, we report an issue the same way we would with a variable declaration
A myA = new A();
- myA.setProperty("secret", "abcdefghijklmnopqrs"); // Noncompliant
- myA.setProperty("secretary", "abcdefghijklmnopqrs"); // Compliant
- myA.setProperty("token", "abcdefghijklmnopqrs"); // Noncompliant
- myA.setProperty("tokenization", "abcdefghijklmnopqrs"); // Compliant
- myA.setProperty("api-key", "abcdefghijklmnopqrs"); // Noncompliant
- myA.setProperty("okapi-keyboard", "abcdefghijklmnopqrs"); // Compliant
+ myA.setProperty("secret", "bacdefghijklmnopqrs"); // Noncompliant
+ myA.setProperty("secretary", "bacdefghijklmnopqrs"); // Compliant
+ myA.setProperty("token", "bacdefghijklmnopqrs"); // Noncompliant
+ myA.setProperty("tokenization", "bacdefghijklmnopqrs"); // Compliant
+ myA.setProperty("api-key", "bacdefghijklmnopqrs"); // Noncompliant
+ myA.setProperty("okapi-keyboard", "bacdefghijklmnopqrs"); // Compliant
myA.setProperty("secret", "X");
myA.setProperty("secret", "anonymous");
myA.setProperty("secret", new Object());
- myA.setProperty("abcdefghijklmnopqrs", "secret");
- myA.setProperty(12, "abcdefghijklmnopqrs");
+ myA.setProperty("bacdefghijklmnopqrs", "secret");
+ myA.setProperty(12, "bacdefghijklmnopqrs");
myA.setProperty(new Object(), new Object());
myA.setProperty("secret", "secret"); // Compliant
myA.setProperty("secret", "auth"); // Compliant
- myA.setProperty("something", "else").setProperty("secret", "abcdefghijklmnopqrs"); // Noncompliant
+ myA.setProperty("something", "else").setProperty("secret", "bacdefghijklmnopqrs"); // Noncompliant
// ^^^^^^^^^^^
}
diff --git a/java-checks/pom.xml b/java-checks/pom.xml
index 130a5762dc5..8183c6303ba 100644
--- a/java-checks/pom.xml
+++ b/java-checks/pom.xml
@@ -66,6 +66,10 @@
org.sonarsource.analyzer-commons
sonar-analyzer-recognizers
+
+ org.sonarsource.analyzer-commons
+ sonar-analyzer-commons
+
org.apache.commons
commons-lang3
diff --git a/java-checks/src/main/java/org/sonar/java/checks/AbstractHardCodedCredentialChecker.java b/java-checks/src/main/java/org/sonar/java/checks/AbstractHardCodedCredentialChecker.java
index 14e33e4b38d..6c582d6f1f8 100644
--- a/java-checks/src/main/java/org/sonar/java/checks/AbstractHardCodedCredentialChecker.java
+++ b/java-checks/src/main/java/org/sonar/java/checks/AbstractHardCodedCredentialChecker.java
@@ -16,10 +16,8 @@
*/
package org.sonar.java.checks;
-import java.util.Collections;
import java.util.List;
import java.util.Optional;
-import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;
@@ -36,10 +34,10 @@
import org.sonar.plugins.java.api.tree.MethodInvocationTree;
import org.sonar.plugins.java.api.tree.Tree;
import org.sonar.plugins.java.api.tree.VariableTree;
+import org.sonarsource.analyzer.commons.appsec.SecretClassifier;
public abstract class AbstractHardCodedCredentialChecker extends IssuableSubscriptionVisitor {
- private static final Set ALLOW_LIST = Collections.singleton("anonymous");
private static final String JAVA_LANG_STRING = "java.lang.String";
private static final String JAVA_LANG_OBJECT = "java.lang.Object";
@@ -58,8 +56,6 @@ public abstract class AbstractHardCodedCredentialChecker extends IssuableSubscri
private List variablePatterns = null;
private List literalPatterns = null;
- private static final int MINIMUM_CREDENTIAL_LENGTH = 2;
-
protected abstract String getCredentialWords();
/**
@@ -145,7 +141,7 @@ protected void handleStringLiteral(LiteralTree tree) {
literalPatterns().map(pattern -> pattern.matcher(cleanedLiteral))
// contains "pwd=" or similar
.filter(Matcher::find)
- .filter(matcher -> !isExcludedLiteral(matcher.group(2)))
+ .filter(matcher -> isPotentialCredential(matcher.group(2)))
.findAny()
.ifPresent(matcher -> report(tree, matcher.group(1)));
}
@@ -156,16 +152,12 @@ private boolean isPartOfConstantCredentialDeclaration(LiteralTree tree) {
return parent != null && parent.is(Tree.Kind.VARIABLE) && isCredentialVariableName(((VariableTree) parent).simpleName()).isPresent();
}
- protected boolean isPotentialCredential(String literal) {
- String trimmed = literal.trim();
- return trimmed.length() >= MINIMUM_CREDENTIAL_LENGTH && !ALLOW_LIST.contains(trimmed);
+ protected static boolean isKnownNonSecret(String candidate) {
+ return SecretClassifier.isKnownNonSecret(candidate);
}
- private boolean isExcludedLiteral(String followingString) {
- return !isPotentialCredential(followingString)
- || followingString.startsWith("?")
- || followingString.startsWith(":")
- || followingString.contains("%s");
+ protected boolean isPotentialCredential(String literal) {
+ return !isKnownNonSecret(literal.trim());
}
protected void handleVariable(VariableTree tree) {
diff --git a/java-checks/src/main/java/org/sonar/java/checks/HardCodedPasswordCheck.java b/java-checks/src/main/java/org/sonar/java/checks/HardCodedPasswordCheck.java
index cdc842b80e1..27efcee8388 100644
--- a/java-checks/src/main/java/org/sonar/java/checks/HardCodedPasswordCheck.java
+++ b/java-checks/src/main/java/org/sonar/java/checks/HardCodedPasswordCheck.java
@@ -20,6 +20,7 @@
import java.net.URL;
import java.util.Arrays;
import java.util.List;
+import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.sonar.check.Rule;
@@ -75,26 +76,31 @@ public void visitNode(Tree tree) {
@Override
protected void handleStringLiteral(LiteralTree tree) {
String cleanedLiteral = LiteralUtils.trimQuotes(tree.value());
- if (isURLWithCredentials(cleanedLiteral)) {
- reportIssue(tree, "Review this hard-coded URL, which may contain a password.");
+ Optional urlPassword = extractURLPassword(cleanedLiteral);
+ if (urlPassword.isPresent()) {
+ if (!isKnownNonSecret(urlPassword.get())) {
+ reportIssue(tree, "Review this hard-coded URL, which may contain a password.");
+ }
} else {
super.handleStringLiteral(tree);
}
}
- private static boolean isURLWithCredentials(String stringLiteral) {
- if (URL_PREFIX.matcher(stringLiteral).find()) {
+ private static Optional extractURLPassword(String url) {
+ if (URL_PREFIX.matcher(url).find()) {
try {
- String userInfo = new URL(stringLiteral).getUserInfo();
+ String userInfo = new URL(url).getUserInfo();
if (userInfo != null) {
Matcher matcher = NON_EMPTY_URL_CREDENTIAL.matcher(userInfo);
- return matcher.matches() && !matcher.group("user").equals(matcher.group("password"));
+ if (matcher.matches() && !matcher.group("user").equals(matcher.group("password"))) {
+ return Optional.of(matcher.group("password"));
+ }
}
} catch (MalformedURLException e) {
- // ignore, stringLiteral is not a valid URL
+ // ignore, url is not a valid URL
}
}
- return false;
+ return Optional.empty();
}
private void handleMethodInvocation(MethodInvocationTree mit) {
diff --git a/java-checks/src/main/java/org/sonar/java/checks/HardCodedSecretCheck.java b/java-checks/src/main/java/org/sonar/java/checks/HardCodedSecretCheck.java
index fad6dd33138..19cef5bfb1e 100644
--- a/java-checks/src/main/java/org/sonar/java/checks/HardCodedSecretCheck.java
+++ b/java-checks/src/main/java/org/sonar/java/checks/HardCodedSecretCheck.java
@@ -39,12 +39,7 @@ public class HardCodedSecretCheck extends AbstractHardCodedCredentialChecker {
private static final String DEFAULT_SECRET_WORDS = "api[_.-]?key,auth,credential,secret,token";
private static final String DEFAULT_RANDOMNESS_SENSIBILITY= "5.0";
- private static final int MINIMUM_CREDENTIAL_LENGTH = 17;
- private static final String FIRST_ACCEPTED_CHARACTER = "[\\w.+/~$:&-]";
- private static final String FOLLOWING_ACCEPTED_CHARACTER = "[=\\w.+/~$:&-]";
- private static final Pattern SECRET_PATTERN =
- Pattern.compile(FIRST_ACCEPTED_CHARACTER + "(" + FOLLOWING_ACCEPTED_CHARACTER + "|\\\\\\\\" + FOLLOWING_ACCEPTED_CHARACTER + ")++");
private static final Pattern IPV_6_PATTERN = Pattern.compile(IP_V6_ALONE);
private RandomnessDetector randomnessDetector;
@@ -102,11 +97,9 @@ private void handleMethodInvocation(MethodInvocationTree mit) {
@Override
protected boolean isPotentialCredential(String literal) {
- if (literal.length() < MINIMUM_CREDENTIAL_LENGTH || !SECRET_PATTERN.matcher(literal).matches()) {
- return false;
- }
return getRandomnessDetector().isRandom(literal)
- && isNotIpV6(literal);
+ && isNotIpV6(literal)
+ && !isKnownNonSecret(literal);
}
private RandomnessDetector getRandomnessDetector() {
diff --git a/pom.xml b/pom.xml
index 5ac45155d71..58b078af2e5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -96,7 +96,7 @@
13.0.0.3026
11.3.0.85510
its/**,java-checks-test-sources/**
- 2.22.0.4796
+ 2.25.0.4954
6.1.0.3962
1.25.1.3886
-Xmx512m