github / github/codeql

False Negative: ImplicitPendingIntents.ql misses mutable implicit PendingIntents once they are stored, enriched, or sent through slightly noisier code paths.

Open
#21,548 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
CodeQL
Stars
10.1k
Forks
2.1k
Avg merge
2d 15h
Merged PRs (30d)
141

Description

# False Negative: ImplicitPendingIntents.ql misses mutable implicit PendingIntents once they are stored, enriched, or sent through slightly noisier code paths.

Version
codeql 2.24.3

## Checker
- Checker id: `Security/CWE/CWE-927/ImplicitPendingIntents.ql`
- Checker description: This checker detects when an implicit Intent is created and then flows into a PendingIntent that is sent to an unspecified third party.

## Description of the false negative
These cases still create an implicit `Intent`, wrap it in a mutable `PendingIntent`, and then send that `PendingIntent` to an unspecified recipient. The extra parcelable write, field store, or unrelated array read does not change the security outcome.

## Affected test cases
### `PosCase1.java`
The intent remains implicit when it is wrapped in the `PendingIntent` and sent onward. The extra statements do not make it safe.

```java
// Implicit Intent with mutable PendingIntent sent to third party, including allowed implicit read of parcelable extra, should be flagged as unsafe.
package scensct.core.pos;

import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Parcelable;

public class PosCase1 {
public void sendPendingIntentToThirdParty(Context context, Parcelable extraData) {
// Implicit Intent creation
Intent implicitIntent = new Intent("com.example.ACTION_TRIGGER");
// Allowed implicit read of parcelable extra (policy allows reading parcelable extras)
implicitIntent.putExtra("key", extraData);
// Create mutable PendingIntent from implicit Intent
PendingIntent pending = PendingIntent.getActivity(
context,
0,
implicitIntent,
PendingIntent.FLAG_MUTABLE
);
// Send to unspecified third party via PendingIntent.send()
try {
pending.send();
} catch (PendingIntent.CanceledException e) {
// Handle exception
}
}
}
```

### `PosCase2.java`
This still creates a mutable implicit `PendingIntent` for an unspecified recipient. The issue is unchanged.

```java
// Implicit Intent with mutable PendingIntent sent to third party, including implicit read of PendingIntent field, should be flagged as unsafe.
package scensct.core.pos;

import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;

public class PosCase2 {
static class Container {
PendingIntent pendingIntentField;
}

public void sendPendingIntentToThirdParty(Context context, Container container) {
// Implicit Intent creation
Intent implicitIntent = new Intent("com.example.ACTION_TRIGGER");
// Create mutable PendingIntent from implicit Intent
PendingIntent pending = PendingIntent.getActivity(
context,
0,
implicitIntent,
PendingIntent.FLAG_MUTABLE
);
// Implicit read of PendingIntent field (reading container.pendingIntentField)
container.pendingIntentField = pending;
// Send to unspecified third party via PendingIntent.send()
try {
container.pendingIntentField.send();
} catch (PendingIntent.CanceledException e) {
// Handle exception
}
}
}
```

### `PosCase3.java`
The added statements are incidental. The important part is that the implicit intent still flows into a third-party `PendingIntent`.

```java
// Implicit Intent with mutable PendingIntent sent to third party, including implicit read of Intent array, should be flagged as unsafe.
package scensct.core.pos;

import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;

public class PosCase3 {
public void sendPendingIntentToThirdParty(Context context, Intent[] intentArray, int index) {
// Implicit Intent creation
Intent implicitIntent = new Intent("com.example.ACTION_TRIGGER");
// Create mutable PendingIntent from implicit Intent
PendingIntent pending = PendingIntent.getActivity(
context,
0,
implicitIntent,
PendingIntent.FLAG_MUTABLE
);
// Implicit read of Intent array (accessing intentArray[index])
Intent retrievedIntent = intentArray[index];
// Send to unspecified third party via PendingIntent.send()
try {
pending.send();
} catch (PendingIntent.CanceledException e) {
// Handle exception
}
}
}
```

## Cause analysis
The query appears too dependent on a direct, linear construction-to-send pattern. Once the `PendingIntent` is written to a field, accompanied by another benign read, or the `Intent` is slightly enriched before wrapping, the result disappears.

That is too brittle for `Security/CWE/CWE-927/ImplicitPendingIntents.ql`. Real Android code rarely keeps these flows in a single minimal statement sequence.

## References
None known.

Contributor guide

Open the contributing guide

Research direction

Start with Security/CWE/CWE-927/ImplicitPendingIntents.ql and the affected PosCase1.java, PosCase2.java, and PosCase3.java examples. Reproduce the false negatives and trace how parcelable writes, field storage, and array reads affect the construction-to-send flow; done means these mutable implicit PendingIntents sent to unspecified recipients are flagged.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
mobile-dev, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.