android-intent-security — Claude Code skill: guide and setup
Audits AndroidManifest.xml component settings and intent-handling code to stop Intent Redirection and unauthorized component execution.
npx skills add android/skills --skill android-intent-security -a claude-codeWhat android-intent-security does
This skill guides coding agents through auditing Android components: activities, services, broadcast receivers, and content providers. It checks android:exported flags, enforces PendingIntent.FLAG_IMMUTABLE, and blocks unsafe forwarding of untrusted incoming intents into private components.
The security rules require IntentSanitizer when handling nested intents. Safe filtering fails if the project lacks androidx.core:core:1.9.0 or higher, which makes this dependency and a minimum of Android API level 23 strictly necessary for compliance.
The scope is limited strictly to local inter-component and inter-app communication. It does not review network protocols, host-to-server security, or web integration logic.
What it helps with
- audit AndroidManifest.xml for unexported and exported component flags
- prevent Intent Redirection vulnerabilities when handling nested extras
- enforce PendingIntent.FLAG_IMMUTABLE on exported notifications and alarms
- protect ContentProvider access with explicit read and write permissions
Example prompts for the agent
- Audit incoming Intent handling in MainActivity to prevent Intent Redirection.
- Check AndroidManifest.xml components for exposed receivers and missing permissions.
- Review PendingIntent flags across all notification helpers.
How to install android-intent-security
1Skills CLI (Vercel)
npx skills add android/skills --skill android-intent-security -a claude-code2Manually: put the files in place
~/.claude/skills/android-intent-security/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/android-intent-security/
1Skills CLI (Vercel)
npx skills add android/skills --skill android-intent-security -a codex2Manually: put the files in place
.agents/skills/android-intent-security/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add android/skills --skill android-intent-security -a cursor2Manually: put the files in place
.cursor/skills/android-intent-security/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install android/skills android-intent-security2Manually: put the files in place
.github/skills/android-intent-security/SKILL.md1Skills CLI (Vercel)
npx skills add android/skills --skill android-intent-security -a gemini-cli2Platform CLI
gemini skills install https://github.com/android/skills --path security/android-intent-securityManually: put the files in place
.devin/skills/android-intent-security/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add android/skills --skill android-intent-security -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about android-intent-security
How to install android-intent-security in Claude Code?
Run npx skills add android/skills --skill android-intent-security -a claude-code in your terminal.
What does android-intent-security do?
It provides security rules to verify Android manifest declarations and intent handling, stopping privilege escalation and intent redirection.
What dependencies are required for intent sanitization?
The target Android project must use minimum API level 23 and include androidx.core:core:1.9.0 or higher.
Source text
SKILL.md · Apache-2.0
---
name: android-intent-security
description: Best practices for Android Intent security. Use this skill when auditing
component configurations in AndroidManifest.xml activities, services, receivers)
or source code handling incoming Intents (getIntent, getParcelableExtra) to prevent
Intent Redirection and unauthorized access.
license: Complete terms in LICENSE.txt
metadata:
author: Google LLC
last-updated: '2026-10-22'
keywords:
- recipe
- Android
- Security
- Intent
- Redirection
- PendingIntent
- ContentProvider
- Service
- Signature
- Verification
- sanitizer
- Vulnerability
- Best Practices
---
This skill provides guidelines and patterns to secure Android components
(Activities, Services, Broadcast Receivers, Content Providers) and handle
Intents safely, preventing privilege escalation and unauthorized access.
## Glossary
- **Intent:** An asynchronous messaging object used to request an action from another app component.
- **Exported component:** A component (`android:exported="true"`) that can be launched by other apps on the device.
- **Sticky intent:** A broadcast intent that remains in the system cache after it's sent, allowing any app to retrieve its contents.
- **Signature permission:** A permission whose protection level is set to `signature`, granted only to apps signed with the same developer key.
- **onNewIntent:** An activity lifecycle callback invoked when an activity is launched with `FLAG_ACTIVITY_SINGLE_TOP` and is already running at the top of the history stack.
- **PendingIntent:** A token granted to a foreign application (for example, system services) allowing it to execute a predefined Intent with the creator's permissions.
- **Mutable PendingIntent:** A PendingIntent whose underlying Intent parameters can be modified by the receiving application.
- **ContentProvider:** A component that encapsulates data and provides it to other applications via standard query/insert interfaces.
- **IntentSanitizer:** A utility class in AndroidX Core used to build a safe, sanitized copy of an incoming Intent by filtering out unauthorized components, actions, or extras.
- **Intent redirection (forwarding):** A vulnerability where an application receives an intent from an untrusted source and uses it to launch a private, non-exported component.
## Prerequisites
- The agent **MUST** be able to describe the function and security implications of `onCreate`, `onNewIntent`, and the `singleTop` launch mode.
- The agent **MUST** be able to declare `<activity>`, `<service>`, `<receiver>`, and `<provider>` tags in `AndroidManifest.xml` and define their `android:exported` and `android:permission` attributes.
- The agent **MUST** be able to implement signature verification checks using `PackageManager`.
## Limitations
- This skill focuses on local inter-component and inter-app communication security on the Android platform.
- This skill **doesn't** cover network security, web integration, or host-to-server security.
## Setup and dependencies
- **Android SDK:** Minimum API Level 23 (Android 6.0) is required for standard hardware-backed keystore operations and component validation.
- **AndroidX Core Library:** `androidx.core:core:1.9.0` or higher is **mandatory** to leverage `IntentSanitizer`.
- **Standard API access:** Standard Android `PackageManager` APIs are required for runtime component verification.
*** ** * ** ***
## Intent security logic and decisions
### 1. Intent routing comparison
Evaluate the security features of different intent delivery methods:
| Intent Delivery Method | Scope | Recommended Use Case |
|---|---|---|
| Explicit Intent (Internal) | App Private | Launching internal activities/services |
| Implicit Intent | System Wide | Launching system camera, dialer, or sharing |
| Local Broadcasts (LocalBroadcastManager) (DEPRECATED) | App Private | Internal asynchronous event routing. **Deprecated**: Use in-app observers like Kotlin Flows/SharedFlow, LiveData, or reactive patterns instead. |
| System Broadcasts | System Wide | Receiving system events (NFC, Bluetooth) |
### 2. PendingIntent mutability flag options
Evaluate the security implications of PendingIntent mutability flags:
| Flag Name | Mutability | Recommended Use Case |
|---|---|---|
| `PendingIntent.FLAG_IMMUTABLE` | Immutable | Default for almost all PendingIntents, such as alarms and notifications |
| `PendingIntent.FLAG_MUTABLE` | Mutable | Inline notifications replies, slice actions (requires explicit target intent) |
### 3. Intent handling and redirection logic
IF (the component receives a nested Intent as an extra) {
IF (AndroidX Core 1.9.0+ and higher is available) {
MUST construct an `IntentSanitizer` to explicitly allowlist components, actions, data, and extras.
MUST call `sanitizeByThrowing()` or `sanitizeByFiltering()` before launching.
} ELSE {
MUST reject or strip URI permission grant flags (`FLAG_GRANT_READ_URI_PERMISSION`, `FLAG_GRANT_WRITE_URI_PERMISSION`, `FLAG_GRANT_PERSISTABLE_URI_PERMISSION`, `FLAG_GRANT_PREFIX_URI_PERMISSION`).
MUST resolve the target component using `resolveActivity()` and verify that both its `packageName` and `className` match an explicitly allowlisted component.
}
NEVER launch the nested Intent directly without validation.
} ELSE IF (the component handles broadcasts) {
MUST rely on the system's Protected Broadcast mechanism for system events (which guarantees the sender is the system framework).
MUST protect custom receivers with signature-level permissions or use `RECEIVER_NOT_EXPORTED` for dynamic receivers to restrict the sender.
IF (using `ContextCompat.registerReceiver` with `RECEIVER_NOT_EXPORTED` AND `minSdk < 33`) {
MUST verify `<permission android:name="${applicationId}.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION" android:protectionLevel="signature" />` and `<uses-permission android:name="${applicationId}.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION" />` are declared in `AndroidManifest.xml`.
}
}
### 4. PendingIntent security logic
IF (a PendingIntent is created for delivery to another application) {
MUST use `PendingIntent.FLAG_IMMUTABLE` by default.
IF (the PendingIntent must be mutable) {
MUST set the explicit target component or package name on the base `Intent`.
NEVER create an implicit, mutable `PendingIntent`.
}
}
### 5. ContentProvider security logic
IF (the ContentProvider is only for internal app use) {
MUST set `android:exported="false"`.
} ELSE {
MUST protect it with `android:readPermission` and `android:writePermission`.
MUST set `android:grantUriPermissions="false"` unless temporary URL access is strictly required.
}
### 6. Service caller verification logic
IF (an exported service communicates with trusted sister/partner apps) {
MUST expose a cross-process interface (such as an AIDL `Stub` or `Messenger`) rather than a local `Binder` subclass, which only works within the same process.
MUST verify the caller on every IPC request---using `Binder.getCallingUid()` inside an AIDL `Stub` method (or `onTransact()`) or `Message.sendingUid` in a `Messenger` `Handler`---and verify that the calling package signature fingerprint matches your trusted certificate hash.
}
*** ** * ** ***
## Code and configuration patterns
### 1. Safe intent redirection (manual verification)
Validate the target of a nested intent before launching it when modern
sanitization libraries are unavailable.
- **Expected Inputs:**
- An incoming `Intent` containing a nested `Intent` extra named `EXTRA_NESTED_INTENT`.
- **Expected Outputs:**
- Launches the target component if safe; throws `SecurityException` if validation fails.
```kotlin
fun safeIntentRedirectionManual() {
val nestedIntent = IntentCompat.getParcelableExtra(intent, "EXTRA_NESTED_INTENT", Intent::class.java)
if (nestedIntent != null) {
// 1. Check for URI permission grants to prevent URI permission bypass
val hasUriPermissionGrants = (
nestedIntent.flags and (
Intent.FLAG_GRANT_READ_URI_PERMISSION or
Intent.FLAG_GRANT_WRITE_URI_PERMISSION or
Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION or
Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
)
) != 0
if (hasUriPermissionGrants) {
throw SecurityException("Nested intent contains forbidden URI permission grant flags!")
}
// 2. Clear any selector intent that could override resolution
nestedIntent.selector = null
// 3. Resolve the target activity and verify both packageName and className
// match the expected allowlisted destination
val target = nestedIntent.resolveActivity(packageManager)
if (target != null &&
target.packageName == packageName &&
target.className == TargetActivity::class.java.name
) {
// 4. Explicitly pin the resolved component to prevent intent interception
nestedIntent.component = target
startActivity(nestedIntent)
} else {
throw SecurityException("Invalid or disallowed redirect target: $target")
}
}
}
```
<br />
### 2. Safe intent redirection using IntentSanitizer
Filter or reject dynamic intents using AndroidX `IntentSanitizer` (AndroidX Core
1.9.0+).
- **Expected Inputs:**
- An untrusted incoming `Intent`.
- **Expected Outputs:**
- `Intent`: A sanitized copy containing only allowlisted components, categories, and actions. Throws `SecurityException` on violations if using `sanitizeByThrowing()`.
```kotlin
fun safeIntentRedirectionSanitizer() {
// Allowlist: anything NOT listed is rejected (only component is required; other fields are optional).
// No allowFlags(): every flag, including FLAG_GRANT_*_URI_PERMISSION, is rejected.
val sanitizer = IntentSanitizer.Builder()
.allowComponent(ComponentName(this, TargetActivity::class.java))
.allowAction(Intent.ACTION_VIEW)
.allowData { it.scheme == ContentResolver.SCHEME_CONTENT && it.authority == "$packageName.provider" }
.allowType("text/plain")
.allowExtra("user_display_name", String::class.java) { it.length <= 100 } // type and content
.build()
val safeIntent = try {
val untrusted = IntentCompat.getParcelableExtra(intent, "EXTRA_NESTED_INTENT", Intent::class.java)
?: return
sanitizer.sanitizeByThrowing(untrusted)
} catch (_: SecurityException) {
Log.w("SECURITY_ALERT", "Blocked non-allowlisted nested intent")
return
} catch (_: BadParcelableException) { // e.g. an extra naming an unknown Parcelable/Serializable
Log.w("SECURITY_ALERT", "Malformed nested intent")
return
}
// The sanitizer doesn't enforce presence; check what the target actually requires.
if (safeIntent.getStringExtra("user_display_name") == null) {
Log.w("SECURITY_ALERT", "Nested intent missing user_display_name")
return
}
startActivity(safeIntent)
}
```
<br />
### 3. Custom signature permission protection
Declare a custom signature-level permission in the manifest to secure family app
communication.
- **Expected Inputs:** Manifest configuration.
- **Expected Outputs:** An activity that can only be launched by apps signed with the same developer certificate.
```xml
<permission
android:name="com.example.snippets.permission.INTERNAL_COMMUNICATION"
android:protectionLevel="signature" />
```
<br />
```xml
<activity
android:name=".intents.InternalSharingActivity"
android:exported="true"
android:permission="com.example.snippets.permission.INTERNAL_COMMUNICATION">
<intent-filter>
<action android:name="com.example.snippets.ACTION_SHARE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
```
<br />
### 4. Safe onNewIntent lifecycle verification (warm boot protection)
Ensure that activities reusing dynamic intents (for example, in background
launch paths) apply the same strict security filters inside `onNewIntent`.
- **Expected Inputs:**
- `newIntent` (`Intent`): The newly delivered intent.
- **Expected Outputs:**
- Executes processing logic only if the new intent passes security validation.
```kotlin
override fun onNewIntent(newIntent: Intent) {
super.onNewIntent(newIntent)
// Set the intent to ensure intent returns the new one
intent = newIntent
// Validate the intent payload
if (validateIntent(newIntent)) {
processIntentPayload(newIntent)
} else {
Log.w("SECURITY_ALERT", "Received invalid or insecure intent during warm boot")
}
}
private fun validateIntent(intent: Intent): Boolean {
return intent.hasExtra("VALID_PAYLOAD_MARKER")
}
```
<br />
### 5. Secure PendingIntent creation
Enforce immutability unless mutability is explicitly required.
- **Expected Inputs (Immutable):** An intent target.
- **Expected Outputs (Immutable):** A `PendingIntent` that cannot be altered by the receiver.
- **Expected Inputs (Mutable):** An intent with an explicit component set.
- **Expected Outputs (Mutable):** A mutable `PendingIntent` locked to a specific receiver component to prevent hijacking.
```kotlin
fun createPendingIntents(context: Context) {
// 1. Secure Immutable PendingIntent (Default)
val intent = Intent(context, TargetActivity::class.java)
val pendingIntent = PendingIntent.getActivity(
context,
0,
intent,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
// 2. Secure Mutable PendingIntent (e.g., Notification Direct Reply)
val mutableIntent = Intent().apply {
// MUST set explicit target component to prevent redirection hijacking
component = ComponentName(context, ReplyReceiver::class.java)
}
val mutablePendingIntent = PendingIntent.getBroadcast(
context,
0,
mutableIntent,
PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
}
```
<br />
### 6. Secure ContentProvider configuration and queries
Expose a ContentProvider securely and parameterize queries to prevent SQL
injection.
- **Expected Inputs:**
- `uri` (`Uri`): The query URI.
- `projection` (`String[]`): Columns to retrieve.
- `selection` (`String`): Query criteria.
- `selectionArgs` (`String[]`): Values mapping to selection placeholders (`?`).
- **Expected Outputs:**
- `Cursor`: Filtered query results, strictly bound to projection maps.
```xml
<provider
android:name=".intents.SecureDataProvider"
android:authorities="com.example.snippets.provider"
android:exported="true"
android:readPermission="com.example.snippets.permission.READ_DATA"
android:writePermission="com.example.snippets.permission.WRITE_DATA"
android:grantUriPermissions="false" />
```
<br />
```kotlin
override fun query(
uri: Uri,
projection: Array<String>?,
selection: String?,
selectionArgs: Array<String>?,
sortOrder: String?
): Cursor? {
val queryBuilder = SQLiteQueryBuilder()
queryBuilder.tables = tableName
// Strict projection map to prevent querying unauthorized columns
queryBuilder.projectionMap = mapOf(
"_id" to "_id",
"display_name" to "display_name"
)
// Enable strict validation (always available since minSdk is 36)
queryBuilder.setStrict(true)
queryBuilder.setStrictColumns(true)
queryBuilder.setStrictGrammar(true)
// MUST parameterize selection criteria; NEVER append selection strings directly
val db = dbHelper.readableDatabase
return queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder)
}
```
<br />
### 7. Service caller signature verification
Verify the calling application's signing certificate on incoming cross-process
IPC calls in an exported bound service.
- **Expected Inputs:**
- An incoming cross-process Binder transaction (for example, an AIDL `Stub` method call or `onTransact()`).
- **Expected Outputs:**
- Executes the requested service operation if the calling UID's signing certificate matches the trusted partner hash; throws `SecurityException` otherwise.
```kotlin
class SecureBoundService : Service() {
companion object {
// Expected SHA-256 hash of the trusted app's signing certificate (Base64 encoded)
private const val TRUSTED_PARTNER_SHA256 = "A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6Q7R8S9T0U1V="
}
override fun onBind(intent: Intent): IBinder {
// Return the binder. Do NOT perform signature verification in onBind() because
// the binder connection is cached by Android, which can bypass checks on subsequent binds.
return LocalBinder()
}
private fun enforceTrustedCaller() {
val callingUid = Binder.getCallingUid()
// Allow calls from the same application
if (callingUid == Process.myUid()) {
return
}
val pm = packageManager
val packages = pm.getPackagesForUid(callingUid)
if (packages.isNullOrEmpty() || !verifySignature(pm, packages[0])) {
throw SecurityException("Access Denied: Caller signature is untrusted.")
}
}
private fun verifySignature(pm: PackageManager, packageName: String): Boolean {
try {
val trustedSha256Raw = Base64.decode(TRUSTED_PARTNER_SHA256, Base64.DEFAULT)
// API 28+ handles rotated certificates and avoids manual hashing.
// Since minSdk is 36, this is always available.
return pm.hasSigningCertificate(packageName, trustedSha256Raw, PackageManager.CERT_INPUT_SHA256)
} catch (e: Exception) {
Log.e("SECURITY_ERROR", "Verification failed for package: $packageName", e)
}
return false
}
inner class LocalBinder : Binder() {
fun doSecureWork() {
// Verify caller identity on every transaction method call
enforceTrustedCaller()
// Safe to proceed with sensitive operations
}
}
}
```
<br />
*** ** * ** ***
## Error handling
Handle component binding, database queries, and intent redirection failures
securely to avoid exposing internal structures.
```kotlin
fun safeErrorHandling(callingPackage: String?) {
try {
val payload = intent.getStringExtra("DATA_EXTRA") ?: throw IllegalArgumentException("Payload parameter missing.")
// Create a specific target intent using the validated payload
val targetIntent = Intent(this, TargetActivity::class.java).apply {
putExtra("SECURE_PAYLOAD", payload)
}
startActivity(targetIntent)
} catch (e: SecurityException) {
// MUST log security violations for audit, but NEVER expose exception details to the user.
Log.e("SECURITY_ERROR", "Unauthorized component transition blocked. Calling Package: ${callingPackage ?: "Unknown"}", e)
// MUST provide generic user feedback.
showFeedbackToUser("Process request failed: Access Denied.")
} catch (e: IllegalArgumentException) {
Log.w("INTEGRITY_WARNING", "Missing intent parameter", e)
}
}
```
<br />
// Secure handling of ContentProvider queries on the client side:
try {
val cursor = contentResolver.query(providerUri, projection, selection, selectionArgs, null)
} catch (e: SQLiteException) {
Log.e("PROVIDER_ERROR", "ContentProvider database query failed", e)
// Secure handling: prevent raw query syntax details from leaking to UI
}
*** ** * ** ***
## Reporting guidelines
When this skill is executed to apply security hardening updates to a codebase,
the agent **MUST** generate a structured "Best Practices and Security Alignment
Update" report for the developer. The report **must** be written to the session
artifact folder (or printed in the final response) and include:
1. **Security alignment area:** The category of improvement applied (for example, Safe Intent Redirection, Secure PendingIntent Configuration, ContentProvider Data Guarding).
2. **Impact and priority:** The potential safety risk addressed by the update (for example, Component Hijacking Prevention, Private Data Isolation).
3. **Scope of changes:** A list of all modified classes, XML files, and dependencies.
4. **Implementation summary:** Concrete details of the solution (for example, "Updated nested intent parsing to use the `IntentSanitizer` API with a strict component allowlist").
5. **Code diff:** Standard unified diffs showing the exact modifications.
### Best practices and security alignment update template
Use the following markdown template when reporting changes to developers:
### Best practices and security alignment update: [Security Alignment Area]
* **Improvement Description:** [Brief description of the hardening update and why it's recommended]
* **Priority Level:** [High / Medium / Low]
* **Alignment Action:** [Summary of updates, for example, converted to FLAG_IMMUTABLE]
#### Files modified
* `[Relative path to File 1]`
* `[Relative path to File 2]`
#### Implementation diff
```diff
// Insert Unified Diff here
#### Testing and verification
1. \[Step 1 to verify the component behaves correctly, for example, run component unit test\]
2. \[Step 2 to verify regression safety\] \`\`\`
*** ** * ** ***
## Antipatterns
- **NEVER** launch a nested `Intent` received from an untrusted source without verifying that its resolved component (`packageName` and `className`) matches an explicit allowlist and rejecting or stripping URI permission grant flags.
- **NEVER** use sticky broadcasts (`sendStickyBroadcast`).
- **NEVER** assume an exported component is safe because it runs in a background thread or performs internal checks.
- **NEVER** expose sensitive functionalities (like SSO authentication or payment processors) to components without signature-level permission restrictions.
- **NEVER** process incoming intents in `onNewIntent` without applying the same security controls as `onCreate`.
- **NEVER** create a mutable `PendingIntent` without setting an explicit target component in the base `Intent`.
- **NEVER** use dynamic string concatenation to construct selection blocks inside a `ContentProvider` query.
- **NEVER** use `Binder.getCallingUid` inside a `BroadcastReceiver.onReceive` to identify the sender of a broadcast, as it returns the receiver's own UID, not the sender's.
## Best Practices
- **MUST** explicitly set `android:exported="false"` for all components that don't need external communication.
- **MUST** protect all exported components with custom permissions utilizing `android:protectionLevel="signature"` when communicating between family apps.
- **MUST** validate all incoming intent extras and handle missing parameters gracefully to prevent crashes.
- **MUST** rely on the system's **Protected Broadcast** mechanism for system events (for example, boot completed, package changes), as the system prevents untrusted apps from spoofing these actions.
- **MUST** protect custom broadcasts with signature-level permissions or use `RECEIVER_NOT_EXPORTED` for dynamic receivers to restrict the sender identity (and when `minSdk < 33`, **MUST** verify that `<permission android:name="${applicationId}.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION" android:protectionLevel="signature" />` and `<uses-permission android:name="${applicationId}.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION" />` are present in `AndroidManifest.xml` when using `ContextCompat.registerReceiver`).
- **MUST** call `setIntent(newIntent)` inside `onNewIntent()` before processing payloads to keep active references updated.
- **MUST** use `PendingIntent.FLAG_IMMUTABLE` by default when constructing `PendingIntent` instances.
- **MUST** protect exported `ContentProviders` with `readPermission` and `writePermission`.
- **MUST** enforce parameterized selection structures in `ContentProvider` query/update methods.
- **MUST** verify the calling application's signing certificate on incoming IPC transactions at runtime inside exported bound services using a cross-process interface (such as an AIDL `Stub` or `Messenger`).
- **MUST** use `androidx.core.content.IntentSanitizer` to sanitize incoming dynamic intents before redirection, if AndroidX Core 1.9.0+ is imported in the project.
© Google LLC · Apache-2.0 · android/skills