Skip to content

Commit 0253a18

Browse files
SONARXML-236 Rule S7207: Components should be explicitly exported (#337)
1 parent 5054427 commit 0253a18

File tree

19 files changed

+451
-22
lines changed

19 files changed

+451
-22
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
'project:special-cases/android-application/app1/AndroidManifest.xml':[
3+
11,
4+
30,
5+
42,
6+
54,
7+
66,
8+
78,
9+
90,
10+
102,
11+
113,
12+
124,
13+
135,
14+
146,
15+
157,
16+
169,
17+
180,
18+
191,
19+
202,
20+
213,
21+
224,
22+
235,
23+
246,
24+
257,
25+
268,
26+
280,
27+
293,
28+
306,
29+
],
30+
'project:special-cases/android-application/app3/AndroidManifest.xml':[
31+
16,
32+
26,
33+
],
34+
}

sonar-xml-plugin/src/main/java/org/sonar/plugins/xml/checks/CheckList.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.sonar.plugins.xml.checks.maven.PomElementOrderCheck;
3030
import org.sonar.plugins.xml.checks.security.HardcodedCredentialsCheck;
3131
import org.sonar.plugins.xml.checks.security.android.AndroidApplicationBackupCheck;
32+
import org.sonar.plugins.xml.checks.security.android.AndroidComponentWithIntentFilterExportedCheck;
3233
import org.sonar.plugins.xml.checks.security.android.AndroidCustomPermissionCheck;
3334
import org.sonar.plugins.xml.checks.security.android.AndroidClearTextCheck;
3435
import org.sonar.plugins.xml.checks.security.android.AndroidExportedContentPermissionsCheck;
@@ -62,6 +63,7 @@ public static List<Class<?>> getCheckClasses() {
6263
AndroidClearTextCheck.class,
6364
AndroidCustomPermissionCheck.class,
6465
AndroidApplicationBackupCheck.class,
66+
AndroidComponentWithIntentFilterExportedCheck.class,
6567
AndroidExportedContentPermissionsCheck.class,
6668
AndroidPermissionsCheck.class,
6769
AndroidProviderPermissionCheck.class,

sonar-xml-plugin/src/main/java/org/sonar/plugins/xml/checks/security/android/AbstractAndroidManifestCheck.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
import org.sonarsource.analyzer.commons.xml.XmlFile;
2020
import org.sonarsource.analyzer.commons.xml.checks.SimpleXPathBasedCheck;
2121

22-
public abstract class AbstractAndroidManifestCheck extends SimpleXPathBasedCheck {
22+
import static org.sonar.plugins.xml.checks.security.android.Utils.isAndroidManifestFile;
2323

24-
private static final String ANDROID_MANIFEST_XML = "AndroidManifest.xml";
24+
public abstract class AbstractAndroidManifestCheck extends SimpleXPathBasedCheck {
2525

2626
@Override
2727
public final void scanFile(XmlFile file) {
@@ -32,8 +32,4 @@ public final void scanFile(XmlFile file) {
3232

3333
protected abstract void scanAndroidManifest(XmlFile file);
3434

35-
public static boolean isAndroidManifestFile(XmlFile file) {
36-
return ANDROID_MANIFEST_XML.equalsIgnoreCase(file.getInputFile().filename());
37-
}
38-
3935
}

sonar-xml-plugin/src/main/java/org/sonar/plugins/xml/checks/security/android/AndroidApplicationBackupCheck.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
import org.w3c.dom.Element;
2626
import org.w3c.dom.Node;
2727

28+
import static org.sonar.plugins.xml.checks.security.android.Utils.ANDROID_MANIFEST_XMLNS;
29+
2830
@Rule(key = "S6358")
2931
public class AndroidApplicationBackupCheck extends AbstractAndroidManifestCheck {
3032

@@ -44,12 +46,12 @@ public class AndroidApplicationBackupCheck extends AbstractAndroidManifestCheck
4446

4547
private static final XPathExpression X_PATH_APPLICATION_WITH_BACKUP = XPathBuilder
4648
.forExpression(APPLICATION_WITH_BACKUP_QUERY)
47-
.withNamespace("n", "http://schemas.android.com/apk/res/android")
49+
.withNamespace("n", ANDROID_MANIFEST_XMLNS)
4850
.build();
4951

5052
private static final XPathExpression X_PATH_APPLICATION_BELOW_SDK_23 = XPathBuilder
5153
.forExpression(APPLICATION_BELOW_SDK_23_QUERY)
52-
.withNamespace("n", "http://schemas.android.com/apk/res/android")
54+
.withNamespace("n", ANDROID_MANIFEST_XMLNS)
5355
.build();
5456

5557
@Override

sonar-xml-plugin/src/main/java/org/sonar/plugins/xml/checks/security/android/AndroidClearTextCheck.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,22 @@
2525
import org.w3c.dom.Element;
2626
import org.w3c.dom.Node;
2727

28+
import static org.sonar.plugins.xml.checks.security.android.Utils.ANDROID_MANIFEST_XMLNS;
29+
2830
@Rule(key = "S5332")
2931
public class AndroidClearTextCheck extends AbstractAndroidManifestCheck {
3032

3133
private static final String MESSAGE = "Make sure allowing clear-text traffic is safe here.";
3234
private static final String MESSAGE_IMPLICIT = "\"usesCleartextTraffic\" is implicitly enabled for older Android versions. " + MESSAGE;
3335

34-
private static final String ANDROID_NAME_SPACE = "http://schemas.android.com/apk/res/android";
35-
3636
private final XPathExpression xPathClearTextTrue = XPathBuilder
3737
.forExpression("/manifest/application[@n:usesCleartextTraffic='true']")
38-
.withNamespace("n", ANDROID_NAME_SPACE)
38+
.withNamespace("n", ANDROID_MANIFEST_XMLNS)
3939
.build();
4040

4141
private final XPathExpression xPathClearTextImplicit = XPathBuilder
4242
.forExpression("/manifest/application[not(@n:usesCleartextTraffic)]")
43-
.withNamespace("n", ANDROID_NAME_SPACE)
43+
.withNamespace("n", ANDROID_MANIFEST_XMLNS)
4444
.build();
4545

4646
@Override
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* SonarQube XML Plugin
3+
* Copyright (C) 2010-2025 SonarSource SA
4+
* mailto:info AT sonarsource DOT com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the Sonar Source-Available License Version 1, as published by SonarSource SA.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12+
* See the Sonar Source-Available License for more details.
13+
*
14+
* You should have received a copy of the Sonar Source-Available License
15+
* along with this program; if not, see https://sonarsource.com/license/ssal/
16+
*/
17+
package org.sonar.plugins.xml.checks.security.android;
18+
19+
import java.util.Collections;
20+
import javax.xml.xpath.XPathExpression;
21+
import org.sonar.check.Rule;
22+
import org.sonarsource.analyzer.commons.xml.XPathBuilder;
23+
import org.sonarsource.analyzer.commons.xml.XmlFile;
24+
import org.w3c.dom.Element;
25+
26+
import static org.sonar.plugins.xml.checks.security.android.Utils.ANDROID_MANIFEST_XMLNS;
27+
import static org.sonar.plugins.xml.checks.security.android.Utils.isAndroidManifestFile;
28+
29+
@Rule(key = "S7207")
30+
public class AndroidComponentWithIntentFilterExportedCheck extends AbstractAndroidManifestCheck {
31+
32+
private static final String MESSAGE = "Mark this component as exported.";
33+
34+
private final XPathExpression xPathExpression = XPathBuilder
35+
.forExpression("/manifest/application/*" +
36+
"[" +
37+
" (self::activity or self::activity-alias or self::provider or self::receiver or self::service)" +
38+
"and" +
39+
" (intent-filter)" +
40+
"and" +
41+
" (not(@n:exported))" +
42+
"]")
43+
.withNamespace("n", ANDROID_MANIFEST_XMLNS)
44+
.build();
45+
46+
@Override
47+
protected void scanAndroidManifest(XmlFile file) {
48+
evaluateAsList(xPathExpression, file.getDocument())
49+
.forEach(node -> reportIssue(XmlFile.nameLocation((Element) node), MESSAGE, Collections.emptyList()));
50+
}
51+
52+
}

sonar-xml-plugin/src/main/java/org/sonar/plugins/xml/checks/security/android/AndroidCustomPermissionCheck.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,14 @@
2121
import org.sonarsource.analyzer.commons.xml.XPathBuilder;
2222
import org.sonarsource.analyzer.commons.xml.XmlFile;
2323

24+
import static org.sonar.plugins.xml.checks.security.android.Utils.ANDROID_MANIFEST_XMLNS;
25+
2426
@Rule(key = "S6359")
2527
public class AndroidCustomPermissionCheck extends AbstractAndroidManifestCheck {
2628

2729
private static final String MESSAGE = "Use a different namespace for the \"%s\" permission.";
2830
private final XPathExpression xPathExpression = XPathBuilder.forExpression("/manifest/permission/@n1:name")
29-
.withNamespace("n1", "http://schemas.android.com/apk/res/android")
31+
.withNamespace("n1", ANDROID_MANIFEST_XMLNS)
3032
.build();
3133

3234
@Override

sonar-xml-plugin/src/main/java/org/sonar/plugins/xml/checks/security/android/AndroidExportedContentPermissionsCheck.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import org.sonarsource.analyzer.commons.xml.XmlFile;
2424
import org.w3c.dom.Element;
2525

26+
import static org.sonar.plugins.xml.checks.security.android.Utils.ANDROID_MANIFEST_XMLNS;
27+
2628
@Rule(key = "S5594")
2729
public class AndroidExportedContentPermissionsCheck extends AbstractAndroidManifestCheck {
2830

@@ -44,7 +46,7 @@ public class AndroidExportedContentPermissionsCheck extends AbstractAndroidManif
4446
" or @n:name='android.intent.action.SENDTO'" +
4547
" or @n:name='android.intent.action.SEND_MULTIPLE'])" +
4648
"]")
47-
.withNamespace("n", "http://schemas.android.com/apk/res/android")
49+
.withNamespace("n", ANDROID_MANIFEST_XMLNS)
4850
.build();
4951

5052
@Override

sonar-xml-plugin/src/main/java/org/sonar/plugins/xml/checks/security/android/AndroidPermissionsCheck.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@
2424
import org.sonarsource.analyzer.commons.xml.XPathBuilder;
2525
import org.sonarsource.analyzer.commons.xml.XmlFile;
2626

27+
import static org.sonar.plugins.xml.checks.security.android.Utils.ANDROID_MANIFEST_XMLNS;
28+
2729
@Rule(key = "S5604")
2830
public class AndroidPermissionsCheck extends AbstractAndroidManifestCheck {
2931

3032
private static final String MESSAGE = "Make sure the use of \"%s\" permission is necessary.";
3133
private final XPathExpression xPathExpression = XPathBuilder.forExpression("/manifest/uses-permission/@n1:name")
32-
.withNamespace("n1", "http://schemas.android.com/apk/res/android")
34+
.withNamespace("n1", ANDROID_MANIFEST_XMLNS)
3335
.build();
3436

3537
private static final Set<String> DANGEROUS_PERMISSIONS = new HashSet<>(Arrays.asList(

sonar-xml-plugin/src/main/java/org/sonar/plugins/xml/checks/security/android/AndroidProviderPermissionCheck.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,12 @@
2828
import org.w3c.dom.NamedNodeMap;
2929
import org.w3c.dom.Node;
3030

31+
import static org.sonar.plugins.xml.checks.security.android.Utils.ANDROID_MANIFEST_XMLNS;
32+
3133
@Rule(key = "S6361")
3234
public class AndroidProviderPermissionCheck extends AbstractAndroidManifestCheck {
3335

3436
private static final String MESSAGE = "Make sure using a single permission for read and write is safe here.";
35-
private static final String ANDROID_NS = "http://schemas.android.com/apk/res/android";
3637
private final XPathExpression xPathExpression = XPathBuilder
3738
.forExpression("/manifest/application/provider" +
3839
"[" +
@@ -44,7 +45,7 @@ public class AndroidProviderPermissionCheck extends AbstractAndroidManifestCheck
4445
"or" +
4546
" (@n:readPermission and @n:writePermission and @n:readPermission = @n:writePermission)" +
4647
"]")
47-
.withNamespace("n", ANDROID_NS)
48+
.withNamespace("n", ANDROID_MANIFEST_XMLNS)
4849
.build();
4950

5051
@Override
@@ -55,7 +56,7 @@ protected final void scanAndroidManifest(XmlFile file) {
5556
// readPermission and writePermission have priority over permission
5657
// order matters to handle the case where the 3 are defined and readPermission and writePermission are equal
5758
final List<Node> nodes = Stream.of("readPermission", "writePermission", "permission")
58-
.map(s -> attributes.getNamedItemNS(ANDROID_NS, s))
59+
.map(s -> attributes.getNamedItemNS(ANDROID_MANIFEST_XMLNS, s))
5960
.filter(Objects::nonNull)
6061
.collect(Collectors.toList());
6162
reportIssue(

0 commit comments

Comments
 (0)