[LyX/2.5.x] Hardening case 00de (xindex) - version check + --restricted jail
Richard Kimberly Heck <[email protected]>
| Newsgroups | gmane.editors.lyx.cvs |
|---|---|
| Message-ID | <[email protected]> |
commit 4d0551470c0e2671a1ccbadebc40beb940546979 Author: Pavel Sanda <[email protected]> Date: Wed Jul 8 12:26:10 2026 +0200 Hardening case 00de (xindex) - version check + --restricted jail Stacks on the processing gate 00de: adds xindex to the processor table. For >= 1.07 ungated + appends --restricted to the spawned command so a hostile document cannot shadow xindex's own config/modules in CWD. Assisted-by: Claude Opus 4.8 --- src/LaTeX.cpp | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/src/LaTeX.cpp b/src/LaTeX.cpp index 1e42ca2d18..5f709f74a0 100644 --- a/src/LaTeX.cpp +++ b/src/LaTeX.cpp @@ -613,6 +613,19 @@ int LaTeX::runMakeIndex(string const & f, OutputParams const & rp, && !checkProcessorAuth(doc_fname, tmp)) return Systemcall::KILLED; + // A --restricted-capable xindex (not gated, i.e. version >= the table + // threshold) is run with --restricted so a document cannot shadow + // xindex's own modules/configs from the current directory and get code + // executed. This also covers a document-supplied \index_command, which + // replaces the whole command string. Older xindex would reject the + // unknown flag, hence the !isProcessorGated guard (cached above). + { + string iprog; + split(tmp, iprog, ' '); + if (onlyFileName(iprog) == "xindex" && !isProcessorGated(tmp)) + tmp += " --restricted"; + } + Language const * doc_lang = languages.getLanguage(rp.document_language); if (contains(tmp, "$$x")) { @@ -844,6 +857,11 @@ RequiredProcessor const required_processors[] = { { "upmendex", true, nullptr, nullptr, 0, 0 }, // biber: code-capable; fixed upstream at 2.22 { "biber", false, "--version", "version:\\s*([0-9]+)\\.([0-9]+)", 2, 22 }, + // xindex: code-capable (texlua); the CWD-shadowing RCE is closed by + // running it with --restricted (see runMakeIndex). Versions that support + // that flag are not gated. PIN this threshold to the xindex release that + // actually ships --restricted before enabling (placeholder: 1.07). + { "xindex", false, "--version", "xindex version ([0-9]+)\\.([0-9]+)", 1, 7 }, }; // False only when >= required version. @@ -871,8 +889,21 @@ bool isProcessorGated(string const & command) break; } //safe because prog was matched against the table - cmd_ret const r = - runCommand(quoteName(prog) + ' ' + p.version_arg); + // Probe in a fresh empty directory, not the export dir: a + // texlua-based processor (xindex) executes CWD-first module loads + // before it prints its version, so probing where the document has + // written files would run planted code. createLyXTmpDir(FileName()) + // makes a unique dir under the system temp; on failure we leave the + // fail-safe gated=true. + cmd_ret r{}; + FileName const probe_dir = createLyXTmpDir(FileName()); + if (!probe_dir.empty()) { + FileName const saved = FileName::getcwd(); + probe_dir.chdir(); + r = runCommand(quoteName(prog) + ' ' + p.version_arg); + saved.chdir(); + probe_dir.destroyDirectory(); + } smatch m; regex const re(p.version_re); if (r.valid && regex_search(r.result, m, re)) { -- lyx-cvs mailing list [email protected] https://lists.lyx.org/mailman/listinfo/lyx-cvs