أمان Artisan وعملياته التشغيلية
لمحة سريعة
قسم بعنوان «لمحة سريعة»يَعرِض الجسر HTML قد يكون غير موثوق داخل Chrome، خلف حاجزَي شبكة مستقلَّين وسياسة محتوى صارمة. ويُعَدّ صندوق العزل على مستوى نظام التشغيل في Chrome ضابطًا منفصلًا واختياريًا له حدود صريحة. توثّق هذه الصفحة تلك الحدود، ولا تدّعي أنها مطلقة.
نظرة مفاهيمية عامة
قسم بعنوان «نظرة مفاهيمية عامة»العرض هو تنفيذ طلب من جانب الخادم: يمرّر تطبيقك HTML إلى محرك متصفح يمكنه جلب الموارد افتراضيًا. وعندما تؤدي مُدخلات غير موثوقة إلى عملية جلب صادرة، يكون الخطر هو تزوير الطلب من جانب الخادم (SSRF): يعرّفه مدخل CWE-918 في تعداد نقاط الضعف الشائعة (CWE) بأنه استرجاع الخادم لمحتوى عنوان URL مُقدَّم دون ضمان كافٍ بأن الطلب يصل إلى الوجهة المتوقعة. وSSRF (CWE-918) هو نقطة ضعف ضمن CWE Top 25. ويتطلب معيار التحقق من أمان التطبيقات (ASVS) الصادر عن مشروع أمان تطبيقات الويب العالمي المفتوح (OWASP) التحكم في الطلبات الصادرة من مكوّنات الخادم بدلًا من تركها ضمنية. وتتعامل ورقة OWASP المرجعية للوقاية من SSRF مع رفض الاستدعاءات إلى وجهات اعتباطية على مستوى الشبكة بوصفه الضابط الأقوى. والوضع الشبكي القائم على الرفض افتراضيًا أدناه هو استجابة الجسر لذلك المتطلب. ويصف المنشور الخاص (SP) 800-53 SC-7 الصادر عن المعهد الوطني للمعايير والتقنية (NIST) المبدأ نفسه لحدّ «الرفض الكامل والسماح بالاستثناء» الذي يطبّقه الجسر على طبقة النقل.
إقامة البيانات وتدابير تخفيف معلومات التعريف الشخصية
قسم بعنوان «إقامة البيانات وتدابير تخفيف معلومات التعريف الشخصية»يُعالَج HTML المُمرَّر إلى الجسر بالكامل داخل العملية وداخل نسخة Chrome المحلية. ولا يُجري الجسر أي استدعاء شبكي صادر خاص به، ويمنع Chrome من إجراء أي استدعاء (انظر نموذج الشبكة أدناه)، بحيث لا يغادر محتوى المُدخلات المضيف عبر محرك العرض. وتظهر معلومات التعريف الشخصية (PII) الموجودة في المُدخلات ضمن مخرجات تنسيق المستندات المحمولة (PDF) التي تنتجها، لذا عامِل المخرجات بضوابط الإقامة نفسها المطبَّقة على المُدخلات. ولا يحفظ الجسر المُدخلات أو المخرجات على القرص؛ فالحفظ مسؤولية المُستدعِي.
القياس عن بُعد الآمن وتنقية السجلات
قسم بعنوان «القياس عن بُعد الآمن وتنقية السجلات»يقبل ChromeHtmlRenderer وBrowserPool واجهة LoggerInterface اختيارية من توصية PHP القياسية (PSR)-3. ولا يسجّل الجسر سوى البيانات الوصفية التشغيلية: طول المُدخلات بالبايت، والعرض والارتفاع المستهدفين، وطول المخرجات بالبايت، وارتفاع المحتوى المقيس، وإطلاق المتصفح بمسار الملف الثنائي المُهيّأ، وإشعارات إعادة التشغيل مع عدد عمليات العرض، وأحداث الإغلاق. وهو لا يسجّل محتوى HTML أو البايتات المعروضة أو النص المُستخرَج. ويتوافق ذلك مع إرشاد NIST SP 800-92 بشأن تسجيل الأحداث التشغيلية مع إبقاء الحمولات الحساسة خارج السجلات. ويُسجَّل مسار الملف الثنائي؛ عامِله بوصفه بيانات وصفية للنشر غير حساسة. وتتحقق الاختبارات من أشكال استدعاءات السجل في tests/Unit/Artisan/ChromeHtmlRendererTest.php::renderLogsDebugWithSizeWidthHeightAndPdfSize وtests/Unit/Artisan/BrowserPoolTest.php::getBrowserLogsInfoOnLaunchWithBinaryPath.
نموذج عزل الشبكة (الدفاع المتعمّق)
قسم بعنوان «نموذج عزل الشبكة (الدفاع المتعمّق)»يطبّق الجسر حاجزَين مستقلَّين حتى لا يعرّض تجاوز أحدهما المضيف للخطر:
-
سياسة أمان المحتوى. تُغلَّف كل عملية عرض بواسطة
ChromeSecurityPolicy::wrapHtml()في مستند يحمل:default-src 'none'; style-src 'unsafe-inline'; img-src data:;base-uri 'none'; form-action 'none'; frame-ancestors 'none';navigate-to 'none';يرفض توجيه سياسة أمان المحتوى (CSP)
default-src 'none'جميع مصادر الموارد. ويسمحimg-src data:بالصور المضمَّنة فقط. ويحجبnavigate-to 'none'التنقل من جانب العميل. أماstyle-src 'unsafe-inline'فهو التخفيف الوحيد المطلوب كي يطبّقprintToPDFفي Chrome الأنماط المضمَّنة. تم التحقق منه فيsrc/Artisan/ChromeSecurityPolicy.phpوتؤكّدهChromeSecurityPolicyTest::wrapHtmlIncludesNavigationCspDirectives. -
حجب النقل في بروتوكول أدوات مطوّري Chrome (CDP). قبل تحميل المحتوى، يُصدِر
ChromeHtmlRendererالأمرNetwork.enableثمNetwork.setBlockedURLsبالنمط['*']. ويحجب ذلك كل عنوان URL لمورد فرعي على طبقة النقل في بروتوكول أدوات مطوّري Chrome، بشكل مستقل عن CSP. تم التحقق منه فيsrc/Artisan/ChromeHtmlRenderer::blockAllNetworkRequests()وتؤكّدهChromeHtmlRendererTest::renderAutoFitsHeightAndBlocksNetworkRequests(التي تتحقق من الترتيب الدقيق لطرق CDP ومن المعامل['urls' => ['*']]). وهذا هو الحجب على مستوى الشبكة الذي يوصي به إرشاد OWASP بشأن SSRF بوصفه الضابط الأقوى، وهو رفض كامل على مستوى النقل يتسق مع NIST SP 800-53 SC-7.
والنتيجة: لا يُحمَّل أي عنوان URL بعيد في المُدخلات لعنصر <img>، أو ورقة أنماط، أو خط، أو سكربت، أو إطار مضمَّن. ولا يطبّق الجسر قائمة سماح للنطاقات أو مرشّحًا لعناوين IP الخاصة لأنه لا يحتاج إلى ذلك: فهو لا يسمح بأي جلب صادر لمورد فرعي على الإطلاق.
ملاحظة انحراف: يقول التعليق البرمجي في
nextpdf/coreعلىwriteHtmlChrome()إن Chrome “سيجلب الموارد الخارجية” وينصح بتهيئة سياسة لـ “حجب نطاقات IP الخاصة وتقييد النطاقات المسموح بها.” وهذا يصف نموذج قائمة سماح قابلة للتهيئة. أماChromeSecurityPolicyالمُورَّد في Artisan فلا يكشف قائمة سماح؛ بل يحجب جميع طلبات الموارد الفرعية دون قيد أو شرط. والكود، لا التعليق البرمجي في النواة، هو المرجع الموثوق. وقد سُجِّل هذا الانحراف لدى فريق توثيق النواة.
التحقق من المُدخلات (قبل Chrome)
قسم بعنوان «التحقق من المُدخلات (قبل Chrome)»ChromeSecurityPolicy::validate() يُنفَّذ قبل أن يتصل الجسر بـ Chrome ويرفض:
| الفحص | الحدّ | المبرّر |
|---|---|---|
| حجم HTML | > maxHtmlSize (الافتراضي 5 MB) | حدّ لاستنزاف الموارد (الاستهلاك غير المُتحكَّم به للموارد ضمن CWE Top 25) |
| معرّف موارد موحَّد ببيانات base64 | مجموعة التقاط >= 13_000_000 بايت | حدّ لقنبلة فكّ الضغط |
<meta http-equiv="refresh"> | أيّ منها (غير حساس لحالة الأحرف، single/double quote) | يحجب عمليات إعادة التوجيه من جانب العميل إلى النقاط الطرفية الداخلية، وهي ناقل تنقّل لـ SSRF |
حجب meta-refresh تصليب صريح ضد SSRF. فبدونه، يمكن لـ HTML يتحكم به المهاجم أن يعيد توجيه Chrome إلى نقطة طرفية لبيانات السحابة الوصفية قبل printToPDF. ويُؤكَّد سلوك الحدّ عبر ChromeSecurityPolicyTest (validateThrowsOnOversizedHtml، validateRejectsMetaRefreshRedirect، validateRejectsMetaRefreshCaseInsensitive، validateRejectsMetaRefreshWithSingleQuotes، validateRejectsOversizedBase64DataUri، validateRejectsBase64DataUriAtExactThreshold).
وبالإضافة إلى ذلك، يجرّد ChromeSecurityPolicy::wrapHtml() الوسمَ </style> من defaultCss قبل الحقن لمنع الخروج من كتلة الأنماط إلى سياق السكربت (تؤكّده ChromeSecurityPolicyTest::wrapHtmlStripsStyleClosingTagsFromDefaultCss).
حدّ صندوق العزل في Chrome — مذكور صراحةً
قسم بعنوان «حدّ صندوق العزل في Chrome — مذكور صراحةً»صندوق العزل على مستوى نظام التشغيل في Chrome ضابط منفصل عن حواجز الشبكة أعلاه، ولا يضمنه الجسر.
- افتراضيًا، تكون قيمة
noSandboxهيfalse، لذا يُطلَق Chrome مع تفعيل صندوق العزل الخاص به. ولا يطبّق الجسر ذلك الصندوق؛ بل يعتمد على صندوق العزل في الملف الثنائي لـ Chrome، وهو بدوره يعتمد على دعم نواة المضيف. - يؤدي ضبط
noSandbox: trueإلى إطلاق Chrome مع--no-sandbox. وهذا يزيل صندوق عزل العمليات في Chrome. وهو متاح للحاويات التي يتعذّر فيها تهيئة صندوق العزل. ويمثّل ذلك خفضًا حقيقيًا للعزل: فاختراق محرك العرض لن يبقى محتوًى ضمن صندوق عزل Chrome. - تبقى حواجز الشبكة في الجسر (CSP + حجب CDP) سارية المفعول سواء أكان صندوق العزل مفعَّلًا أم لا، لكنها ليست بديلًا عن عزل العمليات. وينطبق إرشاد OWASP ASVS بشأن أقل الامتيازات: شغّل Chrome بمستخدم غير الجذر، وداخل حاوية مقيَّدة، واستخدم
noSandboxفقط عندما يتعذّر تجنّبه، وعامِل أي نشر بـ--no-sandboxبوصفه متطلبًا أعلى للثقة في المُدخلات.
لا يدّعي هذا التوثيق أن الجسر “آمن افتراضيًا” أو “مقاوم للعبث”. كما لا يدّعي أن تعطيل صندوق العزل آمن. بل يوضح الضوابط الموجودة وأين تتوقف. وتوفير حاوية قادرة على صندوق العزل مشروح في صفحة /integrations/artisan/chrome-renderer-setup/.
أنماط الفشل
قسم بعنوان «أنماط الفشل»أنماط الفشل هذه مأخوذة من src/Artisan/Exception/ وكود render/transport:
| الحالة | تظهر بوصفها | المصدر |
|---|---|---|
مكتبة chrome-php/chrome غائبة | ChromeNotAvailableException (مع أمر التثبيت) | BrowserPool::getBrowser() |
يتجاوز HTML maxHtmlSize | RuntimeException (“exceeds maximum allowed size“) | ChromeSecurityPolicy::validate() |
| معرّف موارد موحَّد ببيانات base64 مفرط الحجم | RuntimeException (“oversized base64 data URI“) | ChromeSecurityPolicy::validate() |
| meta-refresh ممنوع | RuntimeException (“forbidden meta refresh redirect“) | ChromeSecurityPolicy::validate() |
| إطلاق Chrome / انتهاء المهلة / تعطّل | ChromeRenderException (يغلّف السبب) | ChromeHtmlRenderer::render() |
| أعاد Chrome ملف PDF فارغًا | ChromeRenderException (“returned empty data“) | ChromeHtmlRenderer::render() |
| الصفحة لا تحتوي على دفق محتوى | PdfParseException | PageImporter::import() |
إذا أُثير ChromeRenderException داخل العرض، فيُعاد رميُه دون تغيير. ويُغلَّف أي Throwable آخر بوصفه ChromeRenderException، مع الحفاظ على الاستثناء السابق (تؤكّده ChromeHtmlRendererTest::renderRethrowsChromeRenderExceptionWithoutWrapping و::renderWrapsUnexpectedThrowablesWithChromeRenderException). وتُغلَق صفحة Chrome دائمًا في كتلة finally، حتى عند الفشل.
حدود الموارد
قسم بعنوان «حدود الموارد»- حجم المُدخلات:
maxHtmlSize(الافتراضي 5 MB) وسقف معرّف الموارد الموحَّد لبيانات base64 البالغ 13 MB. - الوقت: يحدّ
renderTimeoutبالثواني كلًّا من تحميل المحتوى واستدعاءات المزامنة في CDP. وتستخدم أوامر التحكم في CDP مهلة ثابتة قدرها 5 ثوانٍ. - العملية: يعيد
BrowserPoolتشغيل Chrome كل 100 عملية عرض للحد من نمو الذاكرة، ويغلق العملية عندclose()/ الإتلاف.
هذه حدود، لا حصص. ولأي مسار معرَّض لمُدخلات غير موثوقة، استخدم كذلك حدًّا للموارد على مستوى المضيف (cgroup أو ulimit أو ميزانية طلبات)، بما يتسق مع إرشاد CWE Top 25 بشأن استهلاك الموارد.
خطافات قابلية المراقبة
قسم بعنوان «خطافات قابلية المراقبة»احقن مُسجِّل PSR-3 لالتقاط بدء العرض (الحجم والعرض والارتفاع)، واكتمال العرض (حجم المخرجات وارتفاع المحتوى)، وإطلاق المتصفح (مسار الملف الثنائي)، وإعادة تشغيل المتصفح (عدد عمليات العرض)، وإغلاق المتصفح (عدد عمليات العرض). هذه هي الأحداث الوحيدة المُصدَرة، ولا تحمل أي محتوى للحمولة. استخدمها لأهداف مستوى الخدمة (SLOs) الخاصة بالكمون ولتنبيهات معدل إعادة التشغيل.
المطابقة
قسم بعنوان «المطابقة»| الادعاء | المرجع | clause_id | reference_id |
|---|---|---|---|
| يجب التحكم بالطلبات الصادرة من مكوّنات الخادم | OWASP ASVS 5.0 | § (SSRF/outbound control) | |
| SSRF = استرجاع الخادم عنوان URL مُقدَّمًا دون التحقق من الوجهة | CWE Top 25 2025 (CWE-918) | cwe_top25_2025#x28.x2.p2 | |
| SSRF (CWE-918) هو نقطة ضعف ضمن CWE Top 25 | CWE Top 25 2025 | cwe_top25_2025#x1.p73 | |
| الاستهلاك غير المُتحكَّم به للموارد هو نقطة ضعف ضمن CWE Top 25 | CWE Top 25 2025 (CWE-400) | cwe_top25_2025#x19.x2.p2 | |
| الحماية الحدّية بالرفض افتراضيًا (السماح بالاستثناء) | NIST SP 800-53 Rev 5 SC-7 | SC-7 | |
| الرفض على مستوى الشبكة للاستدعاءات إلى وجهات اعتباطية هو الضابط القوي ضد SSRF | OWASP Cheat Sheet Series (SSRF Prevention §Network layer) | owasp_cheatsheet_series#x132.x2 | |
| حماية مكوّنات جلب عناوين URL من SSRF | OWASP Cheat Sheet Series | § (SSRF prevention, URL-fetch tools) | |
| عزل عرض المحتوى غير الموثوق، وأقل الامتيازات | OWASP ASVS 5.0 | § (sandbox / least privilege) | |
| سجّل الأحداث التشغيلية؛ وأبقِ الحمولات خارج السجلات | NIST SP 800-92 | § (log content guidance) |
استُرجِعت الاستشهادات عبر محرك المطابقة في NextPDF (بيان فهرس المجموعة 1d05b7c4…d790b6)؛ ونص البند مُعاد صياغته، وليس مقتبسًا حرفيًا أبدًا.
نموذج التهديد
قسم بعنوان «نموذج التهديد»| التهديد | الضابط | الخطر المتبقي |
|---|---|---|
| SSRF عبر مورد فرعي بعيد | CSP default-src 'none' + CDP setBlockedURLs('*') | خلل في محرك Chrome يتجاوز الحاجزين معًا (الدفاع المتعمّق يقلل الخطر، لكنه لا يزيله) |
| SSRF عبر تنقّل meta-refresh | يرفض التحقق قبل Chrome الوسمَ | ناقل تنقّل جديد لا يطابق النمط |
| استنزاف الموارد | حجم المُدخلات + سقوف base64 + المهلة + إعادة التشغيل كل 100 عملية عرض | لا حصة لكل مضيف؛ أرفِقها بـ cgroup/ulimit |
| اختراق عملية محرك العرض | صندوق عزل Chrome عند تفعيله | noSandbox: true يزيل هذا الضابط بالكامل |
| كسر الأنماط / الحقن | تجريد </style> في defaultCss؛ وCSP يحجب السكربت | حقن عبر ناقل مستقبلي لا يُجرَّد |
سلوك وضع FIPS
قسم بعنوان «سلوك وضع FIPS»لا يُجري الجسر أي عمليات تشفيرية. بل ينتج بايتات PDF عبر Chrome ويضمّنها. والتوقيع والتشفير وسلوك وضع المعايير الفيدرالية لمعالجة المعلومات (FIPS) شؤون تخص النواة/الإصدار المميز، ولا تتأثر بـ Artisan.
انظر أيضًا
قسم بعنوان «انظر أيضًا»- /integrations/artisan/configuration/
- /integrations/artisan/chrome-renderer-setup/
- /integrations/artisan/troubleshooting/
- /integrations/artisan/production-usage/
- /integrations/artisan/overview/