Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SPRI002 [JAVA] Google Tracker - A reprendre par Snapp' #1

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import io.ecocode.java.checks.power.SaveModeAwarenessRule;
import io.ecocode.java.checks.power.ChargeAwarenessRule;
import io.ecocode.java.checks.sobriety.*;
import io.ecocode.java.checks.social.privacy.*;
import org.sonar.plugins.java.api.JavaCheck;

import java.util.ArrayList;
Expand Down Expand Up @@ -83,7 +84,8 @@ public static List<Class<? extends JavaCheck>> getJavaChecks() {
JobCoalesceRule.class,
SaveModeAwarenessRule.class,
ThriftyGeolocationCriteriaRule.class,
UncachedDataReceptionRule.class
UncachedDataReceptionRule.class,
GoogleTrackerRule.class
));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* ecoCode SonarQube Plugin
* Copyright (C) 2020-2021 Snapp' - Université de Pau et des Pays de l'Adour
* mailto: contact@ecocode.io
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package io.ecocode.java.checks.social.privacy;

import io.ecocode.java.checks.helpers.TreeHelper;
import org.sonar.check.Rule;
import org.sonar.plugins.java.api.JavaFileScanner;
import org.sonar.plugins.java.api.JavaFileScannerContext;
import org.sonar.plugins.java.api.tree.*;

import java.util.ArrayList;
import java.util.List;

/**
* Check the presence of the import com.google.android.gms.analytics.Tracker
* Importing the com.google.android.gms.analytics.Tracker class means that
* the app sends hits to Google Analytics. It is not necessarily sensitive
* information, but it is a first step towards Google Ads and hence this
* practice should be discouraged at early stage.
*/
@Rule(key = "SPRI002", name = "ecocodeGoogleTracker")
public class GoogleTrackerRule extends BaseTreeVisitor implements JavaFileScanner {

private static final String ERROR_MESSAGE_GGL_TRACKER = "Using com.google.android.gms.analytics.* is a potential threat for privacy.";
private static final String ERROR_MESSAGE_FIREBASE_TRACKER = "Using com.google.firebase.analytics.* is a potential threat for privacy.";

@Override
public void scanFile(JavaFileScannerContext context) {
CompilationUnitTree cut = context.getTree();

GoogleTrackerImports googleTrackerImport = new GoogleTrackerImports();

for (ImportClauseTree importClauseTree : cut.imports()) {
ImportTree importTree = null;

if (importClauseTree.is(Tree.Kind.IMPORT)) {
importTree = (ImportTree) importClauseTree;
}

if (importTree == null) {
// discard empty statements, which can be part of imports
continue;
}

googleTrackerImport.collectTrackerImport(importTree);
}

handleResult(context, googleTrackerImport);
scan(cut);
}

private void handleResult(JavaFileScannerContext context, GoogleTrackerImports googleTrackerImport) {
if (googleTrackerImport.hasTrackerImports()) {
if (googleTrackerImport.hasGoogleTrackerImports()) {
for (ImportTree importTree : googleTrackerImport.getGoogleTrackerImports()) {
context.reportIssue(this, importTree, ERROR_MESSAGE_GGL_TRACKER);
}
}

if (googleTrackerImport.hasFirebaseTrackerImports()) {
for (ImportTree importTree : googleTrackerImport.getFirebaseTrackerImports()) {
context.reportIssue(this, importTree, ERROR_MESSAGE_FIREBASE_TRACKER);
}
}
}
}

private class GoogleTrackerImports {
private static final String IMPORT_STR_GGL_TRCK = "com.google.android.gms.analytics";
private static final String IMPORT_STR_FIREBASE_TRCK = "com.google.firebase.analytics";

private final List<ImportTree> gglTrListTree = new ArrayList<>();
private final List<ImportTree> firebaseTrListTree = new ArrayList<>();

public List<ImportTree> getGoogleTrackerImports() {
return gglTrListTree;
}

public List<ImportTree> getFirebaseTrackerImports() {
return firebaseTrListTree;
}

public boolean hasTrackerImports() {
return hasGoogleTrackerImports() || hasFirebaseTrackerImports();
}

public boolean hasGoogleTrackerImports() {
return !gglTrListTree.isEmpty();
}

public boolean hasFirebaseTrackerImports() {
return !firebaseTrListTree.isEmpty();
}

public void collectTrackerImport(ImportTree importTree) {
String importName = TreeHelper.fullQualifiedName(importTree.qualifiedIdentifier());
if (importName.startsWith(IMPORT_STR_GGL_TRCK)) {
gglTrListTree.add(importTree);
} else if (importName.startsWith(IMPORT_STR_FIREBASE_TRCK)) {
firebaseTrListTree.add(importTree);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<img src="http://www.neomades.com/extern/partage/ecoCode/2sur5_1x.png">
<p>
Importing the <code>com.google.android.gms.analytics.Tracker</code> class means that the app sends hits to Google Analytics. It is not necessarily sensitive information, but it is a first step towards Google Ads and hence this practice should be discouraged at early stage.
</p>
<h2>Noncompliant Code Example</h2>
Import of Google Analytics :
<pre>
import com.google.android.gms.analytics.Tracker
</pre>
Import of Firebase Analytics :
<pre>
import com.google.firebase.analytics
</pre>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"title": "Privacy: Google Tracker",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "20min"
},
"tags": [
"privacy",
"social",
"ecocode"
],
"defaultSeverity": "Minor"
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"ESOB010",
"ESOB011",
"ESOB012",
"EBOT004"
"EBOT004",
"SPRI002"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import com.google.android.gms.analytics.Tracker; // Noncompliant {{Using com.google.android.gms.analytics.* is a potential threat for privacy.}}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import com.google.firebase.analytics.FirebaseAnalytics; // Noncompliant {{Using com.google.firebase.analytics.* is a potential threat for privacy.}}
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,12 @@ private void assertRuleProperties(Repository repository) {
assertThat(uncachedDataReception.name()).isEqualTo("Bottleneck: Uncached Data Reception");
assertThat(uncachedDataReception.debtRemediationFunction().type()).isEqualTo(Type.CONSTANT_ISSUE);
assertThat(uncachedDataReception.type()).isEqualTo(RuleType.CODE_SMELL);

Rule googleTrackerRule = repository.rule("SPRI002");
assertThat(googleTrackerRule).isNotNull();
assertThat(googleTrackerRule.name()).isEqualTo("Privacy: Google Tracker");
assertThat(googleTrackerRule.debtRemediationFunction().type()).isEqualTo(Type.CONSTANT_ISSUE);
assertThat(googleTrackerRule.type()).isEqualTo(RuleType.CODE_SMELL);
}

private void assertAllRuleParametersHaveDescription(Repository repository) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.ecocode.java.checks.social.privacy;

import org.junit.Test;
import org.sonar.java.checks.verifier.JavaCheckVerifier;

public class GoogleTrackerRuleTest {

@Test
public void verify() {
JavaCheckVerifier.newVerifier().onFile("src/test/files/social/privacy/GoogleTrackerCheck.java")
.withCheck(new GoogleTrackerRule())
.verifyIssues();

JavaCheckVerifier.newVerifier().onFile("src/test/files/social/privacy/GoogleTrackerFirebaseCheck.java")
.withCheck(new GoogleTrackerRule())
.verifyIssues();
}
}
6 changes: 3 additions & 3 deletions src/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ services:
- type: bind
source: ./java-plugin/target/ecocode-java-plugin-1.0.0-SNAPSHOT.jar
target: /opt/sonarqube/extensions/plugins/ecocode-java-plugin-1.0.0-SNAPSHOT.jar
#- type: bind
# source: ./php-plugin/target/ecocode-php-plugin-1.0.0-SNAPSHOT.jar
# target: /opt/sonarqube/extensions/plugins/ecocode-php-plugin-1.0.0-SNAPSHOT.jar
- type: bind
source: ./php-plugin/target/ecocode-php-plugin-1.0.0-SNAPSHOT.jar
target: /opt/sonarqube/extensions/plugins/ecocode-php-plugin-1.0.0-SNAPSHOT.jar
- type: bind
source: ./python-plugin/target/ecocode-python-plugin-1.0.0-SNAPSHOT.jar
target: /opt/sonarqube/extensions/plugins/ecocode-python-plugin-1.0.0-SNAPSHOT.jar
Expand Down
2 changes: 1 addition & 1 deletion src/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

<modules>
<module>java-plugin</module>
<!--<module>php-plugin</module>-->
<module>php-plugin</module>
<module>python-plugin</module>
<module>codenarc-converter</module>
<module>android-plugin</module>
Expand Down