diff --git a/CHANGELOG.md b/CHANGELOG.md
index aec324f5..f6da1cce 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,7 @@
* Deprecate `org.sonar.api.issue.DefaultTransitions`
* Deprecate `org.sonar.api.web.UserRole`
* Remove deprecated extension points ~~`org.sonar.api.profiles.ProfileExporter`~~ and ~~`org.sonar.api.profiles.ProfileImporter`~~.
+* Introduce new security standards for OWASP Mobile 2024
## 11.3
* Introduce `org.sonar.api.batch.sensor.SensorContext.addAnalysisData`.
diff --git a/plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java b/plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java
index dbca6b7b..93adb590 100644
--- a/plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java
+++ b/plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java
@@ -276,10 +276,34 @@ public String prefix() {
}
}
+ enum OwaspMobileTop10Version {
+ Y2024("2024", "owaspMobileTop10-2024");
+
+ private final String label;
+ private final String prefix;
+
+ OwaspMobileTop10Version(String label, String prefix) {
+ this.label = label;
+ this.prefix = prefix;
+ }
+
+ public String label() {
+ return label;
+ }
+
+ public String prefix() {
+ return prefix;
+ }
+ }
+
enum OwaspTop10 {
A1, A2, A3, A4, A5, A6, A7, A8, A9, A10
}
+ enum OwaspMobileTop10 {
+ M1, M2, M3, M4, M5, M6, M7, M8, M9, M10
+ }
+
enum PciDssVersion {
V3_2("3.2", "pciDss-3.2"), V4_0("4.0", "pciDss-4.0");
@@ -461,6 +485,7 @@ abstract class NewRule {
/**
* The Clean Code Attribute of the rule.
* Providing it is optional for now, but will become mandatory in the future.
+ *
* @since 10.1
*/
public abstract NewRule setCleanCodeAttribute(CleanCodeAttribute attribute);
@@ -470,7 +495,8 @@ abstract class NewRule {
* For backward compatibility, one of the old method {@link #setHtmlDescription(String)} or {@link #setHtmlDescription(URL)} still
* need to be called on top of that one.
* Each section must have a different section key when they are non-contextual.
- * As soon as one section is contextual for a section key, all sections with that key must be contextual. The pair "section key, context key" pair must still be unique.
+ * As soon as one section is contextual for a section key, all sections with that key must be contextual. The pair "section key,
+ * context key" pair must still be unique.
* If several sections provide contexts, the provided context keys must be the same between sections.
*
* @since 9.6
@@ -484,7 +510,8 @@ abstract class NewRule {
public abstract NewRule setHtmlDescription(@Nullable String s);
/**
- * Load description from a file available in classpath. Example : setHtmlDescription(getClass().getResource("/myrepo/Rule1234.html")
+ * Load description from a file available in classpath. Example : setHtmlDescription(getClass().getResource("/myrepo/Rule1234
+ * .html")
*/
public abstract NewRule setHtmlDescription(@Nullable URL classpathUrl);
@@ -498,7 +525,8 @@ abstract class NewRule {
public abstract NewRule setMarkdownDescription(@Nullable String s);
/**
- * Load description from a file available in classpath. Example : {@code setMarkdownDescription(getClass().getResource("/myrepo/Rule1234.md")}
+ * Load description from a file available in classpath. Example : {@code setMarkdownDescription(getClass().getResource
+ * ("/myrepo/Rule1234.md")}
*
* @deprecated since 9.6. Use {@link #addDescriptionSection(RuleDescriptionSection)} instead
*/
@@ -565,6 +593,11 @@ abstract class NewRule {
*/
public abstract NewRule addOwaspTop10(OwaspTop10Version version, OwaspTop10... standards);
+ /**
+ * @since 11.4
+ */
+ public abstract NewRule addOwaspMobileTop10(OwaspMobileTop10Version owaspMobileTop10Version, OwaspMobileTop10... standards);
+
/**
* @since 9.5
*/
diff --git a/plugin-api/src/main/java/org/sonar/api/server/rule/internal/DefaultNewRule.java b/plugin-api/src/main/java/org/sonar/api/server/rule/internal/DefaultNewRule.java
index 92fc5cc8..2755a04e 100644
--- a/plugin-api/src/main/java/org/sonar/api/server/rule/internal/DefaultNewRule.java
+++ b/plugin-api/src/main/java/org/sonar/api/server/rule/internal/DefaultNewRule.java
@@ -48,6 +48,8 @@
import org.sonar.api.server.rule.RuleDescriptionSection;
import org.sonar.api.server.rule.RuleTagFormat;
import org.sonar.api.server.rule.RulesDefinition;
+import org.sonar.api.server.rule.RulesDefinition.OwaspMobileTop10;
+import org.sonar.api.server.rule.RulesDefinition.OwaspMobileTop10Version;
import org.sonar.api.server.rule.RulesDefinition.OwaspTop10;
import org.sonar.api.server.rule.RulesDefinition.OwaspTop10Version;
import org.sonar.api.server.rule.RulesDefinition.PciDssVersion;
@@ -335,6 +337,17 @@ public DefaultNewRule addOwaspTop10(OwaspTop10Version owaspTop10Version, OwaspTo
return this;
}
+ @Override
+ public DefaultNewRule addOwaspMobileTop10(OwaspMobileTop10Version owaspMobileTop10Version, OwaspMobileTop10... standards) {
+ requireNonNull(owaspMobileTop10Version, "Owasp mobile version must not be null");
+
+ for (OwaspMobileTop10 owaspMobileTop10 : standards) {
+ String standard = owaspMobileTop10Version.prefix() + ":" + owaspMobileTop10.name().toLowerCase(Locale.ENGLISH);
+ securityStandards.add(standard);
+ }
+ return this;
+ }
+
@Override
public DefaultNewRule addOwaspAsvs(OwaspAsvsVersion owaspAsvsVersion, String... requirements) {
requireNonNull(owaspAsvsVersion, "OWASP ASVS version must not be null");
diff --git a/plugin-api/src/test/java/org/sonar/api/server/rule/internal/DefaultNewRuleTest.java b/plugin-api/src/test/java/org/sonar/api/server/rule/internal/DefaultNewRuleTest.java
index c315c6ee..5ca12be9 100644
--- a/plugin-api/src/test/java/org/sonar/api/server/rule/internal/DefaultNewRuleTest.java
+++ b/plugin-api/src/test/java/org/sonar/api/server/rule/internal/DefaultNewRuleTest.java
@@ -35,6 +35,8 @@
import org.sonar.api.server.rule.RuleDescriptionSectionBuilder;
import org.sonar.api.server.rule.RulesDefinition;
import org.sonar.api.server.rule.RulesDefinition.OwaspAsvsVersion;
+import org.sonar.api.server.rule.RulesDefinition.OwaspMobileTop10;
+import org.sonar.api.server.rule.RulesDefinition.OwaspMobileTop10Version;
import org.sonar.api.server.rule.RulesDefinition.OwaspTop10;
import org.sonar.api.server.rule.RulesDefinition.OwaspTop10Version;
import org.sonar.api.server.rule.RulesDefinition.PciDssVersion;
@@ -143,6 +145,10 @@ private void assertSecurityStandards() {
assertThat(rule.securityStandards())
.contains("owaspTop10:a1", "owaspTop10:a2", "owaspTop10:a4", "owaspTop10-2021:a3", "owaspTop10-2021:a5");
+ rule.addOwaspMobileTop10(OwaspMobileTop10Version.Y2024, OwaspMobileTop10.M2, OwaspMobileTop10.M3);
+ rule.addOwaspMobileTop10(OwaspMobileTop10Version.Y2024, OwaspMobileTop10.M5);
+ assertThat(rule.securityStandards()).contains("owaspMobileTop10-2024:m2", "owaspMobileTop10-2024:m3", "owaspMobileTop10-2024:m5");
+
rule.addPciDss(PciDssVersion.V3_2, "6.5.1");
rule.addPciDss(PciDssVersion.V3_2, "6.5");
rule.addPciDss(PciDssVersion.V4_0, "6.5.2", "6.5.10");
@@ -228,6 +234,13 @@ public void fail_if_null_owasp_version() {
.hasMessage("Owasp version must not be null");
}
+ @Test
+ public void fail_if_null_owasp_mobile_version() {
+ assertThatThrownBy(() -> rule.addOwaspMobileTop10(null, OwaspMobileTop10.M5))
+ .isInstanceOf(NullPointerException.class)
+ .hasMessage("Owasp mobile version must not be null");
+ }
+
@Test
public void fail_if_null_pci_dss_version() {
assertThatThrownBy(() -> rule.addPciDss(null, "6.5.1"))