Skip to content

Commit e58a858

Browse files
committed
Add support for Slices
1 parent d43242d commit e58a858

File tree

3 files changed

+104
-15
lines changed

3 files changed

+104
-15
lines changed

java/ql/lib/semmle/code/java/security/ImplicitPendingIntents.qll

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22

33
import java
44
private import semmle.code.java.dataflow.ExternalFlow
5-
private import semmle.code.java.dataflow.TaintTracking
6-
private import semmle.code.java.frameworks.android.Intent
75

8-
private class PendingIntentModels extends SinkModelCsv {
6+
private class PendingIntentCreationModels extends SinkModelCsv {
97
override predicate row(string row) {
108
row =
119
[
@@ -17,6 +15,16 @@ private class PendingIntentModels extends SinkModelCsv {
1715
}
1816
}
1917

18+
private class PendingIntentSentSinkModels extends SinkModelCsv {
19+
override predicate row(string row) {
20+
row =
21+
[
22+
"androidx.slice;SliceProvider;true;onBindSlice;;;ReturnValue;pending-intent-sent",
23+
"androidx.slice;SliceProvider;true;onCreatePermissionRequest;;;ReturnValue;pending-intent-sent"
24+
]
25+
}
26+
}
27+
2028
// TODO: Remove when https://github.com/github/codeql/pull/6397 gets merged
2129
private class DefaultIntentRedirectionSinkModel extends SinkModelCsv {
2230
override predicate row(string row) {

java/ql/lib/semmle/code/java/security/ImplicitPendingIntentsQuery.qll

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,7 @@ class ImplicitPendingIntentStartConf extends TaintTracking::Configuration {
1717
source.asExpr() instanceof ImplicitPendingIntentCreation
1818
}
1919

20-
override predicate isSink(DataFlow::Node sink) {
21-
sink instanceof IntentStartSink and
22-
// startService can't actually start implicit intents since API 21
23-
not exists(MethodAccess ma, Method m |
24-
ma.getMethod() = m and
25-
m.getDeclaringType().getASupertype*() instanceof TypeContext and
26-
m.hasName("startService") and
27-
sink.asExpr() = ma.getArgument(0)
28-
)
29-
}
20+
override predicate isSink(DataFlow::Node sink) { sink instanceof SendPendingIntent }
3021

3122
override predicate isSanitizer(DataFlow::Node sanitizer) {
3223
sanitizer instanceof ExplicitIntentSanitizer
@@ -49,8 +40,19 @@ private class ImplicitPendingIntentCreation extends Expr {
4940
}
5041
}
5142

52-
private class IntentStartSink extends DataFlow::Node {
53-
IntentStartSink() { sinkNode(this, "intent-start") }
43+
private class SendPendingIntent extends DataFlow::Node {
44+
SendPendingIntent() {
45+
sinkNode(this, "intent-start") and
46+
// startService can't actually start implicit intents since API 21
47+
not exists(MethodAccess ma, Method m |
48+
ma.getMethod() = m and
49+
m.getDeclaringType().getASupertype*() instanceof TypeContext and
50+
m.hasName("startService") and
51+
this.asExpr() = ma.getArgument(0)
52+
)
53+
or
54+
sinkNode(this, "pending-intent-sent")
55+
}
5456
}
5557

5658
private class ImplicitPendingIntentConf extends DataFlow2::Configuration {

java/ql/test/query-tests/security/CWE-927/ImplicitPendingIntentsTest.java

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
11
package com.example.test;
22

3+
import java.io.FileNotFoundException;
34
import android.app.Activity;
45
import android.app.PendingIntent;
56
import android.content.Context;
67
import android.content.Intent;
8+
import android.content.res.AssetFileDescriptor;
9+
import android.net.Uri;
10+
import android.os.Bundle;
11+
import android.os.CancellationSignal;
12+
import android.os.RemoteException;
13+
import androidx.core.graphics.drawable.IconCompat;
14+
import androidx.slice.Slice;
15+
import androidx.slice.SliceProvider;
16+
import androidx.slice.builders.ListBuilder;
17+
import androidx.slice.builders.SliceAction;
18+
import androidx.slice.core.SliceHints.ImageMode;
719

820
public class ImplicitPendingIntentsTest {
921

@@ -75,4 +87,71 @@ public static void test(Context ctx) throws PendingIntent.CanceledException {
7587
}
7688

7789
}
90+
91+
static class TestSliceProvider extends SliceProvider {
92+
93+
@Override
94+
public Slice onBindSlice(Uri sliceUri) {
95+
if (sliceUri.getAuthority().equals("1")) {
96+
Intent baseIntent = new Intent();
97+
PendingIntent pi = PendingIntent.getActivity(getContext(), 0, baseIntent, 0);
98+
SliceAction activityAction = SliceAction.createDeeplink(pi, null, 0, "Test");
99+
ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, null);
100+
listBuilder.addRow(new ListBuilder.RowBuilder().setTitle("Title")
101+
.setPrimaryAction(activityAction));
102+
return listBuilder.build(); // $hasTaintFlow
103+
104+
} else if (sliceUri.getAuthority().equals("2")) {
105+
Intent baseIntent = new Intent(getContext(), Activity.class); // Sanitizer
106+
PendingIntent pi = PendingIntent.getActivity(getContext(), 0, baseIntent, 0);
107+
SliceAction activityAction = SliceAction.createDeeplink(pi, null, 0, "Test");
108+
ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, null);
109+
listBuilder.addRow(new ListBuilder.RowBuilder().setTitle("Title")
110+
.setPrimaryAction(activityAction));
111+
return listBuilder.build(); // Safe
112+
113+
} else {
114+
Intent baseIntent = new Intent();
115+
PendingIntent pi = PendingIntent.getActivity(getContext(), 0, baseIntent,
116+
PendingIntent.FLAG_IMMUTABLE); // Sanitizer
117+
SliceAction activityAction = SliceAction.createDeeplink(pi, null, 0, "Test");
118+
ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, null);
119+
listBuilder.addRow(new ListBuilder.RowBuilder().setTitle("Title")
120+
.setPrimaryAction(activityAction));
121+
return listBuilder.build(); // Safe
122+
}
123+
}
124+
125+
@Override
126+
public PendingIntent onCreatePermissionRequest(Uri sliceUri, String callingPackage) {
127+
if (sliceUri.getAuthority().equals("1")) {
128+
Intent baseIntent = new Intent();
129+
PendingIntent pi = PendingIntent.getActivity(getContext(), 0, baseIntent, 0);
130+
return pi; // $hasTaintFlow
131+
} else {
132+
Intent baseIntent = new Intent();
133+
PendingIntent pi = PendingIntent.getActivity(getContext(), 0, baseIntent,
134+
PendingIntent.FLAG_IMMUTABLE); // Sanitizer
135+
return pi; // Safe
136+
}
137+
}
138+
139+
// Implementations needed for compilation
140+
@Override
141+
public boolean onCreateSliceProvider() {
142+
return true;
143+
}
144+
145+
@Override
146+
public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts,
147+
CancellationSignal signal) throws RemoteException, FileNotFoundException {
148+
return null;
149+
}
150+
151+
@Override
152+
public Bundle call(String authority, String method, String arg, Bundle extras)
153+
throws RemoteException {
154+
return null;
155+
}
156+
}
78157
}

0 commit comments

Comments
 (0)