Tools & Performance

App security in the agentic era

Speakers

  • Kristen O'Leary

    Senior Developer Relations Engineer

  • Sabs

    Developer Relations Engineer

About

About the talk

This presentation explores the strategic shift from viewing AI as a generic coding assistant to leveraging it as a context-aware, automated security peer reviewer integrated directly into the Android development lifecycle. We discuss how specialized AI agents, connected to the Android toolchain via skills, can help improve app security. By bridging the gap between raw LLM capabilities and deep project context, this approach empowers development teams to maintain high-velocity feature delivery without compromising rigorous security and policy standards.

Summary

  • Generic AI agents miss key context during audits, but Android security skills provide researcher-backed guidance. They check intent security and enforce permissions using project-specific build configurations.
  • The Play policy skill runs static analysis to catch compliance issues before submission. It can cross-reference code analysis against existing Play Store declarations.
  • The Play Integrity API evaluates app and device integrity at runtime. The Protected with Play dashboard unites integrity and distribution monitoring in one place.
  • Targeted APIs allow apps to protect user privacy without requesting broad permissions. Examples include the SMS Retriever API and the alpha Location Button library.

Skills

Resources

Gemini Notebook

Topics

  • app-security
  • ai-agents
  • play-integrity-api
  • permissions
  • location-button
  • advanced-protection-mode

Transcript

Introduction

  • Hi, I'm Kristen.

  • Hi, and I am Sabs.

  • And we're here to talk to you about today about security in the agentic era.

  • In the past year, we gave up over $2 million in rewards for the Android Bug Hunters program, and over 200k for mobile.

  • In today's agentic era, app security is constantly evolving.

  • So, let's talk about the tools to help us solve these problems quickly and effectively.

  • To improve how agents perform for Android security, the answer isn't a better prompt.

  • It's tools and workflows to help agents understand our toolchains and API to help keep your app safe.

  • So, it's 4:30 p.m.

  • On a Thursday.

  • You're cutting a release, and the CI goes red, only one error: A broadcast receiver registered without an export flag.

  • So, whether you're on a small team, wearing every hat, or on a large one, where security checks hit as you are cutting the release, the reality is the same.

  • We are product engineers, shipping high-quality features fast, and we're not necessarily security researchers.

  • So, what's the natural instinct?

  • So, we hand that warning to an agentic tool, and ask the agent for a fix.

Context limitations of AI agent security audits

  • But agentic tool, working without your project context, has three blind spots.

  • It may not know your app is built from dynamic feature modules or multi-APK bundles.

  • It sees a file, not a shipped artifact.

  • It may not know, be able to trace the data flow from your Kotlin UI down to your KMP shared logic into the native C++ JNI calls.

  • It sees only one layer.

  • Last, but not least, it may not have awareness of your minimum SDK or your Gradle build flavors.

  • So, we pointed an agent the app, and asked for a security audit.

  • Six findings came back.

  • And here's the thing.

  • Every single one of them they're is not wrong.

  • They're defensible, but only one of them is the bug we actually started with.

  • The rest is a mix of good practice, things to investigate further, speculation, and things that may not even apply.

  • So, now you scale that into a real code base, with more warnings, and in every pull request, you will be tempted to reach for the suppress lint.

  • You will to get to change to get that change merged, or may even miss a vulnerability altogether.

  • And that's how real vulnerabilities slip pass through.

  • The tool wasn't careless, it was careful, but careful isn't the same as useful.

  • Let's make this concrete.

  • Say, you ask your agent, "Audit every exported component in this app for app intent intent redirection."

  • That's a genuine security task, and on a multi-module app, it's a large one.

  • That's the kind of request where cost actually shows up.

  • And without Android specific guidance, the agent has no strategy for that question.

  • So, it brute forces.

  • It may read modules that export nothing at all.

  • It may re-derive from first principle what makes an intent redirect exploitable.

  • It may follow paths that were never reachable.

  • You're paying for exploration, not analysis.

  • A skill is what supplies the missing strategy.

  • Android security skills, for example, provide your agent with instructions that follow current guidance, the same sequence of steps a security researcher would actually follow, and the agent stops guessing.

  • It doesn't rediscover the rules because the rules were provided by the skill.

Android security skills for agents

  • Currently, we have launched two security skills: Intent Security and Permissions.

  • Intent security is about what other apps can make your app do.

  • Your app holds permissions, a sign-in session that they don't.

  • So, every exported component and every pending intent you hand out is a potential way for someone to act through you.

  • The skill helps safeguard against this.

  • The permissions skill helps close the gap between a permission that is declared and one that is actually enforced.

  • It can help you write the appropriate permissions check.

  • It helps identify if a provider with a wild card path grants the whole database instead of one directory.

  • It catches over-asking permissions too.

  • For example, requesting a broad access where the photo picker would do.

  • Use it with the Android CLI, and then ask, "Audit for intent security."

  • No config.

  • No rule tuning.

  • So, the output isn't a wall of warnings.

  • It's a review.

  • Here's a bug, here's why it matters for your app, and here's the fix.

  • And here's the pro tip.

  • Use the Android CLI makes it easy to find and install.

    android skills list
    android skills add android-intent-security
    android skills add android-permissions-security
  • And because the skill know exactly what to look for in your project, it sees your app the way it actually ships.

  • It respects your minimum SDK so the fix compiles, real file paths, real line numbers.

  • Here's the review you get back.

  • It points to the exact file and the line, explains the real threat and explanation for the change, not just Lint says so.

  • It cites which skill it used.

  • It read the build config, saw minimum SDK 26, and it picked ContextCompat so the fix works, and it hand you a diff so you can apply it.

  • That's the warning we opened with, but now with a suggested fix and added reasoning.

Google Play policy insights skill

  • So, the previous skills catch security bugs.

  • Now let's talk about another area, app policy compliance.

  • For example, let's imagine you're a new app developer looking to launch on the Play Store.

  • Filling out the data safety form is an important step in launching your app, so let's use every tool we can to help ensure we get it right before app submission.

  • The Play policy skill performs static analysis on your code base.

  • If you're publishing an existing Play Store app, it can also cross-reference that static code analysis with Play Store declarations.

  • Running this skill can help you catch potential Play policy issues before, not after, app submission, and helps speed up your submission process.

  • The workflow is similar to the other skills we've been discussing: import it, and then ask, "Audit this app for Google Play policy compliance before I submit it."

  • You'll see a screenshot of an example report on the right, and the Android CLI commands to install it below.

    android skills list
    android skills add play-policy-insights

Runtime defense with the Play Integrity API

  • So, everything we've talked about so far happens before you ship: auditing intents, checking permissions, validating compliance.

  • That's build time security, and it's essential.

  • But there's a whole class of threats that only exists once your APK is out in the world, running on devices you may not control.

  • The Play Integrity API answers three questions at run time that your own code cannot answer about itself: Is this a genuine, unmodified build of your app?

  • Is this running on an Android device that's genuine?

  • And is this a Play user account?

  • So, you can use the Play Integrity API to return verdicts on app integrity, device integrity, and more.

  • And in addition to making it faster and easier to publish your app safer, we're also making it easier to secure your app's revenue and reputation.

  • So, defend your business against fraud and abuse.

  • The new Protected with Play dashboard, you can see over here, helps you monitor and configure your integrity, distribution, and monetization defenses all in one place.

  • We're also reducing warm up latency for the Play Integrity API so you can use these checks during speed-critical user journeys to block threats and risky devices faster.

  • So, we've just discussed Android features and tools to help keep apps safe, but how about your users?

SMS OTP protection APIs

  • Let's first take a look at SMS OTP Protection.

  • Let's say you want to implement SMS-based user verification for your app and send verification codes.

  • The SMS permission provides app access to messaging data, including sensitive data like OTPs.

  • So, we've introduced a few APIs in your app so you can implement that, so you don't need to request broad SMS permissions, but are still able to pick up SMS OTP codes for verification.

  • The SMS Retriever API allows your app to automatic- automatically verify OTPs without broad SMS permissions.

  • You append an 11-character hash identifying your app to the message, and the system hands you only that one message.

  • And if you can't control the message format, use the SMS User Consent API.

  • The system shows a single, one-time prompt.

  • The user taps allow or deny, and if they allow, you get that single message.

  • Still no need for a broad SMS permission.

One-time access with the location button

  • Some apps may need precise location only one time to complete tasks.

  • The existing only one-time permission has high user friction, so sometimes developers will ask for broader precise permission instead.

  • So, the Location Button is a tool that provides a low friction way to grant the app one-time precise location access.

  • It's an Android UI element that can be customized and embedded by app developers.

  • We launched the first version of the alpha Location Button Jetpack library in June.

  • Here, you can see the permissions required to enable the Location Button in your Android manifest.

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
        android:usesPermissionFlags="onlyForLocationButton"/>
    
    <uses-permission android:name="android.permission.USE_LOCATION_BUTTON" />
    
        <application
            android:icon="@mipmap/ic_launcher"
            android:label="LocationButtonSample"
            android:theme="@style/Theme.PinPoint">
            <activity
                android:name=".MainActivity"
                android:exported="true">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
  • You must declare standard location permission as- adding the onlyForLocationButton permission flag, along with the dedicated USE_LOCATION_BUTTON permission required by the system's remote rendering service.

  • On the right, is the Jetpack code to implement it.

    ...
    import androidx.core.locationbutton.compose.LocationButton
    
    @Composable
    fun LocationPermissionScreen(onPermissionGranted: () -> Unit, onPermissionDenied: () -> Unit) {
        // Renders the secure system-trusted Location Button composable
        LocationButton(
            // Callback triggered when the user taps the secure button and makes a decision on the permission dialog
            onPermissionResult = { isGranted ->
                if (isGranted) {
                    onPermissionGranted()
                } else {
                    onPermissionDenied()
                }
            },
    ...
  • You can see here we're creating a Location Button and initializing a callback.

  • This callback is triggered when the user taps the Location Button to make a decision on if the permission is granted or denied.

Advanced protection mode integration

  • Advanced Protection Mode is a feature that is aimed for your at-risk users or security-conscious ones, but anyone can opt in.

  • For example, say you are a banking app, you don't force the extra multifactor authentication on every transfer because everyday users don't like that extra friction.

  • But, when Advanced Protection Mode is on, your app knows this user wants the maximum amount of protection, so you can automatically require biometric authentication on every transfer.

  • Advanced Protection Mode implements a set of predefined configurations designed for to bolster device protection.

  • Here, we show you how to integrate into your app.

  • You need to request the permission, query Advanced Protection Mode, and you check if the user has turned on Advanced Protection Mode using on the on-device calling the Advanced Protection Mode Manager system service.

    class AdvancedProtectionManager() {
      // Check the current status
      fun isAdvancedProtectionEnabled(): Boolean
    
      // Be alerted when status changes
      fun registerAdvancedProtectionCallback(executor: Executor,
                                             callback: Callback)
    
      fun unregisterAdvancedProtectionCallback(callback: Callback)
    }
    
    interface Callback() {
      // Called when advanced protection state changes
      fun onAdvancedProtectionChanged(enabled: Boolean)
    }
  • And then, you can listen for runtime changes by registering the callback.

Useful links and resources

  • We gone through a lot of topics today.

  • So, here are quick links and if you like to learn more about them.

  • We'll pause here for a second so you can take down the URLs you need.

  • Thank you.

  • Thank you.

Code

Code snippets

Shell snippet at 05:09 in "Android security skills for agents"
android skills list
android skills add android-intent-security
android skills add android-permissions-security
Shell snippet at 06:41 in "Google Play policy insights skill"
android skills list
android skills add play-policy-insights
XML snippet at 09:36 in "One-time access with the location button"
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
    android:usesPermissionFlags="onlyForLocationButton"/>

<uses-permission android:name="android.permission.USE_LOCATION_BUTTON" />

    <application
        android:icon="@mipmap/ic_launcher"
        android:label="LocationButtonSample"
        android:theme="@style/Theme.PinPoint">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
Kotlin snippet at 09:54 in "One-time access with the location button"
...
import androidx.core.locationbutton.compose.LocationButton

@Composable
fun LocationPermissionScreen(onPermissionGranted: () -> Unit, onPermissionDenied: () -> Unit) {
    // Renders the secure system-trusted Location Button composable
    LocationButton(
        // Callback triggered when the user taps the secure button and makes a decision on the permission dialog
        onPermissionResult = { isGranted ->
            if (isGranted) {
                onPermissionGranted()
            } else {
                onPermissionDenied()
            }
        },
...
Kotlin snippet at 10:53 in "Advanced protection mode integration"
class AdvancedProtectionManager() {
  // Check the current status
  fun isAdvancedProtectionEnabled(): Boolean

  // Be alerted when status changes
  fun registerAdvancedProtectionCallback(executor: Executor,
                                         callback: Callback)

  fun unregisterAdvancedProtectionCallback(callback: Callback)
}

interface Callback() {
  // Called when advanced protection state changes
  fun onAdvancedProtectionChanged(enabled: Boolean)
}