Bỏ qua để đến nội dung

Contracts / Chính sách bảo mật

Miền security-policy định nghĩa ba contract mặc định theo hướng từ chối: CryptoPolicyInterface kiểm soát lựa chọn thuật toán và khóa, HtmlSecurityPolicyInterface ràng buộc bề mặt tính năng Hypertext Markup Language (HTML), và ExternalResourcePolicyInterface quản lý việc tải tài nguyên từ xa. Vì mỗi thành phần đều là một contract, bạn có thể cung cấp một triển khai chính sách nghiêm ngặt hơn mà không cần fork.

Terminal window
composer require nextpdf/core:^3

CryptoPolicyInterface là cổng kiểm soát mật mã. Core gọi nó trước mọi bước ký, mã hóa hoặc băm. Các kiểm tra bao gồm hàm băm, object identifier (OID) của chữ ký, thuật toán mã hóa và độ mạnh của khóa. Contract cũng báo cáo hàm băm tối thiểu và tên chính sách cho nhật ký kiểm toán. Hãy dùng nó để áp dụng một bộ quy tắc như Federal Information Processing Standards (FIPS) 140-3 hoặc eIDAS. Mã xử lý ký và mã hóa không thay đổi. Khi không thiết lập chính sách nào, mọi thuật toán đều được cho phép. Một hệ thống chịu quy định bắt buộc phải thiết lập một chính sách rõ ràng.

HtmlSecurityPolicyInterface hoạt động ở lớp phân tích cú pháp HTML. Nó chạy trước khi nội dung đến bất kỳ bộ kết xuất nào. Nó quyết định một thẻ, một thuộc tính, một thuộc tính Cascading Style Sheets (CSS) hay một scheme uniform resource locator (URL) có được cho phép hay không. Nó cũng giới hạn kích thước đầu vào và độ sâu lồng nhau. Nó phối hợp với các chính sách truyền tải theo từng bộ kết xuất (Chrome, Cloudflare, Gotenberg), vốn thiết lập giới hạn kích thước và các header Content Security Policy (CSP). Chính sách HTML làm giảm bề mặt tấn công ở lớp phân tích cú pháp. Một thẻ đã bị loại bỏ sẽ không bao giờ đến được bố cục. Một phần tử được tiêm vào không thể thay đổi kết quả đầu ra. Khi không thiết lập chính sách nào, mặc định sẽ cho phép toàn bộ tập tính năng.

ExternalResourcePolicyInterface quyết định liệu pipeline HTML có thể tải một phông chữ, stylesheet hay hình ảnh bên ngoài hay không. Nó cũng thiết lập giới hạn cho từng lần tải. Quan điểm mặc định của nó là từ chối tất cả. Mọi tùy chọn đều tắt cho đến khi bạn bật. Contract tuân theo nguyên tắc đặc quyền tối thiểu. HTML không đáng tin có thể trỏ tới một URL do kẻ tấn công kiểm soát. Nó kiểm soát các lần tải @font-face theo scheme, kích thước và số lượng glyph. Nó kiểm soát @import theo scheme, độ sâu và tổng kích thước. Nó kiểm soát background-image theo một danh sách scheme và allowlist tên miền khớp chính xác. Nó giới hạn kích thước data-URI (Uniform Resource Identifier). Nó cũng kiểm soát các tham chiếu Scalable Vector Graphics (SVG) bên ngoài. Contract nêu rõ rằng môi trường sản xuất phải luôn từ chối chúng. Chúng tạo điều kiện cho giả mạo yêu cầu và tiêm script. Việc tải URL mở là một đường dẫn tới giả mạo yêu cầu phía máy chủ. Kiểm soát truy cập có thể bị vượt qua bằng cách thay đổi URL, như được mô tả bởi Open Worldwide Application Security Project (OWASP) Top 10 2025. Việc lấy thành phần bên ngoài phải được giới hạn ở các nguồn chính thức và kênh truyền tải an toàn.

LoạiDạngThành viên chínhĐộ ổn địnhTừ phiên bản
CryptoPolicyInterfaceinterfaceisHashAlgorithmAllowed(), isSignatureAlgorithmAllowed(), isEncryptionAlgorithmAllowed(), isKeyStrengthAllowed(), getPreferredHashAlgorithm(), getName()ổn định1.9.0
HtmlSecurityPolicyInterfaceinterfaceisTagAllowed(), isAttributeAllowed(), isCssPropertyAllowed(), isUrlSchemeAllowed(), getMaxInputSize(), getMaxNestingDepth(), getName()ổn định3.1.0
ExternalResourcePolicyInterfaceinterfaceisFontFaceAllowed(), getAllowedFontSchemes(), getMaxFontFileSize(), getMaxFontGlyphs(), isImportAllowed(), getMaxImportDepth(), isBackgroundImageAllowed(), getAllowedImageDomains(), getMaxDataUrlSize(), isSvgExternalReferenceAllowed()ổn định4.0.0

ExternalResourcePolicyInterface trả về các giới hạn có kiểu: kích thước dạng positive-int, độ sâu import dạng int<1, 100>, và danh sách scheme cùng tên miền dạng list<non-empty-string>. Cài đặt mặc định từ chối mọi khả năng.

examples/contracts/security-policy-quickstart.php
<?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);
}

Hàm này chỉ phụ thuộc vào contract. Cả chính sách hạn chế lẫn chính sách mặc định đều thỏa mãn contract đó.

examples/contracts/security-policy-production.php
<?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.');
}
}
}

Cổng này thực thi giới hạn đầu vào và từ chối chính sách tài nguyên không an toàn trước khi pipeline chạy. Nó ghi lại tên chính sách để kiểm toán và ném ra một exception cụ thể.

  • CryptoPolicyInterface cho phép mọi thuật toán khi không thiết lập chính sách nào. Mặc định mở là tiện ích cho phát triển, không phải trạng thái dành cho môi trường sản xuất. Hãy thiết lập một chính sách rõ ràng trong mọi triển khai chịu quy định.
  • HtmlSecurityPolicyInterface::getMaxInputSize() trả về 0 nghĩa là không giới hạn. Hãy hiểu 0 là “không có giới hạn từ chính sách”, chứ không phải “từ chối tất cả”. Hãy áp dụng thêm giới hạn ở lớp truyền tải.
  • ExternalResourcePolicyInterface mặc định từ chối tất cả. Bật @font-face hoặc background-image mà không thiết lập danh sách scheme sẽ mở ra bề mặt giả mạo yêu cầu; hãy thiết lập allowlist cùng lúc.
  • Một allowlist tên miền rỗng trên getAllowedImageDomains() nghĩa là mọi tên miền đều được cho phép sau khi hình nền được bật. Danh sách rỗng không phải là quy tắc từ chối; hãy cung cấp các tên miền rõ ràng.
  • isSvgExternalReferenceAllowed() nên trả về false trong môi trường sản xuất. Contract ghi rõ điều này; chính sách trả về true là một phát hiện vấn đề, không phải lựa chọn cấu hình.

Một lần kiểm tra chính sách là một lời gọi predicate: O(1), không có chi phí tỷ lệ với đầu vào. Chính sách được tham vấn cho mỗi thẻ, mỗi thuộc tính, mỗi thuộc tính CSS và mỗi URL trong quá trình phân tích cú pháp. Một tài liệu bất thường sẽ làm tăng số lần gọi, nhưng mỗi lần gọi vẫn giữ thời gian hằng số. performance_budget ở mức 1500 ms thời gian thực và 64 MB đỉnh chủ yếu do phân tích cú pháp và kết xuất chi phối, không phải do việc đánh giá chính sách. Các giới hạn kích thước đầu vào và độ sâu lồng nhau ràng buộc chi phí của chính trình phân tích cú pháp. Một chính sách nghiêm ngặt cải thiện hiệu năng trong trường hợp xấu nhất bằng cách từ chối tài liệu quá lớn hoặc lồng nhau quá sâu trước khi dàn bố cục.

Các contract này tạo thành vành đai phòng thủ của engine, nên mô hình mối đe dọa được nêu rõ ràng. CryptoPolicyInterface giảm thiểu việc hạ cấp thuật toán bằng cách chặn các hàm băm yếu và khóa ngắn trước mọi thao tác. HtmlSecurityPolicyInterface giảm thiểu cross-site scripting ảnh hưởng đến kết quả đầu ra Portable Document Format (PDF) và việc tiêm nội dung bằng cách loại bỏ các thẻ, thuộc tính và CSS không được phép ở lớp phân tích cú pháp trước khi bộ kết xuất chạy. ExternalResourcePolicyInterface giảm thiểu giả mạo yêu cầu phía máy chủ, bom giải nén và bom tổng kích thước bằng cách mặc định từ chối tất cả và ràng buộc mọi lần tải theo scheme, kích thước, độ sâu và tên miền. Các giới hạn về kích thước đầu vào, độ sâu lồng nhau, glyph phông chữ và độ sâu import giúp giảm thiểu cạn kiệt tài nguyên. Vì mỗi chính sách đều là một contract, bạn có thể tăng cường vành đai mà không cần fork engine, và tên chính sách được phơi bày cho việc ghi nhật ký kiểm toán. Hãy coi tất cả HTML, tất cả URL, cũng như mọi byte phông chữ và hình ảnh là thù địch. Trang này được đánh dấu export_control_class: legal-review-required vì các contract chi phối chính sách mật mã; phần văn bản diễn giải lại mọi nguồn quy chuẩn và không trích dẫn nguyên văn nguồn nào.

Tuyên bốTiêu chuẩnĐiều khoảnBằng chứng
Việc xử lý URL không ràng buộc cho phép thay đổi URL để vượt qua kiểm soát truy cập; chính sách tài nguyên bên ngoài giảm thiểu rủi ro này bằng các mặc định từ chối tất cả và allowlist tên miền khớp chính xác.OWASP Top 10 2025A01
Việc lấy thành phần bên ngoài phải được giới hạn ở các nguồn chính thức và kênh truyền tải an toàn; chính sách hỗ trợ điều này thông qua các allowlist scheme.OWASP Top 10 2025Chuỗi cung ứng phần mềm

Cả hai điểm đều diễn giải lại hướng dẫn của OWASP. Trang này tham chiếu tài liệu OWASP theo điều khoản; engine không tái hiện nguyên văn nội dung đó.

Core định nghĩa và cố định ba contract chính sách. Nó cung cấp các mặc định dễ dãi cho phát triển và các mặc định nghiêm ngặt cho chính sách tài nguyên từ chối tất cả. Phiên bản Enterprise cung cấp một profile FIPS 140-3 đứng sau CryptoPolicyInterface, nhờ đó một triển khai chịu quy định có được trạng thái thuật toán đã được kiểm định mà không cần thay đổi mã ký hay mã hóa. Bề mặt contract giống hệt nhau trên mọi phiên bản. Điểm khác biệt nằm ở cài đặt chính sách mà bạn tiêm vào.