La sécurité de votre application dépend de celle de l'OS sous-jacent. Pour atténuer les risques, votre application doit limiter les opérations sensibles à la sécurité avec une évaluation en temps réel de l'état de sécurité de l'appareil, en déterminant si l'appareil, en particulier ses composants système principaux, est entièrement à jour et protégé contre les failles publiées dans le bulletin de sécurité Android. La visibilité sur l'état de sécurité de l'appareil vous aide à établir des mesures de protection avant que votre application n'exécute des opérations à haut risque.
AndroidX Security State est une bibliothèque Jetpack qui fournit un accès unifié à l'état de sécurité d'un appareil Android. Il combine les API AOSP et les flux publics de vulnérabilités Android pour fournir un état de sécurité des appareils complet, précis et exploitable, au-delà du simple niveau du correctif de sécurité (SPL).
Présentation de l'architecture
Le schéma suivant illustre la façon dont la bibliothèque AndroidX Security State unifie les propriétés de la plate-forme sur l'appareil, les fournisseurs de mise à jour de la communication interprocessus (IPC) et les flux de vulnérabilités publiques dans un ensemble unique et cohérent d'API.

États et composants des correctifs de sécurité
L'avantage principal de l'utilisation de la bibliothèque Security State est sa capacité à fournir le niveau du correctif de sécurité (SPL) au niveau d'un composant précis. Au fil des ans, Android a introduit davantage de modules dans les mises à jour du système Google Play (projet Mainline), qui sont mises à jour à l'aide de Google Play indépendamment des mises à jour système OTA (Over-The-Air) standards, ce qui permet de fournir des correctifs de sécurité essentiels à une fréquence différente.
De même, alors que le niveau de correctif de sécurité impose généralement la version minimale requise de l'image générique du noyau (GKI), les mises à jour du noyau peuvent en fait être effectuées avant la planification du système. Il est possible que ces correctifs spécifiques au noyau ne soient pas entièrement capturés par la chaîne SPL principale du système.
Pour améliorer la transparence, la bibliothèque d'état de sécurité fournit un niveau de correctif effectif pour chacun des trois composants :
- Système (
COMPONENT_SYSTEM) : représente l'état de sécurité standard de l'OS et du système, dérivé du champ standard du niveau du correctif de sécurité. - Modules Mainline du système (
COMPONENT_SYSTEM_MODULES) : représente l'état de sécurité des composants système modulaires (mises à jour du système Google Play), qui est dérivé des versions de publication de modules spécifiques. - Noyau (
COMPONENT_KERNEL) : représente l'état de sécurité du noyau de l'appareil, directement dérivé de la chaîne de version du noyau.
Selon le composant, la bibliothèque fournit jusqu'à trois dimensions d'informations sur le niveau de correctif :
- Niveau de correctif de sécurité de l'appareil (DSPL) : niveau de correctif actuel des composants individuels exécutés sur l'appareil, interrogé de manière synchrone sans requêtes réseau. Les rapports système et Mainline indiquent les dates du calendrier (
DateBasedSecurityPatchLevel), tandis que le noyau indique sa version (VersionedSecurityPatchLevel, par exemple5.15.148). - Niveau de correctif de sécurité publié (PSPL) : niveau de référence officiellement publié dans les rapports du Bulletin sur la sécurité d'Android et de la base de données OSV (Open Source Vulnerabilities). Votre application peut évaluer la conformité en comparant les dates ou les chaînes de version fournies par le SPL de l'appareil.
- SPL (ASPL) disponible : indique si des mises à jour en attente sont disponibles pour un appareil auprès des fournisseurs de mises à jour. Ces mises à jour sont demandées de manière asynchrone à l'aide d'IPC. La fonctionnalité de mise à jour du système Google Play d'Android permet la disponibilité des modules Mainline, et les clients OTA OEM permettent la disponibilité des mises à jour du système. Étant donné que les mises à jour du noyau sont regroupées dans l'image système du système d'exploitation, la disponibilité des mises à jour du noyau est évaluée à l'aide de
COMPONENT_SYSTEM.
Gérer l'accès aux fonctionnalités sensibles à la sécurité
Vous pouvez combiner les informations de DSPL (Device Security Patch Level), ASPL (Available Security Patch Level) et PSPL (Published Security Patch Level) pour déterminer le contexte des fonctionnalités sensibles à la sécurité. Par exemple, vous pouvez comparer DSPL et ASPL pour déterminer si un correctif de sécurité plus récent est disponible et n'a pas encore été installé par l'utilisateur. Vous pouvez ainsi l'inviter à effectuer la mise à jour avant d'initier des opérations sensibles telles que des paiements ou l'enregistrement d'identifiants. Vous pouvez également utiliser areCvesPatched() pour vérifier si des failles spécifiques à haut risque ont été corrigées sur l'appareil avant d'appeler des sous-systèmes vulnérables. Par exemple, vous pouvez vérifier s'il existe des failles critiques liées à la technologie NFC ou Bluetooth avant d'autoriser les paiements de proximité ou le partage de données.
Remarques concernant la version de la plate-forme
Certaines fonctionnalités liées à l'état de sécurité dépendent de l'architecture de la plate-forme sous-jacente et ne sont pas disponibles sur les versions antérieures d'Android :
- Android 11 (niveau d'API 30) et versions ultérieures : compatibilité totale avec tous les composants, y compris les versions LTS du noyau publiées dans les bulletins et les requêtes de disponibilité des mises à jour (ASPL).
- Android 10 (niveau d'API 29) : compatible avec les niveaux de correctifs du système et des modules système. Toutefois, les versions de noyau publiées dans le bulletin ne sont pas disponibles, car le suivi de l'image de noyau générique (GKI) et les cibles LTS du noyau dans le bulletin sur la sécurité d'Android ont commencé dans Android 11. La version de noyau sur l'appareil peut toujours être lue localement.
- Android 9 (niveau d'API 28) et versions antérieures : en plus des limites d'Android 10, les composants système modulaires (Project Mainline) n'existaient pas avant Android 10.
L'appel de
getDeviceSecurityPatchLevel(COMPONENT_SYSTEM_MODULES)revient de manière sécurisée à la date de référence de l'époque Unix (1970-01-01) lorsque les SPL des modules système ne sont pas disponibles.
Comprendre la disponibilité des mises à jour et le niveau de correctif de sécurité disponible (ASPL)
Pour déterminer la stratégie de sécurité d'un appareil, il est nécessaire de savoir si des mises à jour de sécurité en attente sont disponibles pour les composants individuels. Les appareils Android reçoivent des mises à jour de sécurité via plusieurs mécanismes de distribution distincts, tels que les mises à jour système OTA (over-the-air) et les mises à jour du système Google Play pour les composants modulaires.
Avant que votre application puisse récupérer l'ASPL pour un composant donné, le fournisseur de mise à jour correspondant doit publier ces informations. Pour coordonner ces différentes sources de mise à jour, les applications clientes utilisent la bibliothèque AndroidX Security State pour interroger l'état de sécurité, tandis que les clients de mise à jour sur l'appareil utilisent la bibliothèque AndroidX Security State Provider associée pour publier leur niveau de correctif de sécurité disponible (ASPL, Available Security Patch Level).
Google fournit des informations sur les mises à jour des modules Mainline à tous les appareils Android GMS, ainsi que des informations sur les mises à jour système OTA pour les appareils utilisant le client Google OTA (GOTA).
Le schéma suivant montre comment les applications clientes utilisent la bibliothèque AndroidX Security State pour interroger la posture de sécurité des mises à jour du système Google Play et des mises à jour OTA du système :

Ajouter des dépendances
Pour ajouter une dépendance à AndroidX Security State, vous devez inclure le dépôt Maven de Google dans votre projet. Ajoutez la dépendance au fichier build.gradle.kts ou build.gradle de votre application :
Kotlin
// Kotlin DSL (build.gradle.kts)
dependencies {
implementation("androidx.security:security-state:1.1.0")
}
Groovy
// Groovy DSL (build.gradle)
dependencies {
implementation "androidx.security:security-state:1.1.0"
}
Matrice des autorisations déclarées
| API cibles | Autorisations requises dans AndroidManifest.xml |
Remarques opérationnelles |
|---|---|---|
getDeviceSecurityPatchLevel() |
Aucune | Lit les propriétés du système natif et les métadonnées du package local de manière synchrone. |
fetchAvailableSecurityPatchLevel()queryAllAvailableUpdates() |
Aucune | Communique à l'aide de l'IPC sur l'appareil. La bibliothèque n'interroge que les composants approuvés de l'appareil (les fournisseurs de mise à jour doivent détenir l'autorisation privilégiée READ_PRIVILEGED_PHONE_STATE). Votre application peut donc être sûre de l'authenticité des informations qu'elle reçoit. |
createVulnerabilityReportUrl()loadVulnerabilityReport()getPublishedSecurityPatchLevel()areCvesPatched()isDeviceFullyUpdated() |
android.permission.INTERNET |
Nécessaire pour récupérer les rapports OSV publics. Une fois chargé en mémoire à l'aide de loadVulnerabilityReport(), les méthodes d'interrogation s'exécutent localement sans accès au réseau. |
Initialiser la bibliothèque
Initialisez SecurityPatchState avec 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'initialisation avec context seul permet d'accéder immédiatement aux niveaux de correctifs des appareils hors connexion, sans dépendance réseau. (Les requêtes de disponibilité de mise à jour communiquent de manière asynchrone avec les fournisseurs sur l'appareil.)
Si votre application évalue la conformité CVE et a déjà chargé un rapport de vulnérabilité OSV en mémoire, les appelants Kotlin peuvent transmettre la chaîne JSON directement au constructeur en Kotlin :
val securityPatchState = SecurityPatchState(context, vulnerabilityReportJsonString = jsonString)
En Java ou lors du chargement asynchrone des rapports après le démarrage, initialisez avec le contexte et appelez securityPatchState.loadVulnerabilityReport(jsonString).
Vérifier les niveaux de correctifs de l'appareil
Interrogez les niveaux de correctifs sur l'appareil de manière synchrone :
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
}
Vérifier si des mises à jour du système sont en attente
Les applications peuvent évaluer la disponibilité des mises à jour en attente en communiquant de manière asynchrone avec des fournisseurs de mises à jour fiables sur l'appareil, le plus souvent les mises à jour du système Google Play et les clients OTA OEM :
fetchAvailableSecurityPatchLevel(): renvoie le SPL disponible effectif pour un composant spécifié (en revenant au SPL de l'appareil actuel si aucune mise à jour plus récente n'est disponible), qui peut être utilisé pour le comparer au SPL de l'appareil et au SPL publié.queryAllAvailableUpdates(): découvre tous les fournisseurs de mises à jour fiables sur l'appareil et renvoie desUpdateCheckResultprécis, ainsi que des métadonnées sur la source et la fraîcheur des données.
Exemple 1 : Inviter les utilisateurs à effectuer les mises à jour en attente
Utilisez fetchAvailableSecurityPatchLevel() pour inviter les utilisateurs lorsque des mises à jour de sécurité sont disponibles (par exemple, en lançant 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
En Java, les méthodes asynchrones renvoient un ListenableFuture et acheminent les rappels à l'aide de 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));
Exemple 2 : Inspecter l'état détaillé d'un fournisseur
Utilisez queryAllAvailableUpdates() pour inspecter les fournisseurs individuels, les codes temporels et les enregistrements 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));
Vérifier la résolution des failles et vérifier les CVE
Pour évaluer les mesures d'atténuation des CVE, vérifier la conformité globale des mises à jour ou inspecter les niveaux de correctifs de sécurité publiés (PSPL), votre application doit d'abord obtenir et charger un rapport de vulnérabilité OSV, comme indiqué dans la documentation de référence de l'API pour 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);
Charger les rapports sur les failles
- Mise en cache locale et actualisation de WorkManager : les bulletins sur la sécurité d'Android étant publiés tous les mois, mettez en cache le fichier JSON téléchargé dans la mémoire de stockage interne (
context.filesDir) et planifiez une tâche périodique en arrière-plan avecWorkManager(de préférence toutes les 24 à 48 heures) pour actualiser le rapport, en lisant le cache local de manière synchrone au lancement de l'application. - Threading en arrière-plan : appelez
loadVulnerabilityReport()sur un thread en arrière-plan (Dispatchers.IOen Kotlin ouExecutoren Java) pour éviter de bloquer le thread d'UI principal lors de l'analyse des enregistrements CVE. - Évaluation LTS du noyau : l'appel de
getPatchedCves(COMPONENT_KERNEL, ...)génère uneIllegalArgumentException, etareCvesPatched()n'évalue pas les CVE du noyau. Évaluez plutôt la sécurité du noyau en comparant la version du noyau de l'appareil aux cibles LTS du noyau commun Android renvoyées pargetPublishedSecurityPatchLevel(COMPONENT_KERNEL)correspondant à sa branche principale et secondaire (par exemple, en comparant un noyau5.15.140à la cible5.15.159).
Ressources supplémentaires
Pour en savoir plus sur l'état de sécurité des appareils, consultez les ressources suivantes :
Documentation
- Bulletins sur la sécurité d'Android
- Composants du système modulaire
- Image générique du noyau (GKI)
- Correctifs de sécurité supplémentaires
- API Play Integrity
- Base de données Open Source Vulnerabilities (OSV)
- Notes de version de Security State 1.1.0