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 insieme 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 livello di componente granulare. 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 riporta 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 disponibile (ASPL): 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
offre la disponibilità per i moduli Mainline,
mentre i client OTA OEM offrono 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 SPL dispositivo (DSPL), SPL disponibile (ASPL) e
SPL pubblicata (PSPL) per determinare in modo contestuale il controllo
delle 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 per 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 del modulo 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 a
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.
Comprendere la disponibilità degli aggiornamenti e l'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 loro 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 sul dispositivo. 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 essere certa 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 sulla 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 quando carichi i report in modo asincrono dopo l'avvio, inizializza con
il contesto e chiama securityPatchState.loadVulnerabilityReport(jsonString).
Controllare i livelli delle patch del dispositivo
Esegui query sincrone sui livelli di patch sul dispositivo:
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 fornitori di aggiornamenti attendibili sul dispositivo, in genere aggiornamenti di sistema Google Play e client OTA OEM:
fetchAvailableSecurityPatchLevel(): restituisce lo SPL disponibile effettivo per un componente specificato (utilizzando lo SPL del dispositivo corrente se non è disponibile un aggiornamento più recente) che può essere utilizzato per il confronto con lo SPL del dispositivo e lo SPL pubblicato.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 delle patch di sicurezza pubblicate (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à
- Aggiornamento di memorizzazione nella cache locale e WorkManager:poiché i bollettini di sicurezza 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
- 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