لا يكون تطبيقك آمنًا إلا إذا كان نظام التشغيل الأساسي آمنًا. للحدّ من المخاطر، يجب أن يقيّد تطبيقك العمليات الحسّاسة للأمان بتقييم في الوقت الفعلي لوضع الأمان على الجهاز، وتحديد ما إذا كان الجهاز، وخاصةً مكونات النظام الأساسية، محدَّثًا بالكامل ومحميًا من الثغرات الأمنية المنشورة في نشرة أمان Android. تساعدك إمكانية الاطّلاع على حالة أمان الجهاز في وضع ضمانات قبل أن ينفّذ تطبيقك عمليات عالية الخطورة.
AndroidX Security State هي مكتبة Jetpack توفّر إمكانية وصول موحّدة إلى حالة الأمان لجهاز يعمل بنظام التشغيل Android. تجمع هذه الخدمة بين واجهات برمجة التطبيقات في مشروع Android المفتوح المصدر (AOSP) وخلاصات الثغرات الأمنية العامة في Android لتقديم حالة أمان شاملة ودقيقة وقابلة للتنفيذ للجهاز، وذلك بما يتجاوز مجرد مستوى رمز تصحيح الأمان (SPL).
نظرة عامة على البنية
يوضّح المخطّط التالي كيف توحّد مكتبة AndroidX Security State خصائص النظام الأساسي على الجهاز فقط وموفّري تحديثات التواصل البيني للعمليات (IPC) وخلاصات الثغرات الأمنية العامة في مجموعة واحدة ومتماسكة من واجهات برمجة التطبيقات.

حالات ومكوّنات رمز تصحيح الأمان
تتمثّل الميزة الأساسية لاستخدام مكتبة حالة الأمان في قدرتها على توفير مستوى رمز تصحيح الأمان (SPL) على مستوى دقيق للمكوّنات. على مر السنين، أضاف Android المزيد من الوحدات إلى تحديثات نظام Google Play (مشروع Mainline) التي يتم تحديثها باستخدام Google Play بشكل مستقل عن تحديثات النظام العادية عبر اتصال لاسلكي (OTA)، ما يوفّر إصلاحات أمان مهمة بمعدل مختلف.
وبالمثل، على الرغم من أنّ مستوى رمز تصحيح الأمان يفرض عادةً الحد الأدنى المطلوب من إصدار Generic Kernel Image (GKI)، يمكن أن تسبق تحديثات النواة الجدول الزمني للنظام. قد لا يتم تضمين هذه الإصلاحات الخاصة بنواة النظام بالكامل في سلسلة SPL الأساسية للنظام.
لتحسين الشفافية، يوفّر مكتبة حالة الأمان مستوى تصحيح فعّالاً لجميع المكوّنات الثلاثة بشكلٍ فردي:
- النظام (
COMPONENT_SYSTEM): يمثّل نظام التشغيل العادي وحالة أمان النظام المستمدّة من حقل مستوى رمز تصحيح الأمان العادي. - وحدات Mainline للنظام (
COMPONENT_SYSTEM_MODULES): تمثّل حالة الأمان لمكوّنات النظام النموذجية (تحديثات نظام Google Play)، وهي مستمدّة من إصدارات معيّنة من الوحدات. - النواة (
COMPONENT_KERNEL): تمثّل حالة الأمان الخاصة بنواة الجهاز، وهي مستمَدة مباشرةً من سلسلة إصدار النواة.
استنادًا إلى المكوّن، توفّر المكتبة ما يصل إلى 3 سمات من معلومات مستوى تصحيح الأخطاء:
- مستوى تصحيح أمان الجهاز (DSPL): هو مستوى التصحيح الحالي للمكوّنات الفردية
التي تعمل على الجهاز، ويتم طلبه بشكل متزامن بدون طلبات شبكة. تتضمّن تواريخ تقويم تقارير النظام وMainline (
DateBasedSecurityPatchLevel)، بينما يوضّح تقرير النواة إصدارها (VersionedSecurityPatchLevel، مثل5.15.148). - مستوى تصحيح الأمان المنشور (PSPL): هو المستوى الأساسي المنشور رسميًا في نشرة أمان Android وتقارير قاعدة بيانات الثغرات الأمنية في المصادر المفتوحة (OSV). يمكن لتطبيقك تقييم الامتثال من خلال مقارنة التواريخ أو سلاسل الإصدارات التي يوفّرها تصحيح أمان نظام التشغيل على الجهاز.
- حزمة تصحيح الأمان المتاحة (ASPL): تشير إلى ما إذا كان الجهاز يتضمّن تحديثات معلَّقة
متاحة من موفّري التحديثات، ويتم طلبها بشكل غير متزامن باستخدام IPC. توفّر ميزة تحديث نظام Google Play على Android وحدات Mainline، وتوفّر برامج OTA الخاصة بمصنّعي المعدات الأصلية تحديثات النظام. بما أنّ تحديثات النواة مجمَّعة في صورة نظام التشغيل، يتم تقييم مدى توفّر تحديث النواة باستخدام
COMPONENT_SYSTEM.
حماية الميزات التي تتضمّن معلومات حساسة
يمكنك الجمع بين المعلومات من "مستوى تصحيح الأمان الخاص بالجهاز" (DSPL) و"مستوى تصحيح الأمان المتاح" (ASPL) و"مستوى تصحيح الأمان المنشور" (PSPL) لاتخاذ قرارات سياقية بشأن حظر الميزات التي تتطلّب مستوى أمان عاليًا. على سبيل المثال، يمكنك مقارنة DSPL مع ASPL لتحديد ما إذا كان هناك رمز تصحيح أمان أحدث لم يثبِّته المستخدم بعد، ما يدفعك إلى مطالبته بالتحديث قبل بدء عمليات حساسة، مثل الدفعات أو تسجيل بيانات الاعتماد. يمكنك أيضًا استخدام areCvesPatched() للتحقّق مما إذا تمت معالجة الثغرات الأمنية المحدّدة والشديدة الخطورة على الجهاز قبل استدعاء الأنظمة الفرعية المعرَّضة للخطر، مثل التحقّق من الثغرات الأمنية الخطيرة في NFC أو Bluetooth قبل السماح بعمليات الدفع أو مشاركة البيانات المستندة إلى التقارب.
اعتبارات إصدار النظام الأساسي
تعتمد بعض إمكانات حالة الأمان على بنية النظام الأساسي الأساسية، وهي غير متاحة في إصدارات Android الأقدم:
- الإصدار 11 من نظام التشغيل Android (المستوى 30 لواجهة برمجة التطبيقات) والإصدارات الأحدث: يتوافق هذا الإصدار بشكل كامل مع جميع المكوّنات، بما في ذلك إصدارات الدعم الطويل الأمد (LTS) لنواة النظام المنشورة في النشرة الاستشارية، والاستعلامات عن مدى توفّر التحديث (مستوى تصحيح الأمان في Android).
- الإصدار 10 من نظام التشغيل Android (مستوى واجهة برمجة التطبيقات 29): يتوافق مع مستويات تصحيح النظام ووحدة النظام، ولكن لا تتوفّر إصدارات النواة المنشورة في النشرة الإخبارية لأنّ تتبُّع صورة النواة العامة (GKI) واستهداف الدعم الطويل الأمد (LTS) لإصدار النواة في "نشرة أمان Android" بدأ في الإصدار 11 من نظام التشغيل Android، ولكن يمكن قراءة إصدار النواة على الجهاز فقط محليًا.
- نظام التشغيل Android 9 (مستوى واجهة برمجة التطبيقات 28) والإصدارات الأقدم: بالإضافة إلى القيود المفروضة على نظام التشغيل Android 10، لم تكن هناك مكوّنات نظام معيارية (Project Mainline) قبل Android 10.
يتم الرجوع إلى تاريخ بداية حقبة Unix الأساسي (1970-01-01) بأمان عند استدعاء
getDeviceSecurityPatchLevel(COMPONENT_SYSTEM_MODULES)في حال عدم توفّر حِزم SPL لوحدات النظام.
التعرّف على مدى توفّر التحديثات ومستوى تصحيح الأمان المتاح (ASPL)
يتطلّب تحديد مستوى أمان الجهاز معرفة ما إذا كانت هناك تحديثات أمان معلّقة متوفّرة للمكوّنات الفردية. تتلقّى أجهزة Android تحديثات الأمان من خلال آليات تسليم متعدّدة ومختلفة، مثل تحديثات النظام عبر الأثير (OTA) وتحديثات نظام Google Play للمكوّنات النموذجية.
قبل أن يتمكّن تطبيقك من استرداد ASPL لأحد المكوّنات، يجب أن ينشر موفّر التحديث المعنيّ هذه المعلومات. للتنسيق بين مصادر التحديث المختلفة هذه، تستخدم تطبيقات العميل مكتبة حالة الأمان في AndroidX للاستعلام عن حالة الأمان، بينما تستخدم برامج التحديث على الجهاز مكتبة موفّر حالة الأمان في AndroidX المصاحبة لنشر مستوى رموز تصحيح الأمان المتاح (ASPL).
توفّر Google معلومات التحديثات لوحدات Mainline لجميع أجهزة Android التي تعمل بنظام التشغيل GMS ، بالإضافة إلى معلومات تحديثات النظام عبر اتصال لاسلكي للأجهزة التي تستخدم برنامج Google لتحديثات النظام عبر اتصال لاسلكي (GOTA).
يوضّح المخطّط التالي كيف تستخدم تطبيقات العميل مكتبة AndroidX Security State للاستعلام عن حالة الأمان في كلّ من تحديثات نظام Google Play وتحديثات نظام التشغيل عبر الأثير:

إضافة التبعيات
لإضافة اعتمادية على AndroidX Security State، يجب تضمين مستودع Google Maven في مشروعك. أضِف التبعية إلى ملف build.gradle.kts أو build.gradle في تطبيقك:
Kotlin
// Kotlin DSL (build.gradle.kts)
dependencies {
implementation("androidx.security:security-state:1.1.0")
}
أنيق
// Groovy DSL (build.gradle)
dependencies {
implementation "androidx.security:security-state:1.1.0"
}
مصفوفة الأذونات التي تم تضمينها في نماذج البيان
| واجهات برمجة التطبيقات المستهدَفة | الأذونات المطلوبة في AndroidManifest.xml |
ملاحظات تشغيلية |
|---|---|---|
getDeviceSecurityPatchLevel() |
ما من شبكة | يقرأ خصائص النظام الأصلية المحلية وبيانات الحزمة الوصفية بشكل متزامن. |
fetchAvailableSecurityPatchLevel()queryAllAvailableUpdates() |
ما من شبكة | يتواصل باستخدام التواصل البيني للعمليات (IPC) على الجهاز فقط. لا تستعلم المكتبة إلا عن المكوّنات الموثوق بها على الجهاز (ما يتطلّب أن يكون لدى مقدّمي التحديثات إذن READ_PRIVILEGED_PHONE_STATE المميز)، لذا يمكن لتطبيقك الوثوق في صحة المعلومات التي يتلقّاها. |
createVulnerabilityReportUrl()loadVulnerabilityReport()getPublishedSecurityPatchLevel()areCvesPatched()isDeviceFullyUpdated() |
android.permission.INTERNET |
مطلوب لجلب تقارير OSV العامة. بعد تحميلها في الذاكرة باستخدام loadVulnerabilityReport()، يتم تنفيذ طرق البحث محليًا بدون الوصول إلى الشبكة. |
تهيئة المكتبة
ابدأ SecurityPatchState باستخدام Context على Android:
Kotlin
import androidx.security.state.SecurityPatchState
val securityPatchState = SecurityPatchState(context)
Java
import androidx.security.state.SecurityPatchState;
SecurityPatchState securityPatchState = new SecurityPatchState(context);
يوفّر التحديث باستخدام context وحده إمكانية الوصول الفوري إلى مستويات تصحيح الأمان على الجهاز غير المتصل بالإنترنت بدون الحاجة إلى شبكة. تتواصل طلبات البحث عن معلومات التوفّر بشكل غير متزامن مع مقدّمي الخدمات على الجهاز فقط.
إذا كان تطبيقك يقيّم مدى التوافق مع معرّفات CVE وقد حمّل تقريرًا عن الثغرات الأمنية في OSV إلى الذاكرة، يمكن لمستخدمي Kotlin تمرير سلسلة JSON مباشرةً إلى الدالة الإنشائية في Kotlin:
val securityPatchState = SecurityPatchState(context, vulnerabilityReportJsonString = jsonString)
في Java، أو عند تحميل التقارير بشكل غير متزامن بعد بدء التشغيل، عليك إجراء عملية الإعداد باستخدام
السياق واستدعاء securityPatchState.loadVulnerabilityReport(jsonString).
التحقّق من مستويات تصحيح الأمان على الجهاز
طلب مستويات رمز تصحيح الأمان على الجهاز فقط بشكل متزامن:
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
}
التحقّق من توفّر تحديثات معلّقة للنظام
يمكن للتطبيقات تقييم مدى توفّر التحديثات المعلّقة من خلال التواصل بشكل غير متزامن مع مقدّمي التحديثات الموثوق بهم على الجهاز فقط، وأكثرهم شيوعًا هم تحديثات نظام Google Play وبرامج المصنّعين الأصليين للجهاز التي يتم تنزيلها عبر الهواء:
-
fetchAvailableSecurityPatchLevel(): تعرض هذه السمة مستوى تصحيح الأمان الفعّال المتاح لأحد المكوّنات المحدّدة (مع الرجوع إلى مستوى تصحيح الأمان الحالي للجهاز في حال عدم توفّر أي تحديث أحدث) والذي يمكن استخدامه للمقارنة بين مستوى تصحيح الأمان للجهاز ومستوى تصحيح الأمان المنشور. queryAllAvailableUpdates(): تكتشف هذه الطريقة جميع مقدّمي التحديثات الموثوق بهم على الجهاز وتعرضUpdateCheckResultدقيقًا بالإضافة إلى البيانات الوصفية حول المصدر ومدى حداثة البيانات.
المثال 1: طلب إجراء التحديثات المعلّقة من المستخدمين
استخدِم fetchAvailableSecurityPatchLevel() لطلب إجراء تحديث من المستخدمين عند توفّر تحديثات الأمان (على سبيل المثال، من خلال تشغيل 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
في Java، تعرض الطرق غير المتزامنة ListenableFuture وتوجّه عمليات معاودة الاتصال باستخدام 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));
المثال 2: فحص حالة موفّر الخدمة المفصّلة
استخدِم queryAllAvailableUpdates() لفحص مقدّمي الخدمات والطوابع الزمنية وسجلات 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));
التحقّق من حلّ الثغرات الأمنية والاطّلاع على الثغرات الأمنية الشائعة (CVE)
لتقييم إجراءات الحدّ من الثغرات الأمنية الشائعة (CVE) أو التحقّق من الامتثال العام للتحديثات أو فحص مستويات رموز تصحيح الأمان المنشورة (PSPL)، يجب أن يحصل تطبيقك أولاً على تقرير ثغرات أمنية من OSV ويحمّله، كما هو موضّح بالتفصيل في مرجع واجهة برمجة التطبيقات الخاص بفئة 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);
تحميل تقارير الثغرات الأمنية
- التخزين المؤقت المحلي وإعادة التحميل باستخدام WorkManager: بما أنّ "نشرات أمان Android" يتم نشرها شهريًا، خزِّن ملف JSON الذي تم تنزيله في وحدة التخزين الداخلية (
context.filesDir) وجدول مهمة دورية تعمل في الخلفية باستخدامWorkManager(يُفضّل كل 24 إلى 48 ساعة) لإعادة تحميل التقرير، مع القراءة من ذاكرة التخزين المؤقت المحلية بشكل متزامن عند تشغيل التطبيق. - تنفيذ التعليمات البرمجية في سلسلة الخلفية: استدعِ
loadVulnerabilityReport()في سلسلة تعليمات في الخلفية (Dispatchers.IOفي Kotlin أوExecutorفي Java) لتجنُّب حظر سلسلة واجهة المستخدم الرئيسية أثناء تحليل سجلات الثغرات الأمنية الشائعة. - تقييم إصدار LTS من النواة: يؤدي استدعاء
getPatchedCves(COMPONENT_KERNEL, ...)إلى عرضIllegalArgumentException، ولا يقيّمareCvesPatched()ثغرات CVE في النواة. بدلاً من ذلك، يمكنك تقييم أمان النواة من خلال مقارنة إصدار نواة الجهاز بأهداف Android Common Kernel LTS التي تعرضهاgetPublishedSecurityPatchLevel(COMPONENT_KERNEL)، مع مطابقة الفرع الرئيسي والفرع الثانوي (على سبيل المثال، مقارنة نواة5.15.140بالهدف5.15.159).
مراجع إضافية
لمزيد من المعلومات حول حالة أمان الجهاز، يُرجى الاطّلاع على المراجع التالية:
الوثائق
- نشرات أمان Android
- مكوّنات النظام المعيارية
- صورة النواة العامة (GKI)
- تصحيحات أمان تكميلية
- Play Integrity API
- قاعدة بيانات الثغرات الأمنية في البرامج المفتوحة المصدر (OSV)
- ملاحظات الإصدار 1.1.0 من "حالة الأمان"