>From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Pavel Sanda Date: Thu, 11 Jun 2026 02:37:55 +0200 Subject: [PATCH] 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 e0dc4e7654..abb4d05840 100644 --- a/src/support/filetools.cpp +++ b/src/support/filetools.cpp @@ -1363,9 +1363,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;