ความปลอดภัยและการดำเนินงานของ Artisan
ภาพรวมโดยย่อ
หัวข้อที่มีชื่อว่า “ภาพรวมโดยย่อ”Bridge เรนเดอร์ HTML ที่อาจไม่น่าเชื่อถือภายใน Chrome ภายใต้กำแพงเครือข่ายอิสระสองชั้นและนโยบายเนื้อหาที่เข้มงวด แซนด์บ็อกซ์ระดับระบบปฏิบัติการของ Chrome เป็นการควบคุมแยกต่างหากและเป็นทางเลือก โดยมีข้อจำกัดที่ชัดเจน หน้านี้บันทึกขอบเขตเหล่านั้นไว้ และไม่ได้อ้างว่าขอบเขตดังกล่าวเป็นสิ่งสัมบูรณ์
ภาพรวมเชิงแนวคิด
หัวข้อที่มีชื่อว่า “ภาพรวมเชิงแนวคิด”การเรนเดอร์ถือเป็นการดำเนินการคำขอฝั่งเซิร์ฟเวอร์ แอปพลิเคชันของคุณส่ง HTML ไปยังเอนจินเบราว์เซอร์ที่ดึงทรัพยากรได้โดยค่าเริ่มต้น เมื่ออินพุตที่ไม่น่าเชื่อถือกำหนดการดึงข้อมูลขาออก ความเสี่ยงคือ server-side request forgery (SSRF) รายการ Common Weakness Enumeration (CWE) หมายเลข CWE-918 นิยามกรณีที่เซิร์ฟเวอร์ดึงเนื้อหาของ URL ที่ได้รับมา โดยไม่มีหลักประกันเพียงพอว่าคำขอจะไปถึงปลายทางที่คาดหวัง SSRF (CWE-918) เป็นจุดอ่อนใน CWE Top 25 Open Worldwide Application Security Project (OWASP) Application Security Verification Standard (ASVS) กำหนดให้คุณควบคุมคำขอขาออกจากองค์ประกอบฝั่งเซิร์ฟเวอร์ แทนที่จะปล่อยให้เกิดขึ้นโดยปริยาย OWASP SSRF Prevention Cheat Sheet ถือว่าการปฏิเสธการเรียกไปยังปลายทางใด ๆ ที่ระดับเครือข่ายเป็นการควบคุมที่แข็งแกร่ง แนวทางเครือข่ายแบบปฏิเสธโดยค่าเริ่มต้นด้านล่างนี้คือการตอบสนองของ bridge ต่อข้อกำหนดดังกล่าว National Institute of Standards and Technology (NIST) Special Publication (SP) 800-53 SC-7 อธิบายหลักการป้องกันขอบเขตที่ปฏิเสธทั้งหมดและอนุญาตเฉพาะข้อยกเว้น ซึ่งเป็นหลักการเดียวกับที่ bridge นำมาใช้ที่ชั้นการขนส่ง
ถิ่นที่อยู่ของข้อมูลและมาตรการลดความเสี่ยง PII
หัวข้อที่มีชื่อว่า “ถิ่นที่อยู่ของข้อมูลและมาตรการลดความเสี่ยง PII”HTML ที่ส่งไปยัง bridge จะถูกประมวลผลทั้งหมดภายในกระบวนการและอินสแตนซ์ Chrome ในเครื่อง Bridge ไม่ได้เรียกเครือข่ายขาออกใด ๆ เอง และบล็อก Chrome ไม่ให้เรียกเครือข่ายใด ๆ (ดูโมเดลเครือข่ายด้านล่าง) ดังนั้นเนื้อหาอินพุตจึงไม่ออกจากโฮสต์ผ่านตัวเรนเดอร์ ข้อมูลส่วนบุคคลที่ระบุตัวตนได้ (PII) ในอินพุตจะถูกเรนเดอร์ลงในเอาต์พุต Portable Document Format (PDF) ที่คุณสร้างขึ้น ดังนั้นจึงควรควบคุมถิ่นที่อยู่ของข้อมูลสำหรับเอาต์พุตเช่นเดียวกับอินพุต Bridge ไม่ได้คงข้อมูลอินพุตหรือเอาต์พุตไว้บนดิสก์ การเก็บคงไว้เป็นความรับผิดชอบของผู้เรียกใช้
เทเลเมทรีที่ปลอดภัยและการล้างข้อมูลออกจากบันทึก
หัวข้อที่มีชื่อว่า “เทเลเมทรีที่ปลอดภัยและการล้างข้อมูลออกจากบันทึก”ChromeHtmlRenderer และ BrowserPool รองรับ PHP Standard Recommendation (PSR)-3 LoggerInterface แบบไม่บังคับ Bridge บันทึกเฉพาะข้อมูลเมตาด้านการดำเนินงานเท่านั้น ได้แก่ ความยาวไบต์ของอินพุต ความกว้างและความสูงเป้าหมาย ความยาวไบต์ของเอาต์พุต ความสูงของเนื้อหาที่วัดได้ เหตุการณ์เปิดเบราว์เซอร์ด้วยเส้นทางไบนารีที่กำหนดค่าไว้ การแจ้งรีสตาร์ตพร้อมจำนวนการเรนเดอร์ และเหตุการณ์ปิด Bridge ไม่ บันทึกเนื้อหา HTML, ไบต์ที่เรนเดอร์ หรือข้อความที่สกัดออกมา แนวทางนี้สอดคล้องกับ NIST SP 800-92 ที่ให้บันทึกเหตุการณ์ด้านการดำเนินงาน และเก็บเพย์โหลดที่ละเอียดอ่อนไว้นอกบันทึก เส้นทางไบนารีถูกบันทึกไว้ ควรถือเป็นข้อมูลเมตาการปรับใช้ที่ไม่ละเอียดอ่อน การทดสอบยืนยันรูปแบบการเรียกบันทึกใน tests/Unit/Artisan/ChromeHtmlRendererTest.php::renderLogsDebugWithSizeWidthHeightAndPdfSize และ tests/Unit/Artisan/BrowserPoolTest.php::getBrowserLogsInfoOnLaunchWithBinaryPath
โมเดลการแยกตัวของเครือข่าย (การป้องกันเชิงลึก)
หัวข้อที่มีชื่อว่า “โมเดลการแยกตัวของเครือข่าย (การป้องกันเชิงลึก)”Bridge ใช้กำแพงอิสระสองชั้น เพื่อให้การข้ามผ่านชั้นหนึ่งไม่ทำให้โฮสต์ถูกเปิดเผย:
-
Content-Security-Policy การเรนเดอร์ทุกครั้งจะถูก
ChromeSecurityPolicy::wrapHtml()ห่อหุ้มไว้ในเอกสารที่มี:default-src 'none'; style-src 'unsafe-inline'; img-src data:;base-uri 'none'; form-action 'none'; frame-ancestors 'none';navigate-to 'none';คำสั่ง Content Security Policy (CSP)
default-src 'none'ปฏิเสธแหล่งที่มาของทรัพยากรทั้งหมดimg-src data:อนุญาตเฉพาะรูปภาพแบบอินไลน์เท่านั้นnavigate-to 'none'บล็อกการนำทางฝั่งไคลเอนต์style-src 'unsafe-inline'เป็นการผ่อนปรนเพียงอย่างเดียวที่จำเป็นเพื่อให้ ChromeprintToPDFใช้สไตล์แบบอินไลน์ได้ ตรวจสอบได้ในsrc/Artisan/ChromeSecurityPolicy.phpและยืนยันโดยChromeSecurityPolicyTest::wrapHtmlIncludesNavigationCspDirectives -
การบล็อกการขนส่ง Chrome DevTools Protocol (CDP) ก่อนโหลดเนื้อหา
ChromeHtmlRendererจะส่งคำสั่งNetwork.enableแล้วตามด้วยNetwork.setBlockedURLsด้วยรูปแบบ['*']การตั้งค่านี้บล็อก URL ของทรัพยากรย่อยทั้งหมดที่ชั้นการขนส่งของ Chrome DevTools Protocol โดยไม่ขึ้นกับ CSP ตรวจสอบได้ในsrc/Artisan/ChromeHtmlRenderer::blockAllNetworkRequests()และยืนยันโดยChromeHtmlRendererTest::renderAutoFitsHeightAndBlocksNetworkRequests(ซึ่งตรวจสอบลำดับเมธอด CDP ที่แน่นอนและพารามิเตอร์['urls' => ['*']]) นี่คือการบล็อกระดับเครือข่ายที่แนวทาง OWASP SSRF แนะนำว่าเป็นการควบคุมที่แข็งแกร่งที่สุด และเป็นการปฏิเสธทั้งหมดในระดับการขนส่งที่สอดคล้องกับ NIST SP 800-53 SC-7
ผลลัพธ์คือ <img> สไตล์ชีต ฟอนต์ สคริปต์ หรือ URL ของ iframe ระยะไกลในอินพุตจะไม่ถูกโหลด Bridge ไม่ได้ใช้รายการอนุญาตโดเมนหรือตัวกรอง IP ส่วนตัว เพราะไม่จำเป็น เนื่องจาก bridge ไม่อนุญาตให้ดึงทรัพยากรย่อยขาออกใด ๆ เลย
หมายเหตุความเบี่ยงเบน: docblock ของ
nextpdf/coreบนwriteHtmlChrome()ระบุว่า Chrome “will fetch external resources” และแนะนำให้กำหนดค่านโยบายเพื่อ “block private IP ranges and limit allowed domains” ข้อความนั้นอธิบายโมเดลรายการอนุญาตที่กำหนดค่าได้ChromeSecurityPolicyของ Artisan ที่จัดส่งมาไม่ได้เปิดเผยรายการอนุญาต แต่จะบล็อกคำขอทรัพยากรย่อย ทั้งหมด อย่างไม่มีเงื่อนไข โค้ดถือเป็นแหล่งอ้างอิงหลัก ไม่ใช่ docblock ของ core ความเบี่ยงเบนนี้บันทึกไว้ให้ทีมเอกสารของ core
การตรวจสอบอินพุต (ก่อน Chrome)
หัวข้อที่มีชื่อว่า “การตรวจสอบอินพุต (ก่อน Chrome)”ChromeSecurityPolicy::validate() ทำงานก่อนที่ bridge จะติดต่อ Chrome และปฏิเสธ:
| การตรวจสอบ | ขีดจำกัด | เหตุผล |
|---|---|---|
| ขนาด HTML | > maxHtmlSize (ค่าเริ่มต้น 5 MB) | ขอบเขตสำหรับการใช้ทรัพยากรจนหมด (การใช้ทรัพยากรอย่างไม่มีการควบคุมใน CWE Top 25) |
| Base64 data URI (URI ข้อมูลแบบ Base64) | ค่าที่จับได้ >= 13_000_000 ไบต์ | ขอบเขตการป้องกัน decompression bomb |
<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 เป็นการควบคุมที่ แยกต่างหาก จากกำแพงเครือข่ายข้างต้น และ bridge ไม่รับประกันว่าการควบคุมนี้จะมีอยู่
- โดยค่าเริ่มต้น
noSandboxมีค่าเป็นfalseดังนั้น Chrome จึงเริ่มทำงานพร้อมแซนด์บ็อกซ์ของตนเอง Bridge ไม่ได้จัดเตรียมแซนด์บ็อกซ์นี้เอง แต่อาศัยแซนด์บ็อกซ์ของไบนารี Chrome ซึ่งขึ้นอยู่กับการสนับสนุนเคอร์เนลของโฮสต์ - การตั้งค่า
noSandbox: trueจะเปิด Chrome ด้วย--no-sandboxซึ่ง นำออก แซนด์บ็อกซ์การแยกกระบวนการของ Chrome ตัวเลือกนี้มีไว้สำหรับคอนเทนเนอร์ที่ไม่สามารถเริ่มแซนด์บ็อกซ์ได้ และลดการแยกตัวลงอย่างแท้จริง: หากตัวเรนเดอร์ถูกบุกรุก จะไม่ถูกจำกัดด้วยแซนด์บ็อกซ์ของ Chrome อีกต่อไป - กำแพงเครือข่ายของ bridge (CSP + การบล็อก CDP) ยังคงมีผลบังคับไม่ว่าจะเปิดใช้งานแซนด์บ็อกซ์หรือไม่ก็ตาม แต่กำแพงเหล่านี้ไม่ใช่สิ่งทดแทนการแยกกระบวนการ แนวทางสิทธิ์น้อยที่สุดของ OWASP ASVS ยังคงต้องใช้: ให้รัน Chrome ในฐานะผู้ใช้ที่ไม่ใช่ root ในคอนเทนเนอร์ที่มีข้อจำกัด โดยใช้
noSandboxเฉพาะเมื่อหลีกเลี่ยงไม่ได้เท่านั้น และถือว่าการปรับใช้--no-sandboxเป็นข้อกำหนดที่ต้องเชื่อถืออินพุตมากขึ้น
เอกสารนี้ไม่ได้อ้างว่า bridge “secure by default” หรือ “tamper-proof” และไม่ได้อ้างว่าการปิดแซนด์บ็อกซ์เป็นสิ่งที่ปลอดภัย เอกสารนี้ระบุการควบคุมที่มีอยู่และจุดที่การควบคุมเหล่านั้นสิ้นสุดลง การจัดเตรียมคอนเทนเนอร์ที่รองรับแซนด์บ็อกซ์อธิบายไว้ในหน้า /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 data URI ที่มีขนาดใหญ่เกินไป | RuntimeException (“oversized base64 data URI” — Base64 data URI มีขนาดใหญ่เกินไป) | ChromeSecurityPolicy::validate() |
| meta-refresh ที่ต้องห้าม | RuntimeException (“forbidden meta refresh redirect” — การเปลี่ยนเส้นทาง meta refresh ที่ต้องห้าม) | 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 data-URI ที่ 13 MB - เวลา:
renderTimeoutวินาทีกำหนดขอบเขตทั้งการโหลดเนื้อหาและการเรียก CDP แบบ sync ส่วนคำสั่งควบคุม CDP ใช้การหมดเวลาคงที่ 5 วินาที - กระบวนการ:
BrowserPoolรีสตาร์ต Chrome ทุก ๆ 100 การเรนเดอร์เพื่อจำกัดการเติบโตของหน่วยความจำ และปิดกระบวนการเมื่อมีการเรียกclose()/ การทำลายอ็อบเจ็กต์
สิ่งเหล่านี้เป็นขอบเขต ไม่ใช่โควตา สำหรับเส้นทางใด ๆ ที่เปิดรับอินพุตที่ไม่น่าเชื่อถือ ยังคงต้องใช้ขีดจำกัดทรัพยากรระดับโฮสต์ (cgroup, ulimit, request budget) ให้สอดคล้องกับแนวทางด้านการใช้ทรัพยากรใน CWE Top 25
จุดเชื่อมต่อสำหรับการสังเกตการณ์
หัวข้อที่มีชื่อว่า “จุดเชื่อมต่อสำหรับการสังเกตการณ์”กำหนด PSR-3 logger เพื่อบันทึกการเริ่มเรนเดอร์ (ขนาด ความกว้าง ความสูง) การเรนเดอร์เสร็จสมบูรณ์ (ขนาดเอาต์พุต ความสูงของเนื้อหา) การเปิดเบราว์เซอร์ (เส้นทางไบนารี) การรีสตาร์ตเบราว์เซอร์ (จำนวนการเรนเดอร์) และการปิดเบราว์เซอร์ (จำนวนการเรนเดอร์) เหตุการณ์เหล่านี้เป็นเหตุการณ์เดียวที่ถูกปล่อยออกมา และไม่มีเนื้อหาเพย์โหลดแนบมาด้วย ใช้เหตุการณ์เหล่านี้สำหรับ service-level objectives (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 — เครื่องมือดึง URL) | |
| แยกการเรนเดอร์เนื้อหาที่ไม่น่าเชื่อถือ ใช้สิทธิ์น้อยที่สุด | OWASP ASVS 5.0 | § (sandbox / least privilege — แซนด์บ็อกซ์ / สิทธิ์น้อยที่สุด) | |
| บันทึกเหตุการณ์ด้านการดำเนินงาน เก็บเพย์โหลดไว้นอกบันทึก | NIST SP 800-92 | § (log content guidance — แนวทางเนื้อหาบันทึก) |
ดึงข้อมูลอ้างอิงผ่านเอนจินการปฏิบัติตามข้อกำหนดของ NextPDF (corpus manifest 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”Bridge ไม่ได้ทำงานด้านการเข้ารหัสลับใด ๆ Bridge สร้างไบต์ PDF ผ่าน Chrome และฝังไบต์ดังกล่าว การลงนาม การเข้ารหัสลับ และพฤติกรรมในโหมด Federal Information Processing Standards (FIPS) เป็นเรื่องของ core/Premium และไม่ได้รับผลกระทบจาก Artisan
ดูเพิ่มเติม
หัวข้อที่มีชื่อว่า “ดูเพิ่มเติม”- /integrations/artisan/configuration/ — การกำหนดค่า
- /integrations/artisan/chrome-renderer-setup/ — การตั้งค่าตัวเรนเดอร์ Chrome
- /integrations/artisan/troubleshooting/ — การแก้ไขปัญหา
- /integrations/artisan/production-usage/ — การใช้งานในการผลิตจริง
- /integrations/artisan/overview/ — ภาพรวม