Skip to content

Commit 23ddb2d

Browse files
Implemented mask cmd in java wrapper
1 parent 82d6c66 commit 23ddb2d

File tree

6 files changed

+335
-0
lines changed

6 files changed

+335
-0
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.checkmarx.ast.mask;
2+
3+
import com.checkmarx.ast.utils.JsonParser;
4+
import com.fasterxml.jackson.annotation.JsonCreator;
5+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
6+
import com.fasterxml.jackson.annotation.JsonInclude;
7+
import com.fasterxml.jackson.annotation.JsonProperty;
8+
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
9+
import com.fasterxml.jackson.databind.type.TypeFactory;
10+
import lombok.EqualsAndHashCode;
11+
import lombok.ToString;
12+
import lombok.Value;
13+
14+
import java.util.List;
15+
16+
@Value
17+
@EqualsAndHashCode()
18+
@JsonDeserialize()
19+
@ToString(callSuper = true)
20+
@JsonInclude(JsonInclude.Include.NON_NULL)
21+
@JsonIgnoreProperties(ignoreUnknown = true)
22+
public class MaskResult {
23+
24+
List<MaskedSecret> maskedSecrets;
25+
String maskedFile;
26+
27+
@JsonCreator
28+
public MaskResult(@JsonProperty("maskedSecrets") List<MaskedSecret> maskedSecrets,
29+
@JsonProperty("maskedFile") String maskedFile) {
30+
this.maskedSecrets = maskedSecrets;
31+
this.maskedFile = maskedFile;
32+
}
33+
34+
public static MaskResult fromLine(String line) {
35+
return JsonParser.parse(line, TypeFactory.defaultInstance().constructType(MaskResult.class));
36+
}
37+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.checkmarx.ast.mask;
2+
3+
import com.fasterxml.jackson.annotation.JsonCreator;
4+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
5+
import com.fasterxml.jackson.annotation.JsonInclude;
6+
import com.fasterxml.jackson.annotation.JsonProperty;
7+
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
8+
import lombok.EqualsAndHashCode;
9+
import lombok.ToString;
10+
import lombok.Value;
11+
12+
@Value
13+
@EqualsAndHashCode()
14+
@JsonDeserialize()
15+
@ToString(callSuper = true)
16+
@JsonInclude(JsonInclude.Include.NON_NULL)
17+
@JsonIgnoreProperties(ignoreUnknown = true)
18+
public class MaskedSecret {
19+
20+
String masked;
21+
String secret;
22+
int line;
23+
24+
@JsonCreator
25+
public MaskedSecret(@JsonProperty("masked") String masked,
26+
@JsonProperty("secret") String secret,
27+
@JsonProperty("line") int line) {
28+
this.masked = masked;
29+
this.secret = secret;
30+
this.line = line;
31+
}
32+
}

src/main/java/com/checkmarx/ast/wrapper/CxConstants.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,6 @@ public final class CxConstants {
8080
static final String SUB_CMD_IAC_REALTIME = "iac-realtime";
8181
static final String SUB_CMD_SECRETS_REALTIME = "secrets-realtime";
8282
static final String SUB_CMD_CONTAINERS_REALTIME = "containers-realtime";
83+
static final String SUB_CMD_MASK = "mask";
84+
static final String RESULT_FILE = "--result-file";
8385
}

src/main/java/com/checkmarx/ast/wrapper/CxWrapper.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.checkmarx.ast.codebashing.CodeBashing;
55
import com.checkmarx.ast.kicsRealtimeResults.KicsRealtimeResults;
66
import com.checkmarx.ast.learnMore.LearnMore;
7+
import com.checkmarx.ast.mask.MaskResult;
78
import com.checkmarx.ast.ossrealtime.OssRealtimeResults;
89
import com.checkmarx.ast.secretsrealtime.SecretsRealtimeResults;
910

@@ -522,6 +523,17 @@ public List<TenantSetting> tenantSettings() throws CxException, IOException, Int
522523
return Execution.executeCommand(withConfigArguments(arguments), logger, TenantSetting::listFromLine);
523524
}
524525

526+
public MaskResult maskSecrets(@NonNull String filePath) throws CxException, IOException, InterruptedException {
527+
List<String> arguments = new ArrayList<>();
528+
529+
arguments.add(CxConstants.CMD_UTILS);
530+
arguments.add(CxConstants.SUB_CMD_MASK);
531+
arguments.add(CxConstants.RESULT_FILE);
532+
arguments.add(filePath);
533+
534+
return Execution.executeCommand(withConfigArguments(arguments), logger, MaskResult::fromLine);
535+
}
536+
525537
private int getIndexOfBfLNode(List<Node> bflNodes, List<Node> resultNodes) {
526538

527539
int bflNodeNotFound = -1;
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package com.checkmarx.ast;
2+
3+
import com.checkmarx.ast.mask.MaskResult;
4+
import com.checkmarx.ast.mask.MaskedSecret;
5+
import com.fasterxml.jackson.databind.ObjectMapper;
6+
import org.junit.jupiter.api.Assertions;
7+
import org.junit.jupiter.api.Test;
8+
9+
public class MaskTest extends BaseTest {
10+
11+
private static final String RESULTS_FILE = "target/test-classes/results.json";
12+
private static final String SECRETS_REALTIME_FILE = "target/test-classes/Secrets-realtime.json";
13+
14+
@Test
15+
void testMaskSecretsWithFileContainingSecrets() throws Exception {
16+
// Tests CLI execution with file containing actual secrets and validates masking behavior
17+
MaskResult result = wrapper.maskSecrets(SECRETS_REALTIME_FILE);
18+
19+
Assertions.assertNotNull(result);
20+
Assertions.assertNotNull(result.getMaskedFile());
21+
Assertions.assertNotNull(result.getMaskedSecrets());
22+
Assertions.assertFalse(result.getMaskedSecrets().isEmpty());
23+
24+
MaskedSecret secret = result.getMaskedSecrets().get(0);
25+
Assertions.assertNotNull(secret.getMasked());
26+
Assertions.assertNotNull(secret.getSecret());
27+
Assertions.assertEquals(5, secret.getLine());
28+
Assertions.assertTrue(secret.getMasked().contains("<masked>") || secret.getMasked().contains("\\u003cmasked\\u003e"));
29+
Assertions.assertTrue(secret.getSecret().contains("-----BEGIN RSA PRIVATE KEY-----"));
30+
Assertions.assertTrue(secret.getSecret().length() > secret.getMasked().length());
31+
}
32+
33+
@Test
34+
void testMaskSecretsWithFileContainingNoSecrets() throws Exception {
35+
// Tests CLI execution with file containing no secrets
36+
MaskResult result = wrapper.maskSecrets(RESULTS_FILE);
37+
38+
Assertions.assertNotNull(result);
39+
Assertions.assertNotNull(result.getMaskedFile());
40+
Assertions.assertFalse(result.getMaskedFile().isEmpty());
41+
}
42+
43+
@Test
44+
void testMaskSecretsErrorHandling() {
45+
// Tests CLI error handling for invalid inputs
46+
Assertions.assertThrows(Exception.class, () -> wrapper.maskSecrets(null));
47+
Assertions.assertThrows(Exception.class, () -> wrapper.maskSecrets("non-existent-file.json"));
48+
Assertions.assertDoesNotThrow(() -> wrapper.maskSecrets(RESULTS_FILE));
49+
}
50+
51+
@Test
52+
void testMaskSecretsResponseParsing() throws Exception {
53+
// Tests CLI response structure and JSON parsing functionality
54+
MaskResult result = wrapper.maskSecrets(SECRETS_REALTIME_FILE);
55+
56+
Assertions.assertNotNull(result);
57+
Assertions.assertNotNull(result.getMaskedSecrets());
58+
Assertions.assertFalse(result.getMaskedSecrets().isEmpty());
59+
60+
MaskedSecret secret = result.getMaskedSecrets().get(0);
61+
Assertions.assertNotNull(secret.getMasked());
62+
Assertions.assertNotNull(secret.getSecret());
63+
Assertions.assertTrue(secret.getLine() >= 0);
64+
65+
Assertions.assertNull(MaskResult.fromLine(""));
66+
Assertions.assertNull(MaskResult.fromLine("{invalid json}"));
67+
Assertions.assertNull(MaskResult.fromLine(null));
68+
}
69+
70+
@Test
71+
void testMaskSecretsObjectBehavior() throws Exception {
72+
// Tests object equality, serialization and consistency with CLI responses
73+
MaskResult result1 = wrapper.maskSecrets(SECRETS_REALTIME_FILE);
74+
MaskResult result2 = wrapper.maskSecrets(SECRETS_REALTIME_FILE);
75+
76+
Assertions.assertEquals(result1.getMaskedFile(), result2.getMaskedFile());
77+
Assertions.assertNotNull(result1.toString());
78+
Assertions.assertTrue(result1.toString().contains("MaskResult"));
79+
80+
if (result1.getMaskedSecrets() != null && !result1.getMaskedSecrets().isEmpty()) {
81+
MaskedSecret secret1 = result1.getMaskedSecrets().get(0);
82+
MaskedSecret secret2 = result2.getMaskedSecrets().get(0);
83+
84+
Assertions.assertEquals(secret1.getMasked(), secret2.getMasked());
85+
Assertions.assertEquals(secret1.getSecret(), secret2.getSecret());
86+
Assertions.assertEquals(secret1.getLine(), secret2.getLine());
87+
Assertions.assertEquals(secret1.hashCode(), secret2.hashCode());
88+
Assertions.assertEquals(secret1, secret1);
89+
Assertions.assertNotEquals(secret1, null);
90+
91+
String toString = secret1.toString();
92+
Assertions.assertNotNull(toString);
93+
Assertions.assertTrue(toString.contains("MaskedSecret"));
94+
}
95+
96+
ObjectMapper mapper = new ObjectMapper();
97+
String json = mapper.writeValueAsString(result1);
98+
MaskResult deserialized = mapper.readValue(json, MaskResult.class);
99+
100+
Assertions.assertEquals(result1.getMaskedFile(), deserialized.getMaskedFile());
101+
if (result1.getMaskedSecrets() != null) {
102+
Assertions.assertEquals(result1.getMaskedSecrets().size(), deserialized.getMaskedSecrets().size());
103+
}
104+
}
105+
}
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
[
2+
{
3+
"Title": "private-key",
4+
"Description": "Identified a Private Key, which may compromise cryptographic security and sensitive data encryption.",
5+
"SecretValue": "-----BEGIN RSA PRIVATE KEY-----MIIEowIBAAKCAQEAl5X22d9tXl2Bz1b+3mWsAouoBiQhrDS3GxFAdpJFkKF6Wst+Vl1mfshTd+gF2kHXTzLMdxsUM2AS8laG2xeIhLe07FhhOtQGSoAOjHD++K53MBcOD/mDVOlPhNOWAc3qWfa3R7ohxUJq8lvy1OErw7qlQv9U+xABUJtHbJtMn/dDBs1Fy6MUgO6TOtEwzQaTaGpWh3NmGaUu3KQuaekHZnzlYd8mc1XkztXrph0XxZPq43Gg8RVh25fCrcA+7iAkqa4MNL/5gsatzzjP7KRdx1IP0pnM6F/cwoMClmuV7FFhKoP3KFwt8SXglZnqLrCNK6DzrYU5bRaszIxYc8egywIDAQABAoIBADGaq2rkiF+m7cGx0Dlqv/0dQmCwFizKG1lKLfQfLZCEpwtrJ+6PJek7GMVWMgQYI6MRFoOrYtLlD44p7ntnmg8EJrpouXiMxXo/qYMfvvAV937PLJThq65vosvuiVoRziyeZZ+dM0vfzit9F1u+S5oDS+0+rMpzlFqSVa8eqtZ1i4wmVwKXF35FqHyzhXgKmVNXUy/JCiftJYF2hpe2zXAuGQKTD5x3v52GX+cUsRPPAO5GhJbDnwhbL8i06gLDc7xwfaTJbebvOKHT1F2AW/RhoW+BpJke86beea8DM7KR8RYjobgdf66fadosa27u8qqpcdtyzYMqLc3GuTeYL/ECgYEA36KgaxlWNCuQhLOLPZ/2fzebD1SCI7HsPtbiM+mSbWTGBnSPX36b1XLJkynZrAFKYoe9zx9ksqlrBHWG7PC3FLeIO9ExV9BsGFGjzDpkENteArcO5eLfSMkfXIXNlWwhb8m8DPjdnK2pihs3vVN0OMIPeYu9mAXst0CcR8vQuJ0CgYEArYYBgmAyWfRs8exU2F7vQoG8B4mykTOQ9J91Js72WiHaqt+z4NdGJrFr5VkXCZdbBf3J/PfEPVFT3ud/dAm2PZ40TfNQJTa4pwBhuyCozZff1Qm+X5NdzvHkLePFex6wxUgupVwr/W9UOVU7gRFB/hziSLnlglfpgwxA9j9tfocCgYEAqH69YzQp0RDpyDIGvR2i+WMJ/1jq3L4Xg5kfwYFAhA+jbAWyaH7aJs5ftfOYP5KRWv9vMXkzw7EGIsvyJt+O8Zr+mCMbjFBKwV/xi9SKxHCjumP2Y5q2JP70FB/0L5rS7okOmK+BOaVW0emD66/PJ1x/kFKLPNlp6wBRP37++bkCgYAgrkdkfaeeB4npOmB0a9TWCscWCFoIPNUFLW8MAxikuxGK8xzWsNS2ft3aUSAkn0v2YekD6sob3lBUf/ciLJ4VFtG1CKlEiPzX/xto+eqw5fSzE+W17HRTgH1AI1DTMmGKlmCqpiRm0+vh7GqLkWuDZ386wUA3f0UseEdX2XROywKBgE1Xer2yEZtLlrubHgVAKVrz2u5ZCEPzDkLEDhOxX2h1dP19TWvm2Sr6Fm1QL8lez52YhCW/xJHsr8S4Kka3Ntbm9+ZfhhATTICTpqIicqeAq/Iiw++7UgCk1gZPW1hnlDHYRdmI4Dr6j5aUBFLl4Bj2nedH+1L1Eo8EXfnjm0pi-----END RSA PRIVATE KEY-----",
6+
"FilePath": "C:\\Users\\XYZ\\GitHub_Repo\\JavaVulnerableLab\\CxAppMonDeploy.pem",
7+
"Severity": "High",
8+
"Locations": [
9+
{
10+
"Line": 0,
11+
"StartIndex": 1,
12+
"EndIndex": 30
13+
},
14+
{
15+
"Line": 1,
16+
"StartIndex": 1,
17+
"EndIndex": 30
18+
},
19+
{
20+
"Line": 2,
21+
"StartIndex": 1,
22+
"EndIndex": 30
23+
},
24+
{
25+
"Line": 3,
26+
"StartIndex": 1,
27+
"EndIndex": 30
28+
},
29+
{
30+
"Line": 4,
31+
"StartIndex": 1,
32+
"EndIndex": 30
33+
},
34+
{
35+
"Line": 5,
36+
"StartIndex": 1,
37+
"EndIndex": 30
38+
},
39+
{
40+
"Line": 6,
41+
"StartIndex": 1,
42+
"EndIndex": 30
43+
},
44+
{
45+
"Line": 7,
46+
"StartIndex": 1,
47+
"EndIndex": 30
48+
},
49+
{
50+
"Line": 8,
51+
"StartIndex": 1,
52+
"EndIndex": 30
53+
},
54+
{
55+
"Line": 9,
56+
"StartIndex": 1,
57+
"EndIndex": 30
58+
},
59+
{
60+
"Line": 10,
61+
"StartIndex": 1,
62+
"EndIndex": 30
63+
},
64+
{
65+
"Line": 11,
66+
"StartIndex": 1,
67+
"EndIndex": 30
68+
},
69+
{
70+
"Line": 12,
71+
"StartIndex": 1,
72+
"EndIndex": 30
73+
},
74+
{
75+
"Line": 13,
76+
"StartIndex": 1,
77+
"EndIndex": 30
78+
},
79+
{
80+
"Line": 14,
81+
"StartIndex": 1,
82+
"EndIndex": 30
83+
},
84+
{
85+
"Line": 15,
86+
"StartIndex": 1,
87+
"EndIndex": 30
88+
},
89+
{
90+
"Line": 16,
91+
"StartIndex": 1,
92+
"EndIndex": 30
93+
},
94+
{
95+
"Line": 17,
96+
"StartIndex": 1,
97+
"EndIndex": 30
98+
},
99+
{
100+
"Line": 18,
101+
"StartIndex": 1,
102+
"EndIndex": 30
103+
},
104+
{
105+
"Line": 19,
106+
"StartIndex": 1,
107+
"EndIndex": 30
108+
},
109+
{
110+
"Line": 20,
111+
"StartIndex": 1,
112+
"EndIndex": 30
113+
},
114+
{
115+
"Line": 21,
116+
"StartIndex": 1,
117+
"EndIndex": 30
118+
},
119+
{
120+
"Line": 22,
121+
"StartIndex": 1,
122+
"EndIndex": 30
123+
},
124+
{
125+
"Line": 23,
126+
"StartIndex": 1,
127+
"EndIndex": 30
128+
},
129+
{
130+
"Line": 24,
131+
"StartIndex": 1,
132+
"EndIndex": 30
133+
},
134+
{
135+
"Line": 25,
136+
"StartIndex": 1,
137+
"EndIndex": 30
138+
},
139+
{
140+
"Line": 26,
141+
"StartIndex": 1,
142+
"EndIndex": 30
143+
}
144+
]
145+
}
146+
]
147+

0 commit comments

Comments
 (0)