[LyX/2.5.x] Hardening case 00g - arbitrary command execution via mangled filename extension

Richard Kimberly Heck <[email protected]>
Newsgroups gmane.editors.lyx.cvs
Message-ID <[email protected]>
commit e309a049bb16a8d059f1cc3ee9f50bbdd428f2f0
Author: Pavel Sanda <[email protected]>
Date:   Thu Jun 11 02:37:55 2026 +0200

    Hardening case 00g - arbitrary command execution via mangled filename extension
    
    mangledFileName() sanitized the base of a copied file's name but re-attached
    its extension unsanitized; the mangled name reaches shell command lines in
    shipped conversion helpers on export, so a hostile graphics extension injects
    arbitrary commands.
    
    Fires on export.
    
    Tier 00 fix: sanitize the extension too in mangledFileName(), drop ;=
    
    Assisted-by: Claude Opus 4.7
---
 src/support/FileName.cpp  | 12 +++++++-----
 src/support/filetools.cpp |  3 ++-
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/src/support/FileName.cpp b/src/support/FileName.cpp
index e49f76e90c..2b8e0243f3 100644
--- a/src/support/FileName.cpp
+++ b/src/support/FileName.cpp
@@ -990,11 +990,11 @@ string DocFileName::mangledFileName(string const & dir, bool encrypt_path) const
 	// xHTML route
 	// we use hash instead of counter to get stable filenames in export directory
 	if (encrypt_path) {
-		// sanitization probably not neccessary for xhtml, but won't harm
 		string sanfn = support::changeExtension(onlyFileName(), string());
 		sanfn = sanitizeFileName(sanfn);
-		// Add the extension back on
-		sanfn = support::changeExtension(sanfn, getExtension(onlyFileName()));
+		// extension is user-controlled string, suppress metacharacters
+		sanfn = support::changeExtension(sanfn,
+				sanitizeFileName(getExtension(onlyFileName())));
 
 		//various filesystems have filename limit around 2^8
 		if (sanfn.length() > 230)
@@ -1014,8 +1014,10 @@ string DocFileName::mangledFileName(string const & dir, bool encrypt_path) const
 		mname = support::changeExtension(name, string());
 		// The mangled name must be a valid LaTeX name.
 		mname = sanitizeFileName(mname);
-		// Add the extension back on
-		mname = support::changeExtension(mname, getExtension(name));
+		// Add the extension back on, but sanitize from metachars,
+		// it's user-controlled string
+		mname = support::changeExtension(mname,
+				sanitizeFileName(getExtension(name)));
 
 		// Prepend a counter to the filename. This is necessary to make
 		// the mangled name unique, see truncation below.
diff --git a/src/support/filetools.cpp b/src/support/filetools.cpp
index 823ff78728..af24b90713 100644
--- a/src/support/filetools.cpp
+++ b/src/support/filetools.cpp
@@ -1378,9 +1378,10 @@ std::string sanitizeFileName(const std::string & str)
 	// are forbidden: '/', '.', ' ', and ':'.
 	// On windows it is not possible to create files with '<', '>' or '?'
 	// in the name.
+	// We forbid ';', '=' as they could become active in shell.
 	static std::string const keep = "abcdefghijklmnopqrstuvwxyz"
 	                           "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-	                           "+-0123456789;=";
+	                           "+-0123456789";
 
 	std::string name = str;
 	string::size_type pos = 0;
-- 
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.