>From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Pavel Sanda Date: Thu, 4 Jun 2026 13:20:02 +0200 Subject: [PATCH] Hardening case 00b - arbitrary command execution via lyx2lyx invocation convertLyXFormat() builds the lyx2lyx command as a shell string and passes the filenames through quoteName(), which leaves active characters alive. Crafted filename on an old-format .lyx injects arbitrary commands. Fires on .lyx load (old-format file needing conversion). Tier 00 hotfix: single-quote the filename args on POSIX, keep quoteName on Windows. Tier 01 DiD will land in master (argv-form lyx2lyx). Assisted-by: Claude Opus 4.7 --- src/Buffer.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Buffer.cpp b/src/Buffer.cpp index 5471f89cfa..4466b5d131 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -1402,12 +1402,22 @@ Buffer::ReadStatus Buffer::convertLyXFormat(FileName const & fn, // Run lyx2lyx: // $python$ "$lyx2lyx$" -t $LYX_FORMAT$ -o "$tempfile$" "$filetoread$" + + // guard against command expansion in filename strings on linux, + // keep " on windows + auto sh_quote = [](string const & s) -> string { +#ifdef _WIN32 + return quoteName(s); +#else + return '\'' + subst(s, "'", "'\\''") + '\''; +#endif + }; ostringstream command; command << os::python() - << ' ' << quoteName(lyx2lyx.toFilesystemEncoding()) + << ' ' << sh_quote(lyx2lyx.toFilesystemEncoding()) << " -t " << convert(LYX_FORMAT) - << " -o " << quoteName(tmpfile.toSafeFilesystemEncoding()) - << ' ' << quoteName(fn.toSafeFilesystemEncoding()); + << " -o " << sh_quote(tmpfile.toSafeFilesystemEncoding()) + << ' ' << sh_quote(fn.toSafeFilesystemEncoding()); string const command_str = command.str(); LYXERR(Debug::INFO, "Running '" << command_str << '\'');