跳到內容

NextPDF Laravel 套件的安全性與維運

本套件會套用固定的回應標頭集、清理下載檔名、在 worker 端驗證佇列輸出路徑,並透過具備請求偽造防護的用戶端,包裝連往時間戳記憑證機構的 HTTP 連線。本頁說明威脅模型,以及各項控制措施所需的部署設定。

Terminal window
composer require nextpdf/laravel
php artisan vendor:publish --tag=nextpdf-config

本套件會將 PDF 引擎接入 Web Framework(框架)。信任邊界是 HTTP 請求與佇列傳輸。以下控制措施涵蓋回應處理、反序列化後的 job 負載,以及對外連往時間戳記憑證機構的 HTTP 連線。

資產威脅本套件中的控制措施所需的部署設定
PDF HTTP 回應內容類型嗅探、點擊劫持、被搜尋引擎建立 Index(索引)每個 PdfResponse 工廠都會設定固定的標頭集無;標頭不可設定
下載檔名標頭注入、Content-Disposition 中的路徑遍歷檔名清理器會移除分隔字元、控制字元與 null 位元組無;清理器一律會執行
佇列 job 輸出路徑透過竄改後的序列化負載寫入任意檔案在 worker 上的 handle() 中驗證路徑把輸出導向受控制的儲存路徑
對外的 TSA HTTP 連線伺服器端請求偽造、明文竄改具備請求偽造防護的 HTTP 用戶端;除非明確放寬,否則強制使用 HTTPS保持 tsa.allow_insecure_http = false;釘選 SPKI
共用的 worker 狀態長存 worker 中的跨請求狀態外洩鎖定的字型登錄;有界限的影像快取;綁定至工廠的 document設定 preload_fonts;在容器層設定記憶體上限

每個 PdfResponse 工廠都會設定一組固定的標頭集:

  • Cache-Control: private, max-age=0, must-revalidate
  • Pragma: public
  • X-Content-Type-Options: nosniff
  • X-Frame-Options: DENY
  • Content-Security-Policy: default-src 'none'
  • X-Robots-Tag: noindex, nofollow
  • Referrer-Policy: no-referrer

這些值是 PdfResponse 中的常數,且不可設定。本套件的測試套件會針對每個工廠方法斷言所有標頭,包含串流變體。

下載檔名寫入 Content-Disposition 標頭前,會先經過清理器。清理器會移除路徑分隔字元、控制字元與 null 位元組,並針對非 ASCII 名稱輸出一個 RFC 5987 filename*= 參數。空白檔名會變成 document.pdf

GeneratePdfJob 會把一個閉包序列化到佇列傳輸上。輸出路徑是在 worker 端的 handle() 內驗證,而非在派送時。驗證會拒絕:

  • 路徑中的 null 位元組、
  • stream-wrapper 結構描述(例如 php://)、
  • .. 路徑遍歷片段、
  • 任何未以 .pdf 結尾的路徑(不分大小寫)。

每一次拒絕都會引發 InvalidArgumentException。驗證會在實際使用該值時執行。Redis 或資料庫傳輸中的序列化負載,可能在 worker 讀取前被竄改。請把輸出路徑導向受控制的儲存目錄;不要從未經驗證的請求輸入推導出該路徑。

對外連到時間戳記憑證機構的 HTTP 連線

標題為「對外連到時間戳記憑證機構的 HTTP 連線」的區段

設定時間戳記憑證機構時,本套件會綁定一個 PSR-18 Psr\Http\Client\ClientInterface。PSR-18 用戶端會送出 PSR-7 請求並回傳 PSR-7 回應(PSR-18 §2)。綁定的用戶端會以具備請求偽造防護的層,包裝以 curl 為基礎的用戶端;除非 tsa.allow_insecure_http 明確為 true,否則強制使用 HTTPS。

時間戳記憑證機構屬於 Premium 等級能力。本頁所記載的 Core 套件負責綁定 HTTP 用戶端與時間戳記用戶端的接線;簽章本身需要 nextpdf/premium。本頁不記載 PAdES 在 B-B 以外的基準行為;更高的基準不在範圍內。

時間戳記憑證機構的維運指引:

  1. 在正式環境中,讓 tsa.allow_insecure_http 維持為 false
  2. tsa.pinned_public_keys 設為時間戳記憑證機構憑證的 base64 SHA-256 SPKI 雜湊值(RFC 7469 形式)。
  3. tsa.warn_on_key_rotation 維持為 true,如此一來,在釘選憑證過期前,變更後的 SPKI 就會被記錄下來。
  4. 請僅從受信任的設定取得 tsa.url。若操作人員可以從管理介面設定它,請套用對外流量防火牆或 DNS 政策,以降低請求偽造的暴露面。

使用 Psr\Log\LoggerInterface 進行診斷。請傳入結構化的內容,而非經插值的字串。PSR-3 將 placeholder(佔位符)的逸出交由記錄器實作處理,並指示呼叫端不要預先逸出內容值(PSR-3 §1.2)。請記錄例外類別,而非訊息或追蹤,以減少記錄中暴露的內部細節。

resource: config/nextpdf.php (tsa hardening) + src/Laravel/NextPdfServiceProvider.php
<?php
declare(strict_types=1);
// .env — production timestamp-authority hardening
// NEXTPDF_TSA_URL=https://tsa.example.test
// NEXTPDF_TSA_ALLOW_INSECURE_HTTP=false
// NEXTPDF_TSA_WARN_ROTATION=true
return [
'tsa' => [
'url' => env('NEXTPDF_TSA_URL'),
'allow_insecure_http' => env('NEXTPDF_TSA_ALLOW_INSECURE_HTTP', false),
'warn_on_key_rotation' => env('NEXTPDF_TSA_WARN_ROTATION', true),
'pinned_public_keys' => [
// base64 SHA-256 SPKI hashes of the TSA certificate
],
],
];
  • 回應標頭集是固定的。需要不同 CSP 的應用程式,必須在工廠回傳回應後再進行後處理。
  • 路徑驗證會在 worker 端執行。有問題的路徑會通過 dispatch(),只有在 job 執行時才會失敗。
  • tsa.allow_insecure_http = true 會移除 HTTPS 強制要求,並削弱時間戳記的可信度。請把它限制在本機開發環境。
  • 字型登錄在暖機後會被鎖定;在長存 worker 中於執行期嘗試註冊字型的行為,依設計會被拒絕。

這些安全控制是常數時間的字串與陣列運算,不會增加可量測的單次請求成本。主要的維運成本來自首次使用時的字型剖析;請在 worker 啟動時預載字型,以避免首次請求延遲。

本頁是本套件的威脅模型參考文件。此處所述的控制措施都在原始碼中強制執行,並由測試套件加以斷言。操作人員必須提供的部署設定,已在威脅模型表格與時間戳記憑證機構的步驟中明確指出。

主張來源條款參考 ID
PSR-18 用戶端送出 PSR-7 請求,回傳 PSR-7 回應PSR-18 HTTP 用戶端§2
呼叫端傳入未逸出的結構化記錄內容PSR-3 記錄器§1.2

RFC 7469 SPKI 釘選是 tsa.pinned_public_keys 設定鍵所使用的形式;本套件會取用操作人員提供的釘選值,但本身並不實作該 RFC。

PAdES B-B 簽章與時間戳記憑證機構整合需要 nextpdf/premium。這是一項選用的 Enterprise 能力;採用它時,本頁所記載的 Core 套件不需要任何程式碼變更。請參見 https://nextpdf.dev/get-license/?intent=laravel-signing

  • /integrations/laravel/configuration/ — 每個 TSA、簽章與佇列設定鍵
  • /integrations/laravel/production-usage/ — DI 與錯誤處理模式
  • /integrations/laravel/troubleshooting/ — 為何路徑檢查會拒絕輸入
  • /integrations/laravel/boot-and-discovery/ — 長存 worker 中的綁定生命週期