Contracts / นโยบายความปลอดภัย
ภาพรวมโดยย่อ
หัวข้อที่มีชื่อว่า “ภาพรวมโดยย่อ”โดเมน security-policy กำหนด contract แบบปฏิเสธโดยปริยายไว้สามรายการ ได้แก่ CryptoPolicyInterface สำหรับควบคุมการเลือกอัลกอริทึมและคีย์ HtmlSecurityPolicyInterface สำหรับจำกัดขอบเขตฟีเจอร์ของ Hypertext Markup Language (HTML) และ ExternalResourcePolicyInterface สำหรับกำกับการโหลดทรัพยากรระยะไกล เนื่องจากแต่ละรายการเป็น contract คุณจึงสามารถกำหนดนโยบายสำหรับการ deploy ที่เข้มงวดยิ่งขึ้นได้โดยไม่ต้อง fork
การติดตั้ง
หัวข้อที่มีชื่อว่า “การติดตั้ง”composer require nextpdf/core:^3ภาพรวมเชิงแนวคิด
หัวข้อที่มีชื่อว่า “ภาพรวมเชิงแนวคิด”CryptoPolicyInterface เป็นเกตด้านการเข้ารหัสลับ Core เรียกใช้ contract นี้ก่อนขั้นตอนการลงนาม การเข้ารหัสลับ หรือการแฮชทุกรายการ การตรวจสอบครอบคลุมแฮช ตัวระบุออบเจ็กต์ของลายเซ็น (OID) ไซเฟอร์ และความแข็งแรงของคีย์ contract นี้ยังรายงานแฮชขั้นต่ำและชื่อนโยบายสำหรับบันทึกการตรวจสอบด้วย ใช้ contract นี้เพื่อบังคับใช้ชุดกฎ เช่น Federal Information Processing Standards (FIPS) 140-3 หรือ eIDAS โดยไม่ต้องเปลี่ยนโค้ดสำหรับการลงนามและการเข้ารหัสลับ เมื่อไม่ได้กำหนดนโยบายไว้ ทุกอัลกอริทึมจะได้รับอนุญาต ไซต์ที่อยู่ภายใต้การกำกับดูแลจึงต้องกำหนดนโยบายอย่างชัดเจน
HtmlSecurityPolicyInterface ทำงานที่ชั้นการแยกวิเคราะห์ HTML การตรวจสอบจะทำงานก่อนที่เนื้อหาจะไปถึงตัวเรนเดอร์ใด ๆ โดยพิจารณาว่าแท็ก แอตทริบิวต์ พร็อพเพอร์ตี้ Cascading Style Sheets (CSS) หรือสคีมา uniform resource locator (URL) ได้รับอนุญาตหรือไม่ และยังจำกัดขนาดอินพุตกับความลึกของการซ้อนด้วย การตรวจสอบนี้ทำงานร่วมกับนโยบายการขนส่งเฉพาะตัวเรนเดอร์ (Chrome, Cloudflare, Gotenberg) ซึ่งกำหนดขีดจำกัดขนาดและส่วนหัว Content Security Policy (CSP) นโยบาย HTML ช่วยลดพื้นผิวการโจมตีที่ชั้นการแยกวิเคราะห์ แท็กที่ถูกตัดออกจะไม่ไปถึงขั้นตอนการจัดวางเลย เอลิเมนต์ที่ถูกแทรกเข้ามาจึงไม่สามารถเปลี่ยนแปลงเอาต์พุตได้ เมื่อไม่ได้กำหนดนโยบายไว้ ค่าเริ่มต้นจะอนุญาตชุดฟีเจอร์ทั้งหมด
ExternalResourcePolicyInterface ตัดสินว่าไปป์ไลน์ HTML สามารถดึงฟอนต์ สไตล์ชีต หรือรูปภาพภายนอกได้หรือไม่ และกำหนดขีดจำกัดสำหรับการดึงแต่ละครั้งด้วย ท่าทีเริ่มต้นของ contract นี้คือปฏิเสธทั้งหมด ทุกตัวเลือกจะปิดอยู่จนกว่าคุณจะเปิดใช้งาน contract นี้ยึดหลักสิทธิ์น้อยที่สุด HTML ที่ไม่น่าเชื่อถืออาจชี้ไปยัง URL ที่ผู้โจมตีควบคุม contract นี้ควบคุมการดึง @font-face ตามสคีมา ขนาด และจำนวนกลิฟ ควบคุม @import ตามสคีมา ความลึก และขนาดรวม และควบคุม background-image ด้วยรายการสคีมาและรายการโดเมนที่อนุญาตแบบตรงทุกตัวอักษร contract นี้จำกัดขนาด data-URI (Uniform Resource Identifier) และยังควบคุมการอ้างอิงภายนอกของ Scalable Vector Graphics (SVG) ด้วย contract ระบุว่าระบบโปรดักชันต้องปฏิเสธรายการเหล่านั้นเสมอ เพราะเปิดทางให้เกิดการปลอมแปลงคำขอและการแทรกสคริปต์ การดึง URL แบบเปิดเป็นช่องทางการปลอมแปลงคำขอฝั่งเซิร์ฟเวอร์ การควบคุมการเข้าถึงถูกข้ามผ่านได้ด้วยการเปลี่ยน URL ตามที่ระบุไว้ใน Open Worldwide Application Security Project (OWASP) Top 10 2025 การจัดหาคอมโพเนนต์ภายนอกต้องจำกัดอยู่ที่แหล่งที่เป็นทางการและการขนส่งที่ปลอดภัยเท่านั้น
ขอบเขต API
หัวข้อที่มีชื่อว่า “ขอบเขต API”| ชนิด | ประเภท | สมาชิกหลัก | เสถียรภาพ | ตั้งแต่ |
|---|---|---|---|---|
CryptoPolicyInterface | interface | isHashAlgorithmAllowed(), isSignatureAlgorithmAllowed(), isEncryptionAlgorithmAllowed(), isKeyStrengthAllowed(), getPreferredHashAlgorithm(), getName() | เสถียร | 1.9.0 |
HtmlSecurityPolicyInterface | interface | isTagAllowed(), isAttributeAllowed(), isCssPropertyAllowed(), isUrlSchemeAllowed(), getMaxInputSize(), getMaxNestingDepth(), getName() | เสถียร | 3.1.0 |
ExternalResourcePolicyInterface | interface | isFontFaceAllowed(), getAllowedFontSchemes(), getMaxFontFileSize(), getMaxFontGlyphs(), isImportAllowed(), getMaxImportDepth(), isBackgroundImageAllowed(), getAllowedImageDomains(), getMaxDataUrlSize(), isSvgExternalReferenceAllowed() | เสถียร | 4.0.0 |
ExternalResourcePolicyInterface คืนค่าขีดจำกัดที่มีชนิดข้อมูลกำกับ ได้แก่ ขนาดแบบ positive-int ความลึกของการ import แบบ int<1, 100> และรายการสคีมากับโดเมนแบบ list<non-empty-string> การนำไปใช้งานค่าเริ่มต้นจะปฏิเสธทุกความสามารถ
ตัวอย่างโค้ด — เริ่มต้นอย่างรวดเร็ว
หัวข้อที่มีชื่อว่า “ตัวอย่างโค้ด — เริ่มต้นอย่างรวดเร็ว”<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\HtmlSecurityPolicyInterface;
/** * Decide whether a tag survives the policy. * * @param HtmlSecurityPolicyInterface $policy A core or custom policy. */function tagSurvives(HtmlSecurityPolicyInterface $policy, string $tag): bool{ return $policy->isTagAllowed($tag);}ฟังก์ชันนี้ขึ้นอยู่กับ contract เพียงอย่างเดียว ทั้งนโยบายที่เข้มงวดและนโยบายค่าเริ่มต้นจึงใช้งานกับฟังก์ชันนี้ได้
ตัวอย่างโค้ด — โปรดักชัน
หัวข้อที่มีชื่อว่า “ตัวอย่างโค้ด — โปรดักชัน”<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\CryptoPolicyInterface;use NextPDF\Contracts\ExternalResourcePolicyInterface;use NextPDF\Contracts\HtmlSecurityPolicyInterface;use Psr\Log\LoggerInterface;
final readonly class UntrustedHtmlGate{ public function __construct( private HtmlSecurityPolicyInterface $htmlPolicy, private ExternalResourcePolicyInterface $resourcePolicy, private CryptoPolicyInterface $cryptoPolicy, private LoggerInterface $logger, ) {}
/** * Reject input that exceeds the configured limits before rendering. * * @param string $html Untrusted HTML markup. */ public function assertAcceptable(string $html): void { $maxInput = $this->htmlPolicy->getMaxInputSize();
if ($maxInput > 0 && \strlen($html) > $maxInput) { $this->logger->warning('HTML rejected: input over limit', [ 'policy' => $this->htmlPolicy->getName(), 'limit' => $maxInput, ]);
throw new \LengthException('HTML input exceeds policy limit.'); }
if ($this->resourcePolicy->isSvgExternalReferenceAllowed()) { $this->logger->error('Unsafe policy: SVG external references enabled.');
throw new \LogicException('SVG external references must be denied in production.'); } }}เกตนี้บังคับใช้ขีดจำกัดอินพุตและปฏิเสธนโยบายทรัพยากรที่ไม่ปลอดภัยก่อนที่ไปป์ไลน์จะทำงาน พร้อมบันทึกชื่อนโยบายไว้สำหรับการตรวจสอบและโยน exception ที่เจาะจง
กรณีขอบและข้อควรระวัง
หัวข้อที่มีชื่อว่า “กรณีขอบและข้อควรระวัง”CryptoPolicyInterfaceจะอนุญาตทุกอัลกอริทึมเมื่อไม่ได้กำหนดนโยบายไว้ ค่าเริ่มต้นแบบเปิดมีไว้เพื่อความสะดวกในการพัฒนา ไม่ใช่ท่าทีสำหรับโปรดักชัน ต้องกำหนดนโยบายอย่างชัดเจนในการ deploy ที่อยู่ภายใต้การกำกับดูแลทุกครั้งHtmlSecurityPolicyInterface::getMaxInputSize()คืนค่า0เพื่อหมายถึงไม่จำกัด ให้ถือว่า0หมายถึง “ไม่มีขีดจำกัดจากนโยบาย” ไม่ใช่ “ปฏิเสธทั้งหมด” และควรกำหนดขีดจำกัดที่ชั้นการขนส่งด้วยเช่นกันExternalResourcePolicyInterfaceเป็นแบบปฏิเสธทั้งหมดโดยค่าเริ่มต้น การเปิดใช้งาน@font-faceหรือbackground-imageโดยไม่กำหนดรายการสคีมาจะเปิดพื้นผิวการปลอมแปลงคำขอ จึงควรกำหนดรายการที่อนุญาตไปพร้อมกัน- รายการโดเมนที่อนุญาตว่างเปล่าใน
getAllowedImageDomains()หมายความว่าทุกโดเมนได้รับอนุญาตเมื่อเปิดใช้งานภาพพื้นหลังแล้ว รายการว่างเปล่าไม่ใช่กฎการปฏิเสธ จึงต้องระบุโดเมนอย่างชัดเจน isSvgExternalReferenceAllowed()ควรคืนค่าfalseในระบบโปรดักชัน contract ระบุเรื่องนี้ไว้ในเอกสาร นโยบายที่คืนค่าtrueถือเป็นข้อค้นพบ ไม่ใช่ตัวเลือกสำหรับการกำหนดค่า
ประสิทธิภาพ
หัวข้อที่มีชื่อว่า “ประสิทธิภาพ”การตรวจสอบนโยบายเป็นการเรียก predicate แบบ O(1) โดยไม่มีต้นทุนที่แปรผันตามอินพุต ระบบจะตรวจสอบนโยบายระหว่างการแยกวิเคราะห์สำหรับแต่ละแท็ก แต่ละแอตทริบิวต์ แต่ละพร็อพเพอร์ตี้ CSS และแต่ละ URL เอกสารที่ผิดปกติจะทำให้จำนวนการเรียกเพิ่มทวีคูณ แต่การเรียกแต่ละครั้งยังคงใช้เวลาคงที่ performance_budget ที่ 1500 ms ของเวลานาฬิกาและ 64 MB ของจุดสูงสุดถูกครอบงำโดยการแยกวิเคราะห์และการเรนเดอร์ ไม่ใช่การประเมินนโยบาย ขีดจำกัดขนาดอินพุตและความลึกของการซ้อนเป็นตัวจำกัดต้นทุนของตัวแยกวิเคราะห์เอง นโยบายที่เข้มงวดช่วยปรับปรุงประสิทธิภาพในกรณีเลวร้ายที่สุดด้วยการปฏิเสธเอกสารที่มีขนาดใหญ่เกินไปหรือซ้อนลึกก่อนการจัดวาง
หมายเหตุด้านความปลอดภัย
หัวข้อที่มีชื่อว่า “หมายเหตุด้านความปลอดภัย”contract เหล่านี้ประกอบกันเป็นแนวป้องกันของเอนจิน ดังนั้นจึงระบุโมเดลภัยคุกคามไว้อย่างชัดเจน CryptoPolicyInterface ลดความเสี่ยงจากการลดระดับอัลกอริทึมด้วยการปิดกั้นแฮชที่อ่อนแอและคีย์ที่สั้นก่อนการดำเนินการใด ๆ HtmlSecurityPolicyInterface ลดความเสี่ยงจาก cross-site scripting ที่ส่งผลต่อเอาต์พุต Portable Document Format (PDF) และจากการแทรกเนื้อหา ด้วยการตัดแท็ก แอตทริบิวต์ และ CSS ที่ไม่ได้รับอนุญาตออกที่ชั้นการแยกวิเคราะห์ก่อนที่ตัวเรนเดอร์จะทำงาน ExternalResourcePolicyInterface ลดความเสี่ยงจากการปลอมแปลงคำขอฝั่งเซิร์ฟเวอร์ decompression bomb และ cumulative-size bomb ด้วยค่าเริ่มต้นแบบปฏิเสธทั้งหมด และจำกัดการดึงทุกครั้งตามสคีมา ขนาด ความลึก และโดเมน ขีดจำกัดขนาดอินพุต ความลึกของการซ้อน จำนวนกลิฟฟอนต์ และความลึกของการ import ช่วยลดความเสี่ยงจากการใช้ทรัพยากรจนหมด เนื่องจากแต่ละนโยบายเป็น contract คุณจึงสามารถเสริมความแข็งแกร่งให้แนวป้องกันได้โดยไม่ต้อง fork เอนจิน และระบบจะเปิดเผยชื่อนโยบายไว้สำหรับบันทึกการตรวจสอบ ให้ถือว่า HTML ทั้งหมด URL ทั้งหมด และไบต์ของฟอนต์กับรูปภาพทั้งหมดเป็นภัยคุกคาม หน้านี้ถูกทำเครื่องหมายเป็น export_control_class: legal-review-required เนื่องจาก contract เหล่านี้กำกับนโยบายการเข้ารหัสลับ เนื้อความสรุปแหล่งข้อมูลเชิงบรรทัดฐานทั้งหมดด้วยถ้อยคำของตนเองและไม่อ้างอิงข้อความใดโดยตรง
ความสอดคล้อง
หัวข้อที่มีชื่อว่า “ความสอดคล้อง”| ข้อกล่าวอ้าง | มาตรฐาน | ข้อกำหนด | หลักฐาน |
|---|---|---|---|
| การจัดการ URL ที่ไม่มีข้อจำกัดทำให้การเปลี่ยน URL ข้ามผ่านการควบคุมการเข้าถึงได้ นโยบายทรัพยากรภายนอกลดความเสี่ยงนี้ด้วยค่าเริ่มต้นแบบปฏิเสธทั้งหมดและรายการโดเมนที่อนุญาตแบบตรงทุกตัวอักษร | OWASP Top 10 2025 | A01 | |
| การจัดหาคอมโพเนนต์ภายนอกต้องจำกัดอยู่ที่แหล่งที่เป็นทางการและการขนส่งที่ปลอดภัย นโยบายรองรับข้อกำหนดนี้ผ่านรายการสคีมาที่อนุญาต | OWASP Top 10 2025 | ห่วงโซ่อุปทานซอฟต์แวร์ (Software supply chain) |
ทั้งสองประเด็นเป็นการสรุปแนวทางของ OWASP ด้วยถ้อยคำของตนเอง หน้านี้อ้างอิงเอกสารของ OWASP ตามข้อกำหนด โดยเอนจินไม่ได้ทำซ้ำข้อความดังกล่าว
บริบทเชิงพาณิชย์
หัวข้อที่มีชื่อว่า “บริบทเชิงพาณิชย์”Core กำหนดและตรึง contract นโยบายทั้งสามรายการ Core มาพร้อมค่าเริ่มต้นแบบอนุญาตกว้างสำหรับการพัฒนา และค่าเริ่มต้นแบบเข้มงวดสำหรับนโยบายทรัพยากรแบบปฏิเสธทั้งหมด รุ่น Enterprise มาพร้อมโปรไฟล์ FIPS 140-3 ที่อยู่เบื้องหลัง CryptoPolicyInterface ดังนั้นการ deploy ที่อยู่ภายใต้การกำกับดูแลจึงได้ท่าทีด้านอัลกอริทึมที่ผ่านการตรวจสอบแล้ว โดยไม่ต้องเปลี่ยนโค้ดสำหรับการลงนามหรือการเข้ารหัสลับ ขอบเขตของ contract เหมือนกันในทุกรุ่น ความแตกต่างอยู่ที่การนำนโยบายไปใช้งานที่คุณ inject เข้าไป
ดูเพิ่มเติม
หัวข้อที่มีชื่อว่า “ดูเพิ่มเติม”- Contracts: อินเทอร์เฟซสาธารณะ 41 รายการ (service provider interface, SPI) — ภาพรวมและระดับความเสถียร
- Contracts / Signing —
CryptoPolicyInterfaceที่นำไปใช้กับการลงนาม - Contracts / Document — จุดเข้า
writeHtml()และimage()ที่นโยบายเหล่านี้ควบคุม - Security — ขอบเขตการเข้ารหัสลับที่นโยบายการเข้ารหัสลับจำกัดไว้
- HTML — ไปป์ไลน์การแยกวิเคราะห์ที่นโยบาย HTML และนโยบายทรัพยากรปกป้องไว้
- Audit — การบันทึกการตรวจสอบชื่อนโยบาย