Merge pull request #15281 from joefarebrother/android-sensitive-ui-notif

Java: Add query for exposure of sensitive information to android notifiactions
This commit is contained in:
Joe Farebrother
2024-01-26 16:42:55 +00:00
committed by GitHub
33 changed files with 887 additions and 596 deletions

View File

@@ -30,6 +30,48 @@ extensions:
- ["android.app", "FragmentTransaction", True, "replace", "(int,Class,Bundle,String)", "", "Argument[1]", "fragment-injection", "manual"]
- ["android.app", "FragmentTransaction", True, "replace", "(int,Fragment)", "", "Argument[1]", "fragment-injection", "manual"]
- ["android.app", "FragmentTransaction", True, "replace", "(int,Fragment,String)", "", "Argument[1]", "fragment-injection", "manual"]
- ["android.app", "Notification$Action", True, "Action", "(int,CharSequence,PendingIntent)", "", "Argument[1]", "notification", "manual"]
- ["android.app", "Notification$Action$Builder", True, "Builder", "(Icon,CharSequence,PendingIntent)", "", "Argument[1]", "notification", "manual"]
- ["android.app", "Notification$Action$Builder", True, "Builder", "(int,CharSequence,PendingIntent)", "", "Argument[1]", "notification", "manual"]
- ["android.app", "Notification$Action$Builder", True, "addExtras", "(Bundle)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$BigPictureStyle", True, "setBigContentTitle", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$BigPictureStyle", True, "setContentDescription", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$BigPictureStyle", True, "setSummaryText", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$BigTextStyle", True, "bigText", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$BigTextStyle", True, "setBigContentTitle", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$BigTextStyle", True, "setSummaryText", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$Builder", True, "addAction", "(int,CharSequence,PendingIntent)", "", "Argument[1]", "notification", "manual"]
- ["android.app", "Notification$Builder", True, "addExtras", "(Bundle)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$Builder", True, "setCategory", "(String)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$Builder", True, "setChannelId", "(String)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$Builder", True, "setContent", "(RemoteViews)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$Builder", True, "setContentInfo", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$Builder", True, "setContentText", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$Builder", True, "setContentTitle", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$Builder", True, "setCustomBigContentView", "(RemoteViews)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$Builder", True, "setCustomContentView", "(RemoteViews)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$Builder", True, "setCustomHeadsUpContentView", "(RemoteViews)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$Builder", True, "setExtras", "(Bundle)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$Builder", True, "setGroup", "(String)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$Builder", True, "setRemoteInputHistory", "(CharSequence[])", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$Builder", True, "setSettingsText", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$Builder", True, "setSortKey", "(String)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$Builder", True, "setSubText", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$Builder", True, "setTicker", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$Builder", True, "setTicker", "(CharSequence,RemoteViews)", "", "Argument[0..1]", "notification", "manual"]
- ["android.app", "Notification$CallStyle", True, "setVerificationText", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$InboxStyle", True, "addLine", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$InboxStyle", True, "setBigContentTitle", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$InboxStyle", True, "setSummaryText", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$MediaStyle", True, "setRemotePlaybackInfo", "(CharSequence,int,PendingIntent)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$MessagingStyle", True, "MessagingStyle", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$MessagingStyle", True, "addMessage", "(CharSequence,long,CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$MessagingStyle", True, "addMessage", "(CharSequence,long,CharSequence)", "", "Argument[2]", "notification", "manual"]
- ["android.app", "Notification$MessagingStyle", True, "addMessage", "(CharSequence,long,Person)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$MessagingStyle", True, "setConversationTitle", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$MessagingStyle$Message", True, "Message", "(CharSequence,long,CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "Notification$MessagingStyle$Message", True, "Message", "(CharSequence,long,CharSequence)", "", "Argument[2]", "notification", "manual"]
- ["android.app", "Notification$MessagingStyle$Message", True, "Message", "(CharSequence,long,Person)", "", "Argument[0]", "notification", "manual"]
- ["android.app", "NotificationManager", True, "notify", "(String,int,Notification)", "", "Argument[2]", "pending-intents", "manual"]
- ["android.app", "NotificationManager", True, "notify", "(int,Notification)", "", "Argument[1]", "pending-intents", "manual"]
- ["android.app", "NotificationManager", True, "notifyAsPackage", "(String,String,int,Notification)", "", "Argument[3]", "pending-intents", "manual"]
@@ -38,6 +80,7 @@ extensions:
- ["android.app", "PendingIntent", False, "send", "(Context,int,Intent,PendingIntent$OnFinished,Handler)", "", "Argument[2]", "pending-intents", "manual"]
- ["android.app", "PendingIntent", False, "send", "(Context,int,Intent,PendingIntent$OnFinished,Handler,String)", "", "Argument[2]", "pending-intents", "manual"]
- ["android.app", "PendingIntent", False, "send", "(Context,int,Intent,PendingIntent$OnFinished,Handler,String,Bundle)", "", "Argument[2]", "pending-intents", "manual"]
- addsTo:
pack: codeql/java-all
extensible: summaryModel

View File

@@ -7,8 +7,50 @@ extensions:
- ["androidx.core.app", "AlarmManagerCompat", True, "setAndAllowWhileIdle", "", "", "Argument[3]", "pending-intents", "manual"]
- ["androidx.core.app", "AlarmManagerCompat", True, "setExact", "", "", "Argument[3]", "pending-intents", "manual"]
- ["androidx.core.app", "AlarmManagerCompat", True, "setExactAndAllowWhileIdle", "", "", "Argument[3]", "pending-intents", "manual"]
- ["androidx.core.app", "NotificationCompat$Action", True, "Action", "(int,CharSequence,PendingIntent)", "", "Argument[1]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$Action$Builder", True, "Builder", "(IconCompat,CharSequence,PendingIntent)", "", "Argument[1]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$Action$Builder", True, "Builder", "(int,CharSequence,PendingIntent)", "", "Argument[1]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$Action$Builder", True, "addExtras", "(Bundle)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$BigPictureStyle", True, "setBigContentTitle", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$BigPictureStyle", True, "setContentDescription", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$BigPictureStyle", True, "setSummaryText", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$BigTextStyle", True, "bigText", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$BigTextStyle", True, "setBigContentTitle", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$BigTextStyle", True, "setSummaryText", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$Builder", True, "addAction", "(int,CharSequence,PendingIntent)", "", "Argument[1]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$Builder", True, "addExtras", "(Bundle)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$Builder", True, "setCategory", "(String)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$Builder", True, "setChannelId", "(String)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$Builder", True, "setContent", "(RemoteViews)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$Builder", True, "setContentInfo", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$Builder", True, "setContentText", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$Builder", True, "setContentTitle", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$Builder", True, "setCustomBigContentView", "(RemoteViews)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$Builder", True, "setCustomContentView", "(RemoteViews)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$Builder", True, "setCustomHeadsUpContentView", "(RemoteViews)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$Builder", True, "setExtras", "(Bundle)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$Builder", True, "setGroup", "(String)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$Builder", True, "setRemoteInputHistory", "(CharSequence[])", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$Builder", True, "setSettingsText", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$Builder", True, "setSortKey", "(String)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$Builder", True, "setSubText", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$Builder", True, "setTicker", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$Builder", True, "setTicker", "(CharSequence,RemoteViews)", "", "Argument[0..1]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$CallStyle", True, "setVerificationText", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$InboxStyle", True, "addLine", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$InboxStyle", True, "setBigContentTitle", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$InboxStyle", True, "setSummaryText", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$MessagingStyle", True, "addMessage", "(CharSequence,long,CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$MessagingStyle", True, "addMessage", "(CharSequence,long,CharSequence)", "", "Argument[2]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$MessagingStyle", True, "addMessage", "(CharSequence,long,Person)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$MessagingStyle", True, "setConversationTitle", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$MessagingStyle", True, "MessagingStyle", "(CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$MessagingStyle$Message", True, "Message", "(CharSequence,long,CharSequence)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$MessagingStyle$Message", True, "Message", "(CharSequence,long,CharSequence)", "", "Argument[2]", "notification", "manual"]
- ["androidx.core.app", "NotificationCompat$MessagingStyle$Message", True, "Message", "(CharSequence,long,Person)", "", "Argument[0]", "notification", "manual"]
- ["androidx.core.app", "NotificationManagerCompat", True, "notify", "(String,int,Notification)", "", "Argument[2]", "pending-intents", "manual"]
- ["androidx.core.app", "NotificationManagerCompat", True, "notify", "(int,Notification)", "", "Argument[1]", "pending-intents", "manual"]
- addsTo:
pack: codeql/java-all
extensible: summaryModel

View File

@@ -0,0 +1,22 @@
/** Definitions for Android Sensitive UI queries */
import java
private import semmle.code.java.dataflow.ExternalFlow
private import semmle.code.java.dataflow.TaintTracking
private import semmle.code.java.security.SensitiveActions
/** A configuration for tracking sensitive information to system notifications. */
private module NotificationTrackingConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SensitiveExpr }
predicate isSink(DataFlow::Node sink) { sinkNode(sink, "notification") }
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
isSink(node) and exists(c)
}
predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
}
/** Taint tracking flow for sensitive data flowing to system notifications. */
module NotificationTracking = TaintTracking::Global<NotificationTrackingConfig>;

View File

@@ -0,0 +1,8 @@
// BAD: `password` is exposed in a notification.
void confirmPassword(String password) {
NotificationManager manager = NotificationManager.from(this);
manager.send(
new Notification.Builder(this, CHANNEL_ID)
.setContentText("Your password is: " + password)
.build());
}

View File

@@ -0,0 +1,34 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
Sensitive information such as passwords or two-factor authentication (2FA) codes should not be exposed in a system notification.
Notifications should not be considered secure, as other untrusted applications may be able to use a
<code>NotificationListenerService</code> to read the contents of notifications.
</p>
</overview>
<recommendation>
<p>
Do not expose sensitive data in notifications.
</p>
</recommendation>
<example>
<p>
In the following sample, the <code>password</code> is sent as part of a notification.
This can allow another application to read this password.
</p>
<sample src="AndroidSensitiveNotifications.java"/>
</example>
<references>
<li>
OWASP Mobile Application Security: <a href="https://mas.owasp.org/MASTG/Android/0x05d-Testing-Data-Storage/#app-notifications">Android Data Storage - Application Notifications</a>
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,21 @@
/**
* @name Exposure of sensitive information to notifications
* @id java/android/sensitive-notification
* @kind path-problem
* @description Sensitive information exposed in a system notification can be read by an unauthorized application.
* @problem.severity error
* @precision medium
* @security-severity 6.5
* @tags security
* external/cwe/cwe-200
*/
import java
import java
import semmle.code.java.security.SensitiveUiQuery
import NotificationTracking::PathGraph
from NotificationTracking::PathNode source, NotificationTracking::PathNode sink
where NotificationTracking::flowPath(source, sink)
select sink, source, sink, "This $@ is exposed in a system notification.", source,
"sensitive information"

View File

@@ -0,0 +1,4 @@
---
category: newQuery
---
* Added a new query `java/android/sensitive-notification` to detect instances of sensitive data being exposed through Android notifications.

View File

@@ -942,14 +942,28 @@ public class Test {
// "androidx.core.app;NotificationCompat$BigPictureStyle;true;bigLargeIcon;;;Argument[this];ReturnValue;value;manual"
NotificationCompat.BigPictureStyle out = null;
NotificationCompat.BigPictureStyle in = (NotificationCompat.BigPictureStyle) source();
out = in.bigLargeIcon(null);
out = in.bigLargeIcon((Bitmap)null);
sink(out); // $ hasValueFlow
}
{
// "androidx.core.app;NotificationCompat$BigPictureStyle;true;bigLargeIcon;;;Argument[this];ReturnValue;value;manual"
NotificationCompat.BigPictureStyle out = null;
NotificationCompat.BigPictureStyle in = (NotificationCompat.BigPictureStyle) source();
out = in.bigLargeIcon((Icon)null);
sink(out); // $ hasValueFlow
}
{
// "androidx.core.app;NotificationCompat$BigPictureStyle;true;bigPicture;;;Argument[this];ReturnValue;value;manual"
NotificationCompat.BigPictureStyle out = null;
NotificationCompat.BigPictureStyle in = (NotificationCompat.BigPictureStyle) source();
out = in.bigPicture(null);
out = in.bigPicture((Bitmap)null);
sink(out); // $ hasValueFlow
}
{
// "androidx.core.app;NotificationCompat$BigPictureStyle;true;bigPicture;;;Argument[this];ReturnValue;value;manual"
NotificationCompat.BigPictureStyle out = null;
NotificationCompat.BigPictureStyle in = (NotificationCompat.BigPictureStyle) source();
out = in.bigPicture((Icon)null);
sink(out); // $ hasValueFlow
}
{
@@ -1040,7 +1054,14 @@ public class Test {
// "androidx.core.app;NotificationCompat$Builder;true;addPerson;;;Argument[this];ReturnValue;value;manual"
NotificationCompat.Builder out = null;
NotificationCompat.Builder in = (NotificationCompat.Builder) source();
out = in.addPerson(null);
out = in.addPerson((androidx.core.app.Person)null);
sink(out); // $ hasValueFlow
}
{
// "androidx.core.app;NotificationCompat$Builder;true;addPerson;;;Argument[this];ReturnValue;value;manual"
NotificationCompat.Builder out = null;
NotificationCompat.Builder in = (NotificationCompat.Builder) source();
out = in.addPerson((String)null);
sink(out); // $ hasValueFlow
}
{
@@ -1252,7 +1273,14 @@ public class Test {
// "androidx.core.app;NotificationCompat$Builder;true;setLargeIcon;;;Argument[this];ReturnValue;value;manual"
NotificationCompat.Builder out = null;
NotificationCompat.Builder in = (NotificationCompat.Builder) source();
out = in.setLargeIcon(null);
out = in.setLargeIcon((Bitmap)null);
sink(out); // $ hasValueFlow
}
{
// "androidx.core.app;NotificationCompat$Builder;true;setLargeIcon;;;Argument[this];ReturnValue;value;manual"
NotificationCompat.Builder out = null;
NotificationCompat.Builder in = (NotificationCompat.Builder) source();
out = in.setLargeIcon((Icon)null);
sink(out); // $ hasValueFlow
}
{

View File

@@ -0,0 +1,129 @@
import android.app.Activity;
import android.app.Notification;
import androidx.core.app.NotificationCompat;
import android.content.Intent;
import android.app.PendingIntent;
import android.widget.RemoteViews;
class Test extends Activity {
void test(String password) {
Notification.Builder builder = new Notification.Builder(this, "");
builder.setContentText(password); // $sensitive-notification
builder.setContentTitle(password); // $sensitive-notification
builder.setContentInfo(password); // $sensitive-notification
Intent intent = new Intent();
intent.putExtra("a", password);
builder.addExtras(intent.getExtras()); // $sensitive-notification
builder.setCategory(password); // $sensitive-notification
builder.setChannelId(password); // $sensitive-notification
builder.setGroup(password); // $sensitive-notification
builder.setExtras(intent.getExtras()); // $sensitive-notification
builder.setGroup(password); // $sensitive-notification
builder.setSortKey(password); // $sensitive-notification
builder.setSettingsText(password); // $sensitive-notification
builder.setRemoteInputHistory(new CharSequence[] { password }); // $sensitive-notification
builder.setTicker(password); // $sensitive-notification
builder.setTicker(password, null); // $sensitive-notification
builder.setStyle(new Notification.BigPictureStyle()
.setContentDescription(password) // $sensitive-notification
.setSummaryText(password) // $sensitive-notification
.setBigContentTitle(password)); // $sensitive-notification
builder.setStyle(new Notification.BigTextStyle()
.bigText(password) // $sensitive-notification
.setSummaryText(password) // $sensitive-notification
.setBigContentTitle(password)); // $sensitive-notification
builder.setStyle(new Notification.InboxStyle()
.addLine(password) // $sensitive-notification
.setBigContentTitle(password) // $sensitive-notification
.setSummaryText(password)); // $sensitive-notification
builder.setStyle(new Notification.MediaStyle()
.setRemotePlaybackInfo(password, 0, null)); // $sensitive-notification
builder.setStyle(
new Notification.MessagingStyle(password) // $sensitive-notification
.setConversationTitle(password) // $sensitive-notification
.addMessage(password, 0, "") // $sensitive-notification
.addMessage(password, 0, (android.app.Person)null) // $sensitive-notification
.addMessage("", 0, password) // $sensitive-notification
.addMessage(new Notification.MessagingStyle.Message(password, 0, "")) // $sensitive-notification
.addMessage(new Notification.MessagingStyle.Message(password, 0, (android.app.Person)null)) // $sensitive-notification
.addMessage(new Notification.MessagingStyle.Message("", 0, password)) // $sensitive-notification
);
builder.addAction(0, password, null); // $sensitive-notification
builder.addAction(new Notification.Action(0, password, null)); // $sensitive-notification
builder.addAction(new Notification.Action.Builder(0, password, null) // $sensitive-notification
.addExtras(intent.getExtras()) // $sensitive-notification
.build());
builder.addAction(new Notification.Action.Builder(null, password, null).build()); // $sensitive-notification
builder.setStyle(Notification.CallStyle.forScreeningCall(null, null, null)
.setVerificationText(password)); // $sensitive-notification
}
void test2(RemoteViews passwordView) {
Notification.Builder builder = new Notification.Builder(this, "");
builder.setContent(passwordView); // $sensitive-notification
builder.setCustomBigContentView(passwordView); // $sensitive-notification
builder.setCustomContentView(passwordView); // $sensitive-notification
builder.setCustomHeadsUpContentView(passwordView); // $sensitive-notification
builder.setTicker("", passwordView); // $sensitive-notification
}
void test3(String password) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "");
builder.setContentText(password); // $sensitive-notification
builder.setContentTitle(password); // $sensitive-notification
builder.setContentInfo(password); // $sensitive-notification
Intent intent = new Intent();
intent.putExtra("a", password);
builder.addExtras(intent.getExtras()); // $sensitive-notification
builder.setCategory(password); // $sensitive-notification
builder.setChannelId(password); // $sensitive-notification
builder.setGroup(password); // $sensitive-notification
builder.setExtras(intent.getExtras()); // $sensitive-notification
builder.setGroup(password); // $sensitive-notification
builder.setSortKey(password); // $sensitive-notification
builder.setSettingsText(password); // $sensitive-notification
builder.setRemoteInputHistory(new CharSequence[] { password }); // $sensitive-notification
builder.setTicker(password); // $sensitive-notification
builder.setTicker(password, null); // $sensitive-notification
builder.setStyle(new NotificationCompat.BigPictureStyle()
.setContentDescription(password) // $sensitive-notification
.setSummaryText(password) // $sensitive-notification
.setBigContentTitle(password)); // $sensitive-notification
builder.setStyle(new NotificationCompat.BigTextStyle()
.bigText(password) // $sensitive-notification
.setSummaryText(password) // $sensitive-notification
.setBigContentTitle(password)); // $sensitive-notification
builder.setStyle(new NotificationCompat.InboxStyle()
.addLine(password) // $sensitive-notification
.setBigContentTitle(password) // $sensitive-notification
.setSummaryText(password)); // $sensitive-notification
builder.setStyle(
new NotificationCompat.MessagingStyle(password) // $sensitive-notification
.setConversationTitle(password) // $sensitive-notification
.addMessage(password, 0, "") // $sensitive-notification
.addMessage(password, 0, (androidx.core.app.Person)null) // $sensitive-notification
.addMessage("", 0, password) // $sensitive-notification
.addMessage(new NotificationCompat.MessagingStyle.Message(password, 0, "")) // $sensitive-notification
.addMessage(new NotificationCompat.MessagingStyle.Message(password, 0, (androidx.core.app.Person)null)) // $sensitive-notification
.addMessage(new NotificationCompat.MessagingStyle.Message("", 0, password)) // $sensitive-notification
);
builder.addAction(0, password, null); // $sensitive-notification
builder.addAction(new NotificationCompat.Action(0, password, null)); // $sensitive-notification
builder.addAction(new NotificationCompat.Action.Builder(0, password, null) // $sensitive-notification
.addExtras(intent.getExtras()) // $sensitive-notification
.build());
builder.addAction(new NotificationCompat.Action.Builder(null, password, null).build()); // $sensitive-notification
builder.setStyle(NotificationCompat.CallStyle.forScreeningCall(null, null, null)
.setVerificationText(password)); // $sensitive-notification
}
}

View File

@@ -0,0 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../../stubs/google-android-9.0.0

View File

@@ -0,0 +1,2 @@
testFailures
failures

View File

@@ -0,0 +1,19 @@
import java
import TestUtilities.InlineExpectationsTest
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.security.SensitiveUiQuery
module SensitiveNotifTest implements TestSig {
string getARelevantTag() { result = "sensitive-notification" }
predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "sensitive-notification" and
exists(DataFlow::Node sink | NotificationTracking::flowTo(sink) |
sink.getLocation() = location and
element = sink.toString() and
value = ""
)
}
}
import MakeTest<SensitiveNotifTest>

View File

@@ -0,0 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../../stubs/apache-commons-lang3-3.7/

View File

@@ -0,0 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../../stubs/google-android-9.0.0

View File

@@ -1 +0,0 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/apache-commons-lang3-3.7/:${testdir}/../../../../../stubs/google-android-9.0.0

View File

@@ -358,6 +358,17 @@ public class Notification implements Parcelable
public RemoteViews createHeadsUpContentView(){ return null; }
public static Notification.Builder recoverBuilder(Context p0, Notification p1){ return null; }
}
static public class CallStyle extends Notification.Style
{
public Notification.CallStyle setAnswerButtonColorHint(int p0){ return null; }
public Notification.CallStyle setDeclineButtonColorHint(int p0){ return null; }
public Notification.CallStyle setIsVideo(boolean p0){ return null; }
public Notification.CallStyle setVerificationIcon(Icon p0){ return null; }
public Notification.CallStyle setVerificationText(CharSequence p0){ return null; }
public static Notification.CallStyle forIncomingCall(Person p0, PendingIntent p1, PendingIntent p2){ return null; }
public static Notification.CallStyle forOngoingCall(Person p0, PendingIntent p1){ return null; }
public static Notification.CallStyle forScreeningCall(Person p0, PendingIntent p1, PendingIntent p2){ return null; }
}
static public class InboxStyle extends Notification.Style
{
public InboxStyle(){}
@@ -371,8 +382,43 @@ public class Notification implements Parcelable
public MediaStyle(){}
public MediaStyle(Notification.Builder p0){}
public Notification.MediaStyle setMediaSession(MediaSession.Token p0){ return null; }
public Notification.MediaStyle setRemotePlaybackInfo(CharSequence p0, int p1, PendingIntent p2){ return null; } // added manually
public Notification.MediaStyle setShowActionsInCompactView(int... p0){ return null; }
}
static public class MessagingStyle extends Notification.Style
{
protected MessagingStyle() {}
public CharSequence getConversationTitle(){ return null; }
public CharSequence getUserDisplayName(){ return null; }
public List<Notification.MessagingStyle.Message> getHistoricMessages(){ return null; }
public List<Notification.MessagingStyle.Message> getMessages(){ return null; }
public MessagingStyle(CharSequence p0){}
public MessagingStyle(Person p0){}
public Notification.MessagingStyle addHistoricMessage(Notification.MessagingStyle.Message p0){ return null; }
public Notification.MessagingStyle addMessage(CharSequence p0, long p1, CharSequence p2){ return null; }
public Notification.MessagingStyle addMessage(CharSequence p0, long p1, Person p2){ return null; }
public Notification.MessagingStyle addMessage(Notification.MessagingStyle.Message p0){ return null; }
public Notification.MessagingStyle setConversationTitle(CharSequence p0){ return null; }
public Notification.MessagingStyle setGroupConversation(boolean p0){ return null; }
public Person getUser(){ return null; }
public boolean isGroupConversation(){ return false; }
public static int MAXIMUM_RETAINED_MESSAGES = 0;
static public class Message
{
protected Message() {}
public Bundle getExtras(){ return null; }
public CharSequence getSender(){ return null; }
public CharSequence getText(){ return null; }
public Message(CharSequence p0, long p1, CharSequence p2){}
public Message(CharSequence p0, long p1, Person p2){}
public Notification.MessagingStyle.Message setData(String p0, Uri p1){ return null; }
public Person getSenderPerson(){ return null; }
public String getDataMimeType(){ return null; }
public Uri getDataUri(){ return null; }
public long getTimestamp(){ return 0; }
public static List<Notification.MessagingStyle.Message> getMessagesFromBundleArray(Parcelable[] p0){ return null; }
}
}
static public interface Extender
{
Notification.Builder extend(Notification.Builder p0);

View File

@@ -0,0 +1,51 @@
// Generated automatically from android.content.pm.ShortcutInfo for testing purposes
package android.content.pm;
import android.content.ComponentName;
import android.content.Intent;
import android.content.LocusId;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
import android.os.UserHandle;
import java.util.Set;
public class ShortcutInfo implements Parcelable
{
public CharSequence getDisabledMessage(){ return null; }
public CharSequence getLongLabel(){ return null; }
public CharSequence getShortLabel(){ return null; }
public ComponentName getActivity(){ return null; }
public Intent getIntent(){ return null; }
public Intent[] getIntents(){ return null; }
public LocusId getLocusId(){ return null; }
public PersistableBundle getExtras(){ return null; }
public Set<String> getCategories(){ return null; }
public String getId(){ return null; }
public String getPackage(){ return null; }
public String toString(){ return null; }
public UserHandle getUserHandle(){ return null; }
public boolean hasKeyFieldsOnly(){ return false; }
public boolean isCached(){ return false; }
public boolean isDeclaredInManifest(){ return false; }
public boolean isDynamic(){ return false; }
public boolean isEnabled(){ return false; }
public boolean isImmutable(){ return false; }
public boolean isPinned(){ return false; }
public int describeContents(){ return 0; }
public int getDisabledReason(){ return 0; }
public int getRank(){ return 0; }
public long getLastChangedTimestamp(){ return 0; }
public static Parcelable.Creator<ShortcutInfo> CREATOR = null;
public static String SHORTCUT_CATEGORY_CONVERSATION = null;
public static int DISABLED_REASON_APP_CHANGED = 0;
public static int DISABLED_REASON_BACKUP_NOT_SUPPORTED = 0;
public static int DISABLED_REASON_BY_APP = 0;
public static int DISABLED_REASON_NOT_DISABLED = 0;
public static int DISABLED_REASON_OTHER_RESTORE_ISSUE = 0;
public static int DISABLED_REASON_SIGNATURE_MISMATCH = 0;
public static int DISABLED_REASON_UNKNOWN = 0;
public static int DISABLED_REASON_VERSION_LOWER = 0;
public void writeToParcel(Parcel p0, int p1){}
}

View File

@@ -0,0 +1,37 @@
// Generated automatically from androidx.core.app.Person for testing purposes
package androidx.core.app;
import android.os.Bundle;
import android.os.PersistableBundle;
import androidx.core.graphics.drawable.IconCompat;
public class Person
{
protected Person() {}
public Bundle toBundle(){ return null; }
public CharSequence getName(){ return null; }
public IconCompat getIcon(){ return null; }
public PersistableBundle toPersistableBundle(){ return null; }
public String getKey(){ return null; }
public String getUri(){ return null; }
public String resolveToLegacyUri(){ return null; }
public android.app.Person toAndroidPerson(){ return null; }
public androidx.core.app.Person.Builder toBuilder(){ return null; }
public boolean isBot(){ return false; }
public boolean isImportant(){ return false; }
public static androidx.core.app.Person fromAndroidPerson(android.app.Person p0){ return null; }
public static androidx.core.app.Person fromBundle(Bundle p0){ return null; }
public static androidx.core.app.Person fromPersistableBundle(PersistableBundle p0){ return null; }
static public class Builder
{
public Builder(){}
public androidx.core.app.Person build(){ return null; }
public androidx.core.app.Person.Builder setBot(boolean p0){ return null; }
public androidx.core.app.Person.Builder setIcon(IconCompat p0){ return null; }
public androidx.core.app.Person.Builder setImportant(boolean p0){ return null; }
public androidx.core.app.Person.Builder setKey(String p0){ return null; }
public androidx.core.app.Person.Builder setName(CharSequence p0){ return null; }
public androidx.core.app.Person.Builder setUri(String p0){ return null; }
}
}

View File

@@ -0,0 +1,17 @@
// Generated automatically from androidx.core.content.LocusIdCompat for testing purposes
package androidx.core.content;
import android.content.LocusId;
public class LocusIdCompat
{
protected LocusIdCompat() {}
public LocusId toLocusId(){ return null; }
public LocusIdCompat(String p0){}
public String getId(){ return null; }
public String toString(){ return null; }
public boolean equals(Object p0){ return false; }
public int hashCode(){ return 0; }
public static LocusIdCompat toLocusIdCompat(LocusId p0){ return null; }
}

View File

@@ -0,0 +1,45 @@
// Generated automatically from androidx.core.content.pm.ShortcutInfoCompat for testing purposes
package androidx.core.content.pm;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.os.UserHandle;
import androidx.core.content.LocusIdCompat;
import androidx.core.graphics.drawable.IconCompat;
import java.util.Set;
public class ShortcutInfoCompat
{
public Bundle getTransientExtras(){ return null; }
public CharSequence getDisabledMessage(){ return null; }
public CharSequence getLongLabel(){ return null; }
public CharSequence getShortLabel(){ return null; }
public ComponentName getActivity(){ return null; }
public IconCompat getIcon(){ return null; }
public Intent getIntent(){ return null; }
public Intent[] getIntents(){ return null; }
public LocusIdCompat getLocusId(){ return null; }
public PersistableBundle getExtras(){ return null; }
public Set<String> getCategories(){ return null; }
public ShortcutInfo toShortcutInfo(){ return null; }
public String getId(){ return null; }
public String getPackage(){ return null; }
public UserHandle getUserHandle(){ return null; }
public boolean hasKeyFieldsOnly(){ return false; }
public boolean isCached(){ return false; }
public boolean isDeclaredInManifest(){ return false; }
public boolean isDynamic(){ return false; }
public boolean isEnabled(){ return false; }
public boolean isExcludedFromSurfaces(int p0){ return false; }
public boolean isImmutable(){ return false; }
public boolean isPinned(){ return false; }
public int getDisabledReason(){ return 0; }
public int getExcludedFromSurfaces(){ return 0; }
public int getRank(){ return 0; }
public long getLastChangedTimestamp(){ return 0; }
public static int SURFACE_LAUNCHER = 0;
}

View File

@@ -32,8 +32,9 @@ module KindValidation<KindValidationConfigSig Config> {
// Java-only currently, but may be shared in the future
"bean-validation", "fragment-injection", "groovy-injection", "hostname-verification",
"information-leak", "intent-redirection", "jexl-injection", "jndi-injection",
"mvel-injection", "ognl-injection", "pending-intents", "response-splitting",
"trust-boundary-violation", "template-injection", "xpath-injection", "xslt-injection",
"mvel-injection", "notification", "ognl-injection", "pending-intents",
"response-splitting", "trust-boundary-violation", "template-injection", "xpath-injection",
"xslt-injection",
// JavaScript-only currently, but may be shared in the future
"mongodb.sink", "nosql-injection", "unsafe-deserialization",
// Swift-only currently, but may be shared in the future