commit 476bf4dbb20c2669a683d162d377042e47358f6d
Author: Pavel Sanda <[email protected]>
Date:   Thu Jul 16 19:06:25 2026 +0200

    Hardening case 00e - arbitrary command execution via index_command
    
    A document-set \index_command was copied verbatim into the index-processor
    call on export, giving program substitution and <> redirection (file 
overwrite,
    same primitive as 00k), and/or code injection via metachars on windows.
    
    Fires on export.
    
    Tier 00 hotfix: accept only known index cmd, reject <> (+metas on win)
    Tier 01 DiD will land in master (canonical split, shared with 00d).
    
    Assisted-by: Claude Opus 4.8
---
 src/Converter.cpp | 35 +++++++++++++++++++++++++++++++++--
 1 file changed, 33 insertions(+), 2 deletions(-)

diff --git a/src/Converter.cpp b/src/Converter.cpp
index a162129f92..7aa5c00b3e 100644
--- a/src/Converter.cpp
+++ b/src/Converter.cpp
@@ -497,8 +497,39 @@ Converters::RetVal Converters::convert(Buffer const * 
buffer,
                        && bp.encoding().package() == Encoding::japanese;
                runparams.use_indices = bp.use_indices;
                runparams.bibtex_command = bp.bibtexCommand(true);
-               runparams.index_command = (bp.index_command == "default") ?
-                       string() : bp.index_command;
+
+               // Accept only programs from fixed known list
+               string accepted_index_cmd;
+               if (bp.index_command != "default" && !bp.index_command.empty()) 
{
+
+                       // Block redirection (+ metas on Windows where it sinks 
to shell)
+#if defined(_WIN32)
+                       static char const * const SUSPECT_CHARS = "<>" 
"&|()^%;";
+#else
+                       static char const * const SUSPECT_CHARS = "<>";
+#endif
+                       bool const has_suspect =
+                               bp.index_command.find_first_of(SUSPECT_CHARS) 
!= string::npos;
+                       if (!has_suspect) {
+                               string supplied_prog;
+                               split(bp.index_command, supplied_prog, ' ');
+                               for (auto const & alt : 
lyxrc.index_alternatives) {
+                                       string alt_prog;
+                                       split(alt, alt_prog, ' ');
+                                       if (!supplied_prog.empty()
+                                           && supplied_prog == alt_prog) {
+                                               accepted_index_cmd = 
bp.index_command;
+                                               break;
+                                       }
+                               }
+                       }
+                       if (accepted_index_cmd.empty())
+                               LYXERR0("Document-supplied index command '"
+                                       << bp.index_command << "' is not a 
recognised "
+                                       "index processor; falling back to 
default.");
+               }
+
+               runparams.index_command = accepted_index_cmd;
                runparams.document_language = bp.language->lang();
                // Some macros rely on font encoding
                runparams.main_fontenc = bp.main_font_encoding();
-- 
lyx-cvs mailing list
[email protected]
https://lists.lyx.org/mailman/listinfo/lyx-cvs

Reply via email to