La tua app è sicura quanto il sistema operativo sottostante. Per ridurre il rischio, la tua app deve controllare le operazioni sensibili alla sicurezza con una valutazione in tempo reale della postura di sicurezza del dispositivo, determinando se il dispositivo, in particolare i suoi componenti di sistema principali, è completamente aggiornato e protetto dalle vulnerabilità pubblicate nel Bollettino sulla sicurezza di Android. La visibilità sullo stato di sicurezza del dispositivo ti aiuta a stabilire misure di protezione prima che la tua app esegua operazioni ad alto rischio.
AndroidX Security State è una libreria Jetpack che fornisce un accesso unificato allo stato di sicurezza di un dispositivo Android. Combina le API AOSP e i feed pubblici delle vulnerabilità di Android per fornire uno stato di sicurezza del dispositivo completo, preciso e pratico, che va oltre il semplice livello patch di sicurezza (SPL).
Panoramica dell'architettura
Il seguente diagramma illustra come la libreria AndroidX Security State unifica le proprietà della piattaforma sul dispositivo, i fornitori di aggiornamenti della comunicazione interprocesso (IPC) e i feed pubblici delle vulnerabilità in un unico set coeso di API.

Stati e componenti delle patch di sicurezza
Il vantaggio principale dell'utilizzo della libreria Security State è la sua capacità di fornire il livello patch di sicurezza (SPL) a un livello granulare di componente. Nel corso degli anni, Android ha introdotto altri moduli negli aggiornamenti di sistema Google Play (Project Mainline), che vengono aggiornati tramite Google Play indipendentemente dagli aggiornamenti di sistema over-the-air (OTA) standard, fornendo correzioni di sicurezza critiche con una cadenza diversa.
Allo stesso modo, mentre il livello patch di sicurezza di solito impone la versione minima richiesta di Generic Kernel Image (GKI), gli aggiornamenti del kernel possono effettivamente anticipare la pianificazione del sistema. Queste correzioni specifiche del kernel potrebbero non essere acquisite completamente dalla stringa SPL principale del sistema.
Per migliorare la trasparenza, la libreria dello stato di sicurezza fornisce un livello di patch efficace per tutti e tre i componenti singolarmente:
- Sistema (
COMPONENT_SYSTEM): rappresenta lo stato di sicurezza del sistema operativo e del sistema standard derivato dal campo del livello patch di sicurezza standard. - Moduli Mainline di sistema (
COMPONENT_SYSTEM_MODULES): Rappresenta lo stato di sicurezza dei componenti di sistema modulari (aggiornamenti di sistema Google Play) derivato da versioni di rilascio di moduli specifici. - Kernel (
COMPONENT_KERNEL): rappresenta lo stato di sicurezza del kernel del dispositivo, derivato direttamente dalla stringa della versione kernel.
A seconda del componente, la libreria fornisce fino a tre dimensioni di informazioni a livello di patch:
- SPL dispositivo (DSPL): il livello di patch attuale dei singoli componenti
in esecuzione sul dispositivo, interrogato in modo sincrono senza richieste di rete. Sistema
e date del calendario dei report Mainline (
DateBasedSecurityPatchLevel), mentre il kernel segnala la versione di rilascio (VersionedSecurityPatchLevel, ad esempio5.15.148). - SPL pubblicato (PSPL): la baseline pubblicata ufficialmente nel Bollettino sulla sicurezza di Android e nei report del database Open Source Vulnerabilities (OSV). La tua app può valutare la conformità confrontando le date o le stringhe di versione fornite da Device SPL.
- SPL (ASPL) disponibile: indica se un dispositivo ha aggiornamenti in attesa
disponibili dai fornitori di aggiornamenti, eseguiti in modo asincrono utilizzando IPC. La funzionalità di aggiornamento di sistema Google Play di Android
fornisce la disponibilità per i moduli Mainline,
mentre i client OTA OEM forniscono la disponibilità per gli aggiornamenti di sistema. Poiché gli aggiornamenti del kernel sono inclusi nell'immagine di sistema, la disponibilità degli aggiornamenti del kernel viene valutata utilizzando
COMPONENT_SYSTEM.
Funzionalità sensibili alla sicurezza del cancello
Puoi combinare le informazioni di Device SPL (DSPL), Available SPL (ASPL) e
Published SPL (PSPL) per determinare in modo contestuale l'accesso
alle funzionalità sensibili alla sicurezza. Ad esempio, puoi confrontare DSPL e ASPL per
determinare se è disponibile una patch di sicurezza più recente che l'utente non ha ancora
installato, invitandolo a eseguire l'aggiornamento prima di avviare operazioni sensibili come
pagamenti o registrazione delle credenziali. Puoi anche utilizzare areCvesPatched() per
verificare se vulnerabilità specifiche e ad alto rischio sono state corrette sul
dispositivo prima di richiamare sottosistemi vulnerabili, ad esempio per verificare la presenza di vulnerabilità critiche NFC
o Bluetooth prima di autorizzare pagamenti o condivisione di dati
basati sulla prossimità.
Considerazioni sulla versione della piattaforma
Alcune funzionalità dello stato di sicurezza dipendono dall'architettura della piattaforma sottostante e non sono disponibili nelle versioni precedenti di Android:
- Android 11 (livello API 30) e versioni successive:supporto completo di tutti i componenti, incluse le versioni LTS del kernel pubblicate nel bollettino e le query sulla disponibilità degli aggiornamenti (ASPL).
- Android 10 (livello API 29): supporta i livelli di patch del sistema e dei moduli di sistema; tuttavia, le versioni kernel pubblicate nel bollettino non sono disponibili perché il monitoraggio dell'immagine del kernel generico (GKI) e i target LTS del kernel nel Bollettino sulla sicurezza di Android sono iniziati in Android 11. La versione kernel sul dispositivo può comunque essere letta localmente.
- Android 9 (livello API 28) e versioni precedenti:oltre alle limitazioni di Android 10, i componenti modulari del sistema (Project Mainline) non esistevano prima di Android 10.
La chiamata
getDeviceSecurityPatchLevel(COMPONENT_SYSTEM_MODULES)torna in modo sicuro alla data dell'epoca Unix di base (1970-01-01) quando gli SPL del modulo di sistema non sono disponibili.
Informazioni sulla disponibilità degli aggiornamenti e sull'ASPL (Available SPL)
Per determinare il security posture di un dispositivo, è necessario sapere se sono disponibili aggiornamenti della sicurezza in attesa per i singoli componenti. I dispositivi Android ricevono aggiornamenti della sicurezza tramite diversi meccanismi di distribuzione distinti, ad esempio aggiornamenti di sistema over-the-air (OTA) e aggiornamenti di sistema Google Play per i componenti modulari.
Prima che la tua app possa recuperare l'ASPL per un determinato componente, il provider di aggiornamenti corrispondente deve pubblicare queste informazioni. Per coordinarsi tra queste diverse origini di aggiornamento, le applicazioni client utilizzano la libreria AndroidX Security State per eseguire query sullo stato di sicurezza, mentre i client di aggiornamento sul dispositivo utilizzano la libreria complementare AndroidX Security State Provider per pubblicare il livello patch di sicurezza disponibile (ASPL).
Google fornisce informazioni sugli aggiornamenti dei moduli Mainline a tutti i dispositivi Android GMS, nonché informazioni OTA di sistema per i dispositivi che utilizzano il client OTA di Google (GOTA).
Il seguente diagramma illustra come le applicazioni client utilizzano la libreria AndroidX Security State per eseguire query sulla postura di sicurezza sia negli aggiornamenti di sistema Google Play sia negli aggiornamenti OTA del sistema:

Aggiungi dipendenze
Per aggiungere una dipendenza da AndroidX Security State, devi includere il repository Maven di Google nel tuo progetto. Aggiungi la dipendenza al file build.gradle.kts o build.gradle della tua app:
Kotlin
// Kotlin DSL (build.gradle.kts)
dependencies {
implementation("androidx.security:security-state:1.1.0")
}
Alla moda
// Groovy DSL (build.gradle)
dependencies {
implementation "androidx.security:security-state:1.1.0"
}
Matrice delle autorizzazioni dichiarate
| API target | Autorizzazioni obbligatorie in AndroidManifest.xml |
Note operative |
|---|---|---|
getDeviceSecurityPatchLevel() |
Nessuno | Legge in modo sincrono le proprietà di sistema native locali e i metadati del pacchetto. |
fetchAvailableSecurityPatchLevel()queryAllAvailableUpdates() |
Nessuno | Comunica utilizzando l'IPC on-device. La libreria esegue query solo sui componenti attendibili del dispositivo (richiedendo ai fornitori di aggiornamenti di disporre dell'autorizzazione privilegiata READ_PRIVILEGED_PHONE_STATE), in modo che la tua app possa avere la certezza dell'autenticità delle informazioni che riceve. |
createVulnerabilityReportUrl()loadVulnerabilityReport()getPublishedSecurityPatchLevel()areCvesPatched()isDeviceFullyUpdated() |
android.permission.INTERNET |
Obbligatorio per recuperare i report OSV pubblici. Una volta caricati in memoria utilizzando loadVulnerabilityReport(), i metodi di query vengono eseguiti localmente senza accesso alla rete. |
Inizializzare la libreria
Inizializza SecurityPatchState con un Context Android:
Kotlin
import androidx.security.state.SecurityPatchState
val securityPatchState = SecurityPatchState(context)
Java
import androidx.security.state.SecurityPatchState;
SecurityPatchState securityPatchState = new SecurityPatchState(context);
L'inizializzazione con context da solo fornisce l'accesso immediato ai livelli di patch del dispositivo offline senza dipendenze di rete. (Aggiorna le query di disponibilità
comunica in modo asincrono con i fornitori sul dispositivo).
Se la tua app valuta la conformità alle CVE e ha già caricato in memoria un report sulle vulnerabilità OSV, i chiamanti Kotlin possono passare la stringa JSON direttamente al costruttore in Kotlin:
val securityPatchState = SecurityPatchState(context, vulnerabilityReportJsonString = jsonString)
In Java o durante il caricamento asincrono dei report dopo l'avvio, inizializza con
il contesto e chiama securityPatchState.loadVulnerabilityReport(jsonString).
Controllare i livelli delle patch del dispositivo
Esegui query sui livelli di patch sul dispositivo in modo sincrono:
Kotlin
val deviceSpl = securityPatchState.getDeviceSecurityPatchLevel(SecurityPatchState.COMPONENT_SYSTEM)
val mainlineSpl = securityPatchState.getDeviceSecurityPatchLevel(SecurityPatchState.COMPONENT_SYSTEM_MODULES)
val kernelVersion = securityPatchState.getDeviceSecurityPatchLevel(SecurityPatchState.COMPONENT_KERNEL)
// Gatekeeping check: compare against a required baseline patch date
val requiredSpl = SecurityPatchState.DateBasedSecurityPatchLevel.fromString("2026-01-01")
if (deviceSpl < requiredSpl) {
// Restrict access to sensitive features or guide user to update
}
Java
SecurityPatchState.SecurityPatchLevel deviceSpl = securityPatchState.getDeviceSecurityPatchLevel(SecurityPatchState.COMPONENT_SYSTEM);
SecurityPatchState.SecurityPatchLevel mainlineSpl = securityPatchState.getDeviceSecurityPatchLevel(SecurityPatchState.COMPONENT_SYSTEM_MODULES);
SecurityPatchState.SecurityPatchLevel kernelVersion = securityPatchState.getDeviceSecurityPatchLevel(SecurityPatchState.COMPONENT_KERNEL);
// Gatekeeping check: compare against a required baseline patch date
SecurityPatchState.SecurityPatchLevel requiredSpl = SecurityPatchState.DateBasedSecurityPatchLevel.fromString("2026-01-01");
if (deviceSpl.compareTo(requiredSpl) < 0) {
// Restrict access to sensitive features or guide user to update
}
Verificare la presenza di aggiornamenti di sistema in attesa
Le app possono valutare la disponibilità di aggiornamenti in attesa comunicando in modo asincrono con provider di aggiornamenti attendibili sul dispositivo, in genere aggiornamenti di sistema Google Play e client OTA OEM:
fetchAvailableSecurityPatchLevel(): restituisce l'SPL disponibile effettivo per un componente specificato (con fallback all'SPL del dispositivo attuale se non è disponibile un aggiornamento più recente) che può essere utilizzato per il confronto con l'SPL del dispositivo e l'SPL pubblicata.queryAllAvailableUpdates(): rileva tutti i fornitori di aggiornamenti attendibili sul dispositivo e restituisceUpdateCheckResultgranulari insieme ai metadati sull'origine e sulla freschezza dei dati.
Esempio 1: richiedere agli utenti gli aggiornamenti in attesa
Utilizza fetchAvailableSecurityPatchLevel() per chiedere agli utenti quando sono disponibili aggiornamenti della sicurezza (ad esempio, avviando Settings.ACTION_SYSTEM_UPDATE_SETTINGS):
Kotlin
import androidx.lifecycle.lifecycleScope
import androidx.security.state.SecurityPatchState
import kotlinx.coroutines.launch
// Pattern A: Prompt users for pending updates (with automatic offline fallback)
lifecycleScope.launch {
val currentSpl = securityPatchState.getDeviceSecurityPatchLevel(SecurityPatchState.COMPONENT_SYSTEM)
val availableSpl = securityPatchState.fetchAvailableSecurityPatchLevel(SecurityPatchState.COMPONENT_SYSTEM)
if (availableSpl > currentSpl) {
// Prompt the user to install pending updates in system settings
}
}
Java
In Java, i metodi asincroni restituiscono un ListenableFuture e indirizzano
i callback utilizzando ContextCompat.getMainExecutor():
import androidx.core.content.ContextCompat;
import androidx.security.state.SecurityPatchState;
import androidx.security.state.SecurityPatchState.SecurityPatchLevel;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
// Pattern A: Prompt users for pending updates (with automatic offline fallback)
SecurityPatchLevel currentSpl = securityPatchState.getDeviceSecurityPatchLevel(SecurityPatchState.COMPONENT_SYSTEM);
ListenableFuture<SecurityPatchLevel> availableSpl = securityPatchState.fetchAvailableSecurityPatchLevelAsync(
SecurityPatchState.COMPONENT_SYSTEM,
SecurityPatchState.UPDATE_INFO_SERVICE_BINDING_TIMEOUT_MS
);
Futures.addCallback(availableSpl, new FutureCallback<SecurityPatchLevel>() {
@Override
public void onSuccess(SecurityPatchLevel available) {
if (available.compareTo(currentSpl) > 0) {
// Prompt the user to install pending updates in system settings
}
}
@Override
public void onFailure(Throwable t) {
// Handle timeout or IPC communication error
}
}, ContextCompat.getMainExecutor(context));
Esempio 2: esaminare lo stato dettagliato del fornitore
Utilizza queryAllAvailableUpdates() per esaminare singoli fornitori, timestamp e record UpdateInfo:
Kotlin
import androidx.lifecycle.lifecycleScope
import androidx.security.state.SecurityPatchState
import kotlinx.coroutines.launch
// Pattern B: Inspect detailed provider status
lifecycleScope.launch {
val updateResults = securityPatchState.queryAllAvailableUpdates()
for (result in updateResults) {
val provider = result.providerPackageName
val lastCheck = result.lastCheckTimeMillis
val updates = result.updates // List<UpdateInfo>
}
}
Java
import androidx.core.content.ContextCompat;
import androidx.security.state.SecurityPatchState;
import androidx.security.state.UpdateCheckResult;
import androidx.security.state.UpdateInfo;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.List;
// Pattern B: Inspect detailed provider status
ListenableFuture<List<UpdateCheckResult>> updateResults = securityPatchState.queryAllAvailableUpdatesAsync(
SecurityPatchState.UPDATE_INFO_SERVICE_BINDING_TIMEOUT_MS
);
Futures.addCallback(updateResults, new FutureCallback<List<UpdateCheckResult>>() {
@Override
public void onSuccess(List<UpdateCheckResult> results) {
for (UpdateCheckResult result : results) {
String provider = result.getProviderPackageName();
long lastCheck = result.getLastCheckTimeMillis();
List<UpdateInfo> updates = result.getUpdates();
}
}
@Override
public void onFailure(Throwable t) {
// Handle error
}
}, ContextCompat.getMainExecutor(context));
Verifica la risoluzione delle vulnerabilità e controlla le CVE
Per valutare le mitigazioni delle CVE, verificare la conformità complessiva degli aggiornamenti o esaminare i livelli patch di sicurezza pubblicati (PSPL), la tua app deve prima ottenere e caricare un report sulle vulnerabilità OSV, come descritto nel riferimento API per SecurityPatchState.
Kotlin
// Load vulnerability report
val reportUrl = SecurityPatchState.createVulnerabilityReportUrl()
// ... download JSON string from reportUrl ...
securityPatchState.loadVulnerabilityReport(jsonString)
// Check overall update compliance against published bulletin
val isFullyUpdated = securityPatchState.isDeviceFullyUpdated()
val cves = listOf("CVE-2019-9501", "CVE-2020-3699", "CVE-2024-0016")
val isPatched = securityPatchState.areCvesPatched(cves)
// Get a list of all patched CVEs for a specific component and SPL
val deviceSpl = securityPatchState.getDeviceSecurityPatchLevel(SecurityPatchState.COMPONENT_SYSTEM)
val patchedSystemCVEs = securityPatchState.getPatchedCves(SecurityPatchState.COMPONENT_SYSTEM, deviceSpl)
// Inspect published SPL and kernel LTS target versions from the bulletin
val publishedSystemSpl = securityPatchState.getPublishedSecurityPatchLevel(SecurityPatchState.COMPONENT_SYSTEM)
val kernelLtsTargets = securityPatchState.getPublishedSecurityPatchLevel(SecurityPatchState.COMPONENT_KERNEL)
Java
// Load vulnerability report
Uri reportUrl = SecurityPatchState.createVulnerabilityReportUrl();
// ... download JSON string from reportUrl ...
securityPatchState.loadVulnerabilityReport(jsonString);
// Check overall update compliance against published bulletin
boolean isFullyUpdated = securityPatchState.isDeviceFullyUpdated();
List<String> cves = Arrays.asList("CVE-2019-9501", "CVE-2020-3699", "CVE-2024-0016");
boolean isPatched = securityPatchState.areCvesPatched(cves);
// Get a list of all patched CVEs for a specific component and SPL
SecurityPatchState.SecurityPatchLevel deviceSpl = securityPatchState.getDeviceSecurityPatchLevel(SecurityPatchState.COMPONENT_SYSTEM);
Map<SecurityPatchState.Severity, Set<String>> patchedSystemCVEs =
securityPatchState.getPatchedCves(SecurityPatchState.COMPONENT_SYSTEM, deviceSpl);
// Inspect published SPL and kernel LTS target versions from the bulletin
List<SecurityPatchState.SecurityPatchLevel> publishedSystemSpl =
securityPatchState.getPublishedSecurityPatchLevel(SecurityPatchState.COMPONENT_SYSTEM);
List<SecurityPatchState.SecurityPatchLevel> kernelLtsTargets =
securityPatchState.getPublishedSecurityPatchLevel(SecurityPatchState.COMPONENT_KERNEL);
Caricare i report sulle vulnerabilità
- Memorizzazione nella cache locale e aggiornamento di WorkManager:poiché i bollettini di sicurezza di Android
vengono pubblicati mensilmente, memorizza nella cache il file JSON scaricato nella memoria interna
(
context.filesDir) e pianifica un'attività periodica in background conWorkManager(preferibilmente ogni 24-48 ore) per aggiornare il report, leggendo dalla cache locale in modo sincrono all'avvio dell'app. - Threading in background: richiama
loadVulnerabilityReport()su un thread in background (Dispatchers.IOin Kotlin o unExecutorin Java) per evitare di bloccare il thread dell'interfaccia utente principale durante l'analisi dei record CVE. - Valutazione LTS del kernel:la chiamata di
getPatchedCves(COMPONENT_KERNEL, ...)genera unIllegalArgumentExceptioneareCvesPatched()non valuta le CVE del kernel. Valuta invece la sicurezza del kernel confrontando la versione del kernel del dispositivo con i target LTS del kernel comune Android restituiti dagetPublishedSecurityPatchLevel(COMPONENT_KERNEL)che corrispondono al ramo principale e secondario (ad es. confrontando un kernel5.15.140con il target5.15.159).
Risorse aggiuntive
Per saperne di più sullo stato di sicurezza del dispositivo, consulta le seguenti risorse:
Documentazione
- Pubblica lo stato di sicurezza del dispositivo
- Bollettini sulla sicurezza di Android
- Componenti del sistema modulare
- Generic Kernel Image (GKI)
- Patch di sicurezza supplementari
- API Play Integrity
- Database Open Source Vulnerabilities (OSV)
- Note di rilascio di Security State 1.1.0