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

حالات رموز تصحيح الأمان ومكوّناتها
تتمثّل الميزة الأساسية لاستخدام مكتبة حالة الأمان في قدرتها على توفير مستوى رمز تصحيح الأمان (SPL) على مستوى دقيق للمكوّنات. على مر السنين، أضاف Android المزيد من الوحدات إلى تحديثات نظام Google Play (المعروفة باسم Project Mainline) التي يتم تحديثها باستخدام Google Play بشكل مستقل عن تحديثات النظام العادية عبر اتصال لاسلكي، ما يوفّر إصلاحات أمان مهمة بوتيرة مختلفة.
وبالمثل، على الرغم من أنّ مستوى رمز تصحيح الأمان يفرض عادةً الحد الأدنى المطلوب من إصدار صورة النواة العامة (GKI)، يمكن أن تسبق تحديثات النواة الجدول الزمني للنظام. قد لا يتم تضمين هذه الإصلاحات الخاصة بنواة النظام بشكل كامل في سلسلة SPL الأساسية للنظام.
لتحسين الشفافية، توفّر مكتبة حالة الأمان مستوى تصحيح فعّالاً لجميع المكوّنات الثلاثة بشكلٍ فردي:
- النظام (
COMPONENT_SYSTEM): يمثّل حالة الأمان العادية لنظام التشغيل والنظام، المستمدة من حقل مستوى رمز تصحيح الأمان العادي. - وحدات Mainline للنظام (
COMPONENT_SYSTEM_MODULES): تمثّل حالة الأمان لمكوّنات النظام النموذجية (تحديثات نظام Google Play)، وهي مستمدّة من إصدارات معيّنة من الوحدات. - النواة (
COMPONENT_KERNEL): تمثّل حالة الأمان لنواة الجهاز، وهي مستمَدة مباشرةً من سلسلة إصدار النواة.
استنادًا إلى المكوّن، توفّر المكتبة ما يصل إلى 3 سمات من معلومات مستوى التصحيح:
- مستوى تصحيح أمان الجهاز (DSPL): هو مستوى التصحيح الحالي للمكوّنات الفردية
التي تعمل على الجهاز، ويتم طلبه بشكل متزامن بدون طلبات شبكة. تتضمّن تقارير النظام وMainline تواريخ التقويم (
DateBasedSecurityPatchLevel)، بينما يوضّح تقرير النواة إصدارها (VersionedSecurityPatchLevel، مثل5.15.148). - مستوى تصحيح الأمان المنشور (PSPL): هو المستوى الأساسي المنشور رسميًا في نشرة أمان Android وتقارير قاعدة بيانات الثغرات الأمنية المفتوحة المصدر (OSV). يمكن لتطبيقك تقييم الامتثال من خلال مقارنة التواريخ أو سلاسل الإصدارات التي يوفّرها Device SPL.
- حزمة تصحيح الأمان المتاحة (ASPL): تشير إلى ما إذا كان الجهاز يتضمّن تحديثات معلَّقة
متاحة من مقدّمي التحديثات، ويتم طلبها بشكل غير متزامن باستخدام IPC. توفّر ميزة تحديث نظام Google Play على Android إمكانية الوصول إلى وحدات Mainline، كما يوفّر عملاء OTA من مصنّعي المعدات الأصلية إمكانية الوصول إلى تحديثات النظام. بما أنّ تحديثات النواة مضمّنة في صورة نظام التشغيل، يتم تقييم مدى توفّر تحديث النواة باستخدام
COMPONENT_SYSTEM.
حظر الميزات التي تتطلّب أذونات حساسة
يمكنك الجمع بين المعلومات الواردة من حزمة أمان الجهاز (DSPL) وحزمة الأمان المتاحة (ASPL) وحزمة الأمان المنشورة (PSPL) لاتخاذ قرارات سياقية بشأن حظر الميزات الحسّاسة للأمان. على سبيل المثال، يمكنك مقارنة DSPL مع ASPL لتحديد ما إذا كان هناك حزمة أمان أحدث لم يثبّتها المستخدم بعد، ما يدفعه إلى تثبيتها قبل بدء العمليات الحسّاسة، مثل عمليات الدفع أو تسجيل بيانات الاعتماد. يمكنك أيضًا استخدام areCvesPatched() للتحقّق مما إذا تمت معالجة الثغرات الأمنية المحدّدة والشديدة الخطورة على الجهاز قبل استدعاء الأنظمة الفرعية المعرَّضة للخطر، مثل التحقّق من الثغرات الأمنية الخطيرة في NFC أو Bluetooth قبل السماح بعمليات الدفع أو مشاركة البيانات المستندة إلى التقارب.
اعتبارات إصدار النظام الأساسي
تعتمد بعض إمكانات حالة الأمان على بنية النظام الأساسي الأساسية، وهي غير متاحة في إصدارات Android الأقدم:
- الإصدار 11 من نظام التشغيل Android (مستوى واجهة برمجة التطبيقات 30) والإصدارات الأحدث: يتوافق هذا الإصدار مع جميع المكوّنات، بما في ذلك إصدارات الدعم الطويل الأمد (LTS) لنواة النظام المنشورة في النشرة الأمنية، وطلبات البحث عن مدى توفّر التحديثات (ASPL).
- الإصدار 10 من نظام التشغيل Android (مستوى واجهة برمجة التطبيقات 29): يتوافق مع مستويات تصحيح النظام ووحدة النظام، إلا أنّ إصدارات النواة المنشورة في النشرة غير متاحة لأنّ تتبُّع صورة النواة العامة (GKI) واستهداف الدعم الطويل الأمد (LTS) لإصدار النواة في "نشرة أمان Android" بدأ في الإصدار 11 من نظام التشغيل Android، ولكن يمكن قراءة إصدار النواة على الجهاز فقط محليًا.
- نظام التشغيل Android 9 (مستوى واجهة برمجة التطبيقات 28) والإصدارات الأقدم: بالإضافة إلى القيود المفروضة على نظام التشغيل Android 10، لم تكن هناك مكونات نظام نمطية (Project Mainline) قبل نظام التشغيل Android 10.
يتم الرجوع إلى تاريخ حقبة يونكس الأساسي (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 باستخدام هاتف Android Context:
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 من "حالة الأمان"