[LyX/master] Hardening case 00e - arbitrary command execution via index_command

Pavel Sanda <[email protected]>
Newsgroups gmane.editors.lyx.cvs
Message-ID <[email protected]>
commit b2f155029f59f655d6ba63621840abc6a51924b6
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 03172ac2ae..6b352553da 100644
--- a/src/Converter.cpp
+++ b/src/Converter.cpp
@@ -498,8 +498,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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.