This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
mobilecritical PriorityID: android-15-private-space-keystore-invalidation-standard

Android 15 Private Space Biometric Keystore Invalidation Standard

Enforces immediate zeroization of memory-resident cryptographic keys and instantaneous termination of background jobs when an Android 15 Private Space enters the locked state. Mandates listening to ACTION_PROFILE_UNAVAILABLE and user-lifecycle broadcasts to invalidate Keystore handles and prevent key retention in suspended profile runtimes.

Prohibited Anti-Pattern: Retaining In-Memory Cryptographic Handles and Background Job Schedulers Across Private Space Profile Lock Cycles

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Android 15 Private Space Biometric Keystore Invalidation Standard - Enforces immediate zeroization of memory-resident cryptographic keys and instantaneous termination of background jobs when an Android 15 Private Space enters the locked state. Mandates listening to ACTION_PROFILE_UNAVAILABLE and user-lifecycle broadcasts to invalidate Keystore handles and prevent key retention in suspended profile runtimes.
globs: **/*.kt, **/*.java, **/AndroidManifest.xml
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/android-15-private-space-keystore-invalidation-standard"
---

# Android 15 Private Space Biometric Keystore Invalidation Standard

> **Severity**: CRITICAL | **Category**: mobile
> **Anti-Pattern Warning**: Retaining In-Memory Cryptographic Handles and Background Job Schedulers Across Private Space Profile Lock Cycles

## System Constraints
You are a Principal Mobile Security Engineer enforcing the Android 15 Private Space Biometric Keystore Invalidation Standard. You must ensure that applications running within Android 15's Private Space (or separate profiles) explicitly handle profile suspension and locking events by securely wiping cryptographic key material from memory, cancelling all pending WorkManager and JobScheduler tasks, and invalidating MasterKey/BiometricPrompt sessions. Never allow plaintext secrets or cipher instances to persist across profile lock boundaries.

## Strict Guidelines
- Engineers MUST ALWAYS register a BroadcastReceiver listening for Intent.ACTION_PROFILE_UNAVAILABLE or Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE to detect profile locking.
- Engineers MUST ALWAYS invoke explicit zeroization (e.g., Arrays.fill(keyBytes, 0.toByte())) on all memory-resident buffers, byte arrays, and cached SecretKey references upon receiving profile lock signals.
- Engineers MUST cancel active WorkManager jobs and JobScheduler tasks within the private profile using WorkManager.cancelAllWork() or profile-scoped job cancellation upon transition to locked state.
- Engineers MUST NOT cache Cipher instances or crypto objects wrapped in BiometricPrompt.AuthenticationResult past the immediate cryptographic transaction boundary.
- Security layers MUST configure KeyGenParameterSpec with setUserAuthenticationRequired(true) and setInvalidatedByBiometricEnrollment(true) to tie Keystore keys strictly to hardware-backed biometric state.
- Components NEVER store sensitive decrypted state inside Application-level singletons or static fields that persist across Private Space suspension cycles.

## Bad vs Good Implementations
### Private Space Key Retention Anti-Pattern vs. Zeroization and Invalidation Handler

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Retains the SecretKey and Cipher instances within memory singletons. When Android 15 locks the Private Space, the app process may be suspended rather than completely destroyed, leaving sensitive cryptographic state reachable in memory and active background jobs running without authorization.
```kotlin
class PrivateSpaceCryptoManager(private val context: Context) {
    // ANTI-PATTERN: Retaining decrypted keys in memory across profile states
    private var cachedKey: SecretKey? = null
    private var activeCipher: Cipher? = null

    fun getCipher(): Cipher {
        if (activeCipher == null) {
            val keyStore = KeyStore.getInstance("AndroidKeyStore").apply { load(null) }
            cachedKey = keyStore.getKey("private_space_vault_key", null) as SecretKey
            activeCipher = Cipher.getInstance("AES/GCM/NoPadding").apply {
                init(Cipher.DECRYPT_MODE, cachedKey)
            }
        }
        return activeCipher!!
    }
    // No lifecycle or profile unavailable handling; jobs continue executing in suspended state
}
```

#### Production Standard (Correct)
> **Standard**: Listens for ACTION_PROFILE_UNAVAILABLE, instantaneously zeroizes in-memory cryptographic byte arrays, flushes active background tasks through WorkManager, and invalidates Keystore references to ensure no residual plaintext or crypto handles persist while the Private Space is locked.
```kotlin
class PrivateSpaceSecurityManager(private val context: Context) : BroadcastReceiver() {
    private val keyStore = KeyStore.getInstance("AndroidKeyStore").apply { load(null) }
    private var ephemeralBuffer: ByteArray? = null

    fun registerProfileLockListener() {
        val filter = IntentFilter().apply {
            addAction(Intent.ACTION_PROFILE_UNAVAILABLE)
            addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE)
        }
        context.registerReceiver(this, filter, Context.RECEIVER_NOT_EXPORTED)
    }

    override fun onReceive(context: Context, intent: Intent) {
        when (intent.action) {
            Intent.ACTION_PROFILE_UNAVAILABLE,
            Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE -> {
                enforceImmediateZeroization(context)
            }
        }
    }

    @Synchronized
    fun enforceImmediateZeroization(context: Context) {
        // 1. Overwrite in-memory sensitive buffers immediately
        ephemeralBuffer?.let { buffer ->
            Arrays.fill(buffer, 0.toByte())
        }
        ephemeralBuffer = null

        // 2. Sever background jobs tied to Private Space
        WorkManager.getInstance(context).cancelAllWork()

        // 3. Clear Keystore entry reference to force hardware re-auth
        if (keyStore.containsAlias("private_space_vault_key")) {
            keyStore.deleteEntry("private_space_vault_key")
        }
    }
}
```

Recommended MCP Servers (mcp-serverlist.com)

Equip agent with system tools to verify code for this stack.

Recommended Agent Skills (askills.dev)

Ready-to-use executable skill functions tailored to this stack.

Architectural Specification & Invariant Rationale

Architectural Invariant Design: Android 15 Private Space Biometric Keystore Invalidation Standard

Android 15 Private Space Biometric Keystore Invalidation Standard defines an industrial-grade behavioral standard for mobile engineering. Enforces immediate zeroization of memory-resident cryptographic keys and instantaneous termination of background jobs when an Android 15 Private Space enters the locked state. Mandates listening to ACTION_PROFILE_UNAVAILABLE and user-lifecycle broadcasts to invalidate Keystore handles and prevent key retention in suspended profile runtimes. Modern software architectures require strict adherence to deterministic patterns to guarantee high availability, maintainability, and zero security vulnerabilities.

Framework Paradigm Shift & Drift MechanicsLLMs are trained on millions of open-source repositories containing outdated code, legacy idioms, and unpatched antipatterns. When coding assistants generate implementations for this stack, they default to common statistical tokens: Retaining In-Memory Cryptographic Handles and Background Job Schedulers Across Private Space Profile Lock Cycles Without an explicit system instruction file, developers spend hours debugging silent failures.
Failure Modes & Production Blast Radius

Hazard Analysis: What Breaks Without This Rule

The following failure modes have been cataloged from hundreds of hours of production code reviews where AI assistants produced non-compliant implementations:

Failure ModeAI Symptom (The Anti-Pattern)SeverityProduction Impact & Remedy
AI Hallucination & Deprecation DriftRetaining In-Memory Cryptographic Handles and Background Job Schedulers Across Private Space Profile Lock CyclesCritical
Violating this industrial standard introduces regression bugs, security risks, and unexpected runtime failures in production.
Enforce explicit behavioral system directives across all AI coding assistants in your repository.
Silent Architecture InconsistencyAI assistants produce mixed paradigms across files, creating fragmented codebase conventions.Medium
Increases cognitive load during code reviews and leads to maintenance debt across engineering teams.
Pin project conventions in .cursor/rules, CLAUDE.md, and AGENTS.md so all team agents follow identical guardrails.
Architectural Directives in Detail

Step-by-Step Production Directives

Each rule constraint below is injected into the AI agent's system prompt to establish deterministic boundaries:

1

Engineers MUST ALWAYS register a BroadcastReceiver listening for Intent.ACTION_PROFILE_UNAVAILABLE or Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE to detect profile locking.

Engineers MUST ALWAYS register a BroadcastReceiver listening for Intent.ACTION_PROFILE_UNAVAILABLE or Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE to detect profile locking.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
2

Engineers MUST ALWAYS invoke explicit zeroization (e.g., Arrays.fill(keyBytes, 0.toByte())) on all memory-resident buffers, byte arrays, and cached SecretKey references upon receiving profile lock signals.

Engineers MUST ALWAYS invoke explicit zeroization (e.g., Arrays.fill(keyBytes, 0.toByte())) on all memory-resident buffers, byte arrays, and cached SecretKey references upon receiving profile lock signals.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
3

Engineers MUST cancel active WorkManager jobs and JobScheduler tasks within the private profile using WorkManager.cancelAllWork() or profile-scoped job cancellation upon transition to locked state.

Engineers MUST cancel active WorkManager jobs and JobScheduler tasks within the private profile using WorkManager.cancelAllWork() or profile-scoped job cancellation upon transition to locked state.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
4

Engineers MUST NOT cache Cipher instances or crypto objects wrapped in BiometricPrompt.AuthenticationResult past the immediate cryptographic transaction boundary.

Engineers MUST NOT cache Cipher instances or crypto objects wrapped in BiometricPrompt.AuthenticationResult past the immediate cryptographic transaction boundary.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
5

Security layers MUST configure KeyGenParameterSpec with setUserAuthenticationRequired(true) and setInvalidatedByBiometricEnrollment(true) to tie Keystore keys strictly to hardware-backed biometric state.

Security layers MUST configure KeyGenParameterSpec with setUserAuthenticationRequired(true) and setInvalidatedByBiometricEnrollment(true) to tie Keystore keys strictly to hardware-backed biometric state.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
6

Components NEVER store sensitive decrypted state inside Application-level singletons or static fields that persist across Private Space suspension cycles.

Components NEVER store sensitive decrypted state inside Application-level singletons or static fields that persist across Private Space suspension cycles.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
Technical Questions & Answers

Frequently Asked Technical Questions

Common questions developers face when configuring AI coding assistants for this stack:

Q:Why is Android 15 Private Space Biometric Keystore Invalidation Standard critical for AI coding assistants?

Enforces immediate zeroization of memory-resident cryptographic keys and instantaneous termination of background jobs when an Android 15 Private Space enters the locked state. Mandates listening to ACTION_PROFILE_UNAVAILABLE and user-lifecycle broadcasts to invalidate Keystore handles and prevent key retention in suspended profile runtimes. Without explicit behavioral boundaries, AI coding assistants (Cursor, Claude Code, Windsurf, Codex) rely on training data averages, which frequently produce deprecated, inefficient, or vulnerable code patterns.

Q:How does adopting this rule prevent AI hallucinations?

This rule explicitly declares what the AI must avoid (Retaining In-Memory Cryptographic Handles and Background Job Schedulers Across Private Space Profile Lock Cycles) and prescribes verified positive examples. Grounding the LLM with negative and positive pairs eliminates guesswork.

Q:Which AI coding environments are supported?

This specification is multi-platform compatible: Cursor (.cursor/rules/*.mdc & .cursorrules), Anthropic Claude Code (CLAUDE.md), Windsurf (.windsurfrules), Codex / Cline (AGENTS.md), and GitHub Copilot (.github/copilot-instructions.md).

Q:Can I combine this rule with other technology stacks?

Yes. Use the Interactive Stack Builder or download an Agent Pack to merge this rule with other frontend, backend, database, security, and DevOps rules without syntax collision.

Open Specification · CC BY 4.0·Free for Personal, Team & Commercial In-Repo Use

Citation & Open Source Attribution Guidelines

This specification is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). You are completely free to adapt and share this rule in your workspace. If citing, including in public AI benchmark datasets, or redistributing, attribution to AgentRules.org is required.

Related MOBILE Rules

View all rules →
1 Rule in Stack

Android