資安雷達 2026 年 10 月 8 日

2026-10-08 — Docling 的 Tectonic TikZ 渲染可任意讀寫檔案

primary=https://github.com/advisories/GHSA-x3q2-h9hx-4r4j primary=https://github.com/docling-project/docling/pull/4419 primary=https://github.com/docling-project/docling/releases/tag/v2.132.0

Docling 的 Tectonic TikZ 渲染可任意讀寫檔案

GitHub Advisory Database · 2026-10-07

Docling 的 LaTeX 後端只要改用 Tectonic 引擎渲染 TikZ 圖,惡意 .tex 就能讓處理程序讀走任何它讀得到的檔案,並在任何它寫得進去的路徑建立或覆寫檔案。這個問題登記為 CVE-2026-105744(GHSA-x3q2-h9hx-4r4j),嚴重度 high,CVSS v3 分數 7.5,在 docling 與 docling-slim 的 2.132.0 修補。

如果同時開了 shell escape,文件還能透過 \write18 直接執行指令。

漏洞機制

Docling 轉換 LaTeX 時,可以把文件裡的 TikZ 圖交給外部編譯器畫成圖片。docling/backend/latex/engines/tectonic.py 的做法是把圖的原始碼寫進暫存文件,再對它執行 tectonic 執行檔。其中的 _resolve_local_dependency 只決定哪些檔案要複製進暫存目錄,並不限制 TeX 編譯時實際會開啟什麼。

於是 TeX 本身的檔案原語全部可用:

  • \input{/abs/path}、\verbatiminput{...}、\openin 可讀任意檔案,內容還能被排進圖裡,最後出現在轉換輸出中。
  • \immediate\openout 與 \write 可在暫存目錄之外建立或覆寫檔案,而且不需要 shell escape。
  • 輸入若是記憶體內的 DocumentStream,連暫存檔的 staging 步驟都會整個略過。

advisory 特別指出,Tectonic 的 --untrusted 旗標擋不住上述寫檔行為。所以「我有用 untrusted 模式」不能當成防護。

另有一個獨立的問題:TectonicEngine 建構子的 allow_shell_escape 預設是 True。Docling 的 LaTeX 後端一律明確傳入 tikz_engine_allow_shell_escape(預設 False),所以這個預設值只影響直接實例化 TectonicEngine 的程式。

受影響版本與條件

版本範圍是 >= 2.94.0, < 2.132.0,docling 與 docling-slim 兩個 pip 套件都在內。但要中招必須同時滿足下列三項:

  • 呼叫端設定了 tikz_engine="tectonic"。
  • 環境中找得到 tectonic 執行檔(在 PATH 或 docling 快取裡)。
  • 轉換的是不受信任的 LaTeX。

預設設定(tikz_engine=None)不受影響。Docling 不會自動安裝 tectonic,CLI 也沒有開啟它的選項。所以真正需要檢查的是:把 Docling 包進文件解析服務、接受使用者上傳 .tex,且程式碼裡自己開了 Tectonic 的人,例如 RAG 攝取管線與論文轉 Markdown 的服務。

advisory 給的 PoC 只有幾行,用 \openout 在 TikZ 圖裡寫檔:

\begin{tikzpicture}
  \immediate\openout15=/tmp/docling-tectonic-poc.txt
  \immediate\write15{written by the input document}
  \immediate\closeout15
  \node {x};
\end{tikzpicture}

以 LatexBackendOptions(tikz_engine="tectonic") 轉換這份文件,就會在 /tmp/docling-tectonic-poc.txt 產生檔案。advisory 也提醒,寫入啟動檔或設定檔可進一步導致程式碼執行,所以歸類在 RCE 風險之下並不誇張。

修補與緩解

修補由 PR #4419 帶入,包含在 v2.132.0,做了兩件事:

項目2.132.0 之前2.132.0
TectonicEngine 的 allow_shell_escape 預設TrueFalse
未開 shell escape 時的 Tectonic 參數無額外限制--untrusted 與 --only-cached
編譯前檢查無掃描產生的文件與每個 staged 檔案

新增的檢查會在原始碼用到 \openin、\openout、\XeTeXpicfile、\XeTeXpdffile,或在 \input、\include、\includegraphics、\InputIfFileExists、\graphicspath 中使用絕對路徑、家目錄、磁碟代號或上層目錄時,跳過渲染並把圖保留為 TikZ 原始碼。

這個檢查只是 best-effort。它讀的是原始碼文字,而 TeX 可以透過套件指令或巨集拼出來的檔名開檔,文字比對看不到。advisory 因此仍然要求:以 tikz_engine="tectonic" 渲染不受信任的 LaTeX 時,必須放進隔離環境。

無法立刻升級的人,advisory 列出的 workaround 是:

  • 不要對不受信任的輸入啟用 tikz_engine="tectonic",或改在 OS 層沙箱中轉換:容器、不掛載主機目錄、唯讀檔案系統、無網路。
  • 對不受信任的輸入,絕不設定 tikz_engine_allow_shell_escape=True。

實務上先用 pip show docling 確認版本是否落在範圍內,再在程式碼裡搜尋 tikz_engine。沒有出現就不受影響。有出現的話,升級到 2.132.0,並確認轉換行程以最小權限執行,因為這類洩漏與覆寫的上限,就是該行程本身的檔案權限。

CWE 分類:CWE-22、CWE-73、CWE-1188(不安全的資源初始預設值)。commit 見 38b6fa0。

原始來源:GHSA-x3q2-h9hx-4r4j、docling PR #4419、docling v2.132.0


End of article
0
Would love your thoughts, please comment.x
()
x