Skip to content

Commit ddf4a1b

Browse files
ACOMMONS-34 Expose Standards OWASP LLM Top 10 2025, OWASP Top 10 2025, ASVS 5.0, STIG ASD_V6, MASVS 2 metadata (#370)
1 parent 1d9d05b commit ddf4a1b

File tree

4 files changed

+172
-44
lines changed

4 files changed

+172
-44
lines changed

commons/src/main/java/org/sonarsource/analyzer/commons/RuleMetadataLoader.java

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import org.sonar.api.server.rule.RulesDefinition.NewRepository;
4040
import org.sonar.api.server.rule.RulesDefinition.NewRule;
4141
import org.sonar.api.server.rule.RulesDefinition.OwaspAsvsVersion;
42+
import org.sonar.api.server.rule.RulesDefinition.OwaspLlmTop10Version;
4243
import org.sonar.api.server.rule.RulesDefinition.OwaspTop10Version;
4344
import org.sonar.api.server.rule.RulesDefinition.OwaspMobileTop10Version;
4445
import org.sonar.api.server.rule.RulesDefinition.PciDssVersion;
@@ -68,6 +69,7 @@ public class RuleMetadataLoader {
6869
private final EducationRuleLoader educationRuleLoader;
6970

7071
private static final String OWASP_MOBILE_2024 = "OWASP Mobile Top 10 2024";
72+
private static final String OWASP_2025 = "OWASP Top 10 2025";
7173
private static final String OWASP_2021 = "OWASP Top 10 2021";
7274
private static final String OWASP_2017 = "OWASP";
7375
private static final String PCI_DSS_PREFIX = "PCI DSS ";
@@ -259,31 +261,46 @@ private void setSecurityStandardsFromJson(NewRule rule, Map<String, Object> secu
259261
rule.addCwe(getIntArray(securityStandards, "CWE"));
260262
}
261263

264+
addMasvs(rule, securityStandards);
262265
addOwasp(rule, securityStandards);
266+
addOwaspAsvs(rule, securityStandards);
267+
addOwaspLlm(rule, securityStandards);
263268
addOwaspMobile(rule, securityStandards);
264269
addPciDss(rule, securityStandards);
265-
addOwaspAsvs(rule, securityStandards);
266270
addStig(rule, securityStandards);
267271
}
268272

269-
private void addOwasp(NewRule rule, Map<String, Object> securityStandards) {
270-
boolean isOwaspByVersionSupported = isSupported(9, 3);
271-
272-
for (String standard : getStringArray(securityStandards, OWASP_2017)) {
273-
if (isOwaspByVersionSupported) {
274-
rule.addOwaspTop10(OwaspTop10Version.Y2017, RulesDefinition.OwaspTop10.valueOf(standard));
275-
} else {
276-
rule.addOwaspTop10(RulesDefinition.OwaspTop10.valueOf(standard));
277-
}
273+
private void addMasvs(NewRule rule, Map<String, Object> securityStandards) {
274+
if (!isSupported(13, 3)) {
275+
return;
276+
}
277+
for (RulesDefinition.MasvsVersion masvsVersion : RulesDefinition.MasvsVersion.values()) {
278+
rule.addMasvs(masvsVersion, getStringArray(securityStandards, masvsVersion.label()));
278279
}
280+
}
279281

282+
private void addOwasp(NewRule rule, Map<String, Object> securityStandards) {
283+
boolean isOwaspByVersionSupported = isSupported(9, 3);
284+
RulesDefinition.OwaspTop10[] valuesFor2017 = getOwaspTop10Values(securityStandards, OWASP_2017);
280285
if (isOwaspByVersionSupported) {
281-
for (String standard : getStringArray(securityStandards, OWASP_2021)) {
282-
rule.addOwaspTop10(OwaspTop10Version.Y2021, RulesDefinition.OwaspTop10.valueOf(standard));
286+
rule.addOwaspTop10(OwaspTop10Version.Y2017, valuesFor2017);
287+
RulesDefinition.OwaspTop10[] valuesFor2021 = getOwaspTop10Values(securityStandards, OWASP_2021);
288+
rule.addOwaspTop10(OwaspTop10Version.Y2021, valuesFor2021);
289+
if (isSupported(13, 3)) {
290+
RulesDefinition.OwaspTop10[] valuesFor2025 = getOwaspTop10Values(securityStandards, OWASP_2025);
291+
rule.addOwaspTop10(OwaspTop10Version.Y2025, valuesFor2025);
283292
}
293+
} else {
294+
rule.addOwaspTop10(valuesFor2017);
284295
}
285296
}
286297

298+
private RulesDefinition.OwaspTop10[] getOwaspTop10Values(Map<String, Object> securityStandards, String owaspVersionLabel) {
299+
return Arrays.stream(getStringArray(securityStandards, owaspVersionLabel))
300+
.map(RulesDefinition.OwaspTop10::valueOf)
301+
.toArray(RulesDefinition.OwaspTop10[]::new);
302+
}
303+
287304
private void addOwaspMobile(NewRule rule, Map<String, Object> securityStandards) {
288305
if (!isSupported(11, 4)) {
289306
return;
@@ -293,6 +310,18 @@ private void addOwaspMobile(NewRule rule, Map<String, Object> securityStandards)
293310
}
294311
}
295312

313+
private void addOwaspLlm(NewRule rule, Map<String, Object> securityStandards) {
314+
if (!isSupported(13, 3)) {
315+
return;
316+
}
317+
for (OwaspLlmTop10Version owaspLlmTop10Version : OwaspLlmTop10Version.values()) {
318+
RulesDefinition.OwaspLlmTop10[] llmTop10Values = Arrays.stream(getStringArray(securityStandards, owaspLlmTop10Version.label()))
319+
.map(RulesDefinition.OwaspLlmTop10::valueOf)
320+
.toArray(RulesDefinition.OwaspLlmTop10[]::new);
321+
rule.addOwaspLlmTop10(owaspLlmTop10Version, llmTop10Values);
322+
}
323+
}
324+
296325
private void addPciDss(NewRule rule, Map<String, Object> securityStandards) {
297326
if (!isSupported(9, 5)) {
298327
return;

commons/src/test/java/org/sonarsource/analyzer/commons/RuleMetadataLoaderTest.java

Lines changed: 107 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ public class RuleMetadataLoaderTest {
7878
private static final SonarRuntime SONAR_RUNTIME_10_10 = SonarRuntimeImpl.forSonarLint(Version.create(10, 10));
7979
private static final SonarRuntime SONAR_RUNTIME_10_11 = SonarRuntimeImpl.forSonarLint(Version.create(10, 11));
8080
private static final SonarRuntime SONAR_RUNTIME_11_4 = SonarRuntimeImpl.forSonarLint(Version.create(11, 4));
81+
private static final SonarRuntime SONAR_RUNTIME_13_3 = SonarRuntimeImpl.forSonarLint(Version.create(13, 3));
8182

8283
@Before
8384
public void setup() {
@@ -530,72 +531,148 @@ class TestRule {
530531
RulesDefinition.Rule rule = context.repository(RULE_REPOSITORY_KEY).rule("S2092");
531532
assertThat(rule.type()).isEqualTo(RuleType.SECURITY_HOTSPOT);
532533
assertThat(rule.securityStandards())
533-
.containsExactlyInAnyOrder("cwe:311", "cwe:315", "cwe:614", "owaspTop10:a2", "owaspTop10:a3", "owaspTop10-2021:a4", "owaspTop10-2021:a5");
534+
.containsExactlyInAnyOrder(
535+
"cwe:311",
536+
"cwe:315",
537+
"cwe:614",
538+
"owaspTop10:a2",
539+
"owaspTop10:a3",
540+
"owaspTop10-2021:a4",
541+
"owaspTop10-2021:a5");
542+
}
543+
544+
@Test
545+
public void test_security_standards_on_13_3() {
546+
Set<String> securityStandards = getSecurityStandards(SONAR_RUNTIME_13_3);
547+
assertThat(securityStandards).containsExactlyInAnyOrder(
548+
"cwe:311",
549+
"cwe:315",
550+
"cwe:614",
551+
"masvs-1:MSTG-STORAGE-14",
552+
"masvs-2:MASVS-STORAGE-15",
553+
"owaspTop10:a2",
554+
"owaspTop10:a3",
555+
"owaspTop10-2021:a4",
556+
"owaspTop10-2021:a5",
557+
"owaspTop10-2025:a6",
558+
"owaspTop10-2025:a7",
559+
"pciDss-3.2:1.1.1",
560+
"pciDss-3.2:1.1.2",
561+
"owaspAsvs-4.0:2.1.1",
562+
"owaspAsvs-4.0:2.1.2",
563+
"owaspAsvs-5:2.1.3",
564+
"owaspAsvs-5:2.1.4",
565+
"stig-ASD_V5R3:V-222612",
566+
"stig-ASD_V6:V-222613",
567+
"owaspMobileTop10-2024:m3",
568+
"owaspMobileTop10-2024:m4",
569+
"owaspLlmTop10-2025:llm01",
570+
"owaspLlmTop10-2025:llm10"
571+
);
534572
}
535573

536574
@Test
537575
public void test_security_standards_on_11_4() {
538576
Set<String> securityStandards = getSecurityStandards(SONAR_RUNTIME_11_4);
539577
assertThat(securityStandards).containsExactlyInAnyOrder(
540-
"cwe:311", "cwe:315", "cwe:614",
541-
"owaspTop10:a2", "owaspTop10:a3",
542-
"owaspTop10-2021:a4", "owaspTop10-2021:a5",
543-
"pciDss-3.2:1.1.1", "pciDss-3.2:1.1.2",
544-
"owaspAsvs-4.0:2.1.1", "owaspAsvs-4.0:2.1.2",
545-
"stig-ASD_V5R3:V-222612",
546-
"owaspMobileTop10-2024:m3", "owaspMobileTop10-2024:m4"
578+
"cwe:311",
579+
"cwe:315",
580+
"cwe:614",
581+
"owaspTop10:a2",
582+
"owaspTop10:a3",
583+
"owaspTop10-2021:a4",
584+
"owaspTop10-2021:a5",
585+
"pciDss-3.2:1.1.1",
586+
"pciDss-3.2:1.1.2",
587+
"owaspAsvs-4.0:2.1.1",
588+
"owaspAsvs-4.0:2.1.2",
589+
"owaspAsvs-5:2.1.3",
590+
"owaspAsvs-5:2.1.4",
591+
"stig-ASD_V5R3:V-222612",
592+
"stig-ASD_V6:V-222613",
593+
"owaspMobileTop10-2024:m3",
594+
"owaspMobileTop10-2024:m4"
547595
);
548596
}
549597

550598
@Test
551599
public void test_security_standards_on_10_10_return_stig() {
552600
Set<String> securityStandards = getSecurityStandards(SONAR_RUNTIME_10_10);
553601
assertThat(securityStandards).containsExactlyInAnyOrder(
554-
"cwe:311", "cwe:315", "cwe:614",
555-
"owaspTop10:a2", "owaspTop10:a3",
556-
"owaspTop10-2021:a4", "owaspTop10-2021:a5",
557-
"pciDss-3.2:1.1.1", "pciDss-3.2:1.1.2",
558-
"owaspAsvs-4.0:2.1.1", "owaspAsvs-4.0:2.1.2",
559-
"stig-ASD_V5R3:V-222612"
602+
"cwe:311",
603+
"cwe:315",
604+
"cwe:614",
605+
"owaspTop10:a2",
606+
"owaspTop10:a3",
607+
"owaspTop10-2021:a4",
608+
"owaspTop10-2021:a5",
609+
"pciDss-3.2:1.1.1",
610+
"pciDss-3.2:1.1.2",
611+
"owaspAsvs-4.0:2.1.1",
612+
"owaspAsvs-4.0:2.1.2",
613+
"owaspAsvs-5:2.1.3",
614+
"owaspAsvs-5:2.1.4",
615+
"stig-ASD_V5R3:V-222612",
616+
"stig-ASD_V6:V-222613"
560617
);
561618
}
562619

563620
@Test
564621
public void test_security_standards_on_9_9_return_asvs() {
565622
Set<String> securityStandards = getSecurityStandards(SONAR_RUNTIME_9_9);
566623
assertThat(securityStandards).containsExactlyInAnyOrder(
567-
"cwe:311", "cwe:315", "cwe:614",
568-
"owaspTop10:a2", "owaspTop10:a3",
569-
"owaspTop10-2021:a4", "owaspTop10-2021:a5",
570-
"pciDss-3.2:1.1.1", "pciDss-3.2:1.1.2",
571-
"owaspAsvs-4.0:2.1.1", "owaspAsvs-4.0:2.1.2");
624+
"cwe:311",
625+
"cwe:315",
626+
"cwe:614",
627+
"owaspTop10:a2",
628+
"owaspTop10:a3",
629+
"owaspTop10-2021:a4",
630+
"owaspTop10-2021:a5",
631+
"pciDss-3.2:1.1.1",
632+
"pciDss-3.2:1.1.2",
633+
"owaspAsvs-4.0:2.1.1",
634+
"owaspAsvs-4.0:2.1.2",
635+
"owaspAsvs-5:2.1.3",
636+
"owaspAsvs-5:2.1.4");
572637
}
573638

574639
@Test
575640
public void test_security_standards_on_9_5_return_pci_dss() {
576641
Set<String> securityStandards = getSecurityStandards(SONAR_RUNTIME_9_5);
577642
assertThat(securityStandards).containsExactlyInAnyOrder(
578-
"cwe:311", "cwe:315", "cwe:614",
579-
"owaspTop10:a2", "owaspTop10:a3",
580-
"owaspTop10-2021:a4", "owaspTop10-2021:a5",
581-
"pciDss-3.2:1.1.1", "pciDss-3.2:1.1.2");
643+
"cwe:311",
644+
"cwe:315",
645+
"cwe:614",
646+
"owaspTop10:a2",
647+
"owaspTop10:a3",
648+
"owaspTop10-2021:a4",
649+
"owaspTop10-2021:a5",
650+
"pciDss-3.2:1.1.1",
651+
"pciDss-3.2:1.1.2");
582652
}
583653

584654
@Test
585655
public void test_security_standards_on_9_3_return_owasp_2021() {
586656
Set<String> securityStandards = getSecurityStandards(SONAR_RUNTIME_9_3);
587657
assertThat(securityStandards).containsExactlyInAnyOrder(
588-
"cwe:311", "cwe:315", "cwe:614",
589-
"owaspTop10:a2", "owaspTop10:a3",
590-
"owaspTop10-2021:a4", "owaspTop10-2021:a5");
658+
"cwe:311",
659+
"cwe:315",
660+
"cwe:614",
661+
"owaspTop10:a2",
662+
"owaspTop10:a3",
663+
"owaspTop10-2021:a4",
664+
"owaspTop10-2021:a5");
591665
}
592666

593667
@Test
594668
public void test_security_standards_before_9_3() {
595669
Set<String> securityStandards = getSecurityStandards(SONAR_RUNTIME_9_2);
596670
assertThat(securityStandards).containsExactlyInAnyOrder(
597-
"cwe:311", "cwe:315", "cwe:614",
598-
"owaspTop10:a2", "owaspTop10:a3");
671+
"cwe:311",
672+
"cwe:315",
673+
"cwe:614",
674+
"owaspTop10:a2",
675+
"owaspTop10:a3");
599676
}
600677

601678
@Test
@@ -714,7 +791,8 @@ public String attribute() {
714791
assertThat(rule.param("Param0").description()).isEqualTo("Param0 Description");
715792
assertThat(rule.param("Param1").type()).isEqualTo(RuleParamType.INTEGER);
716793
assertThat(rule.param("Param1").defaultValue()).isEqualTo("10");
717-
assertThat(rule.param("Param1").description()).isEqualTo("Param1 Description"); }
794+
assertThat(rule.param("Param1").description()).isEqualTo("Param1 Description");
795+
}
718796

719797
@Test
720798
public void test_create_rule_from_rule_manifest_with_constant_remediation() {

commons/src/test/resources/org/sonarsource/analyzer/commons/S2092.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,41 @@
3636
"A4",
3737
"A5"
3838
],
39+
"OWASP Top 10 2025": [
40+
"A6",
41+
"A7"
42+
],
3943
"OWASP Mobile Top 10 2024": [
4044
"M3",
4145
"M4"
4246
],
47+
"OWASP LLM Top 10 2025": [
48+
"LLM01",
49+
"LLM10"
50+
],
4351
"PCI DSS 3.2": [
4452
"1.1.1",
4553
"1.1.2"
4654
],
55+
"MASVS": [
56+
"MSTG-STORAGE-14"
57+
],
58+
"MASVS 2": [
59+
"MASVS-STORAGE-15"
60+
],
4761
"ASVS 4.0": [
4862
"2.1.1",
4963
"2.1.2"
5064
],
65+
"ASVS 5": [
66+
"2.1.3",
67+
"2.1.4"
68+
],
5169
"STIG ASD_V5R3": [
5270
"V-222612"
71+
],
72+
"STIG ASD_V6": [
73+
"V-222613"
5374
]
5475
}
5576
}

pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@
7373

7474
<properties>
7575
<!-- versions -->
76-
<version.sonar>11.4.0.2922</version.sonar>
76+
<version.sonar.plugin.api>13.3.0.3209</version.sonar.plugin.api>
7777
<sonarqube.api.impl.version>10.7.0.96327</sonarqube.api.impl.version>
7878
<version.assertj>3.17.1</version.assertj>
7979
<version.jsr305>3.0.2</version.jsr305>
@@ -95,7 +95,7 @@
9595
<dependency>
9696
<groupId>org.sonarsource.api.plugin</groupId>
9797
<artifactId>sonar-plugin-api</artifactId>
98-
<version>${version.sonar}</version>
98+
<version>${version.sonar.plugin.api}</version>
9999
<scope>provided</scope>
100100
</dependency>
101101
<dependency>
@@ -112,7 +112,7 @@
112112
<dependency>
113113
<groupId>org.sonarsource.api.plugin</groupId>
114114
<artifactId>sonar-plugin-api-test-fixtures</artifactId>
115-
<version>${version.sonar}</version>
115+
<version>${version.sonar.plugin.api}</version>
116116
</dependency>
117117

118118
<!-- COMPILE -->

0 commit comments

Comments
 (0)