Summary
The profile name is used directly in file path construction and OS autorun entries without sanitization, enabling path traversal and potential command injection.
Details
Path traversal in profile paths (src/persistence/profile.cpp)
The profile name is concatenated directly into file paths at multiple locations:
// Line 314
const QString path = paths.getSettingsDirPath() + name + ".tox";
// Line 898-899
const QString path = paths.getSettingsDirPath() + name;
const QString newPath = paths.getSettingsDirPath() + newName;
A profile name containing ../../../ could write files outside the settings directory. Profile names can originate from imported .tox files where the filename becomes the name (src/widget/tool/profileimporter.cpp:83).
Command injection in autorun - XDG (src/platform/autorun_xdg.cpp:28-29,44-61)
QString getAutostartFilePath(const Settings& settings, QString dir)
{
return dir + "/qTox - " + settings.getCurrentProfile() + ".desktop";
}
The profile name appears unescaped in both the .desktop filename and the Exec= line. A profile name containing newlines could inject arbitrary desktop file keys.
Command injection in autorun - Windows (src/platform/autorun_win.cpp:41-45)
"\"" + QApplication::applicationFilePath().replace('/', '\\')
+ "\" -p \"" + settings.getCurrentProfile() + "\""
A profile name containing " breaks out of the quoting in the registry Run key value.
Suggested Fix
Add a profile name validation function and use it at all entry points:
// In profile.h/cpp
static bool isValidProfileName(const QString& name) {
// Allow only safe characters
static const QRegularExpression valid(QStringLiteral("^[\\w\\- ]+$"));
if (!valid.match(name).hasMatch()) return false;
if (name.contains("..")) return false;
if (name.trimmed().isEmpty()) return false;
// Reject Windows reserved device names
static const QSet<QString> reserved = {
"CON", "PRN", "AUX", "NUL",
"COM1","COM2","COM3","COM4","COM5","COM6","COM7","COM8","COM9",
"LPT1","LPT2","LPT3","LPT4","LPT5","LPT6","LPT7","LPT8","LPT9"
};
return !reserved.contains(name.toUpper());
}
Apply this validation in:
Profile::createProfile()
Profile::renameProfile()
ProfileImporter::importProfile()
- Login screen profile name input
For autorun entries, additionally escape the profile name for the target format (desktop file spec / Windows command line).
Impact
A crafted .tox import file could write files outside the profile directory. If autorun is enabled, the profile name can inject commands that execute on login.
Summary
The profile name is used directly in file path construction and OS autorun entries without sanitization, enabling path traversal and potential command injection.
Details
Path traversal in profile paths (
src/persistence/profile.cpp)The profile name is concatenated directly into file paths at multiple locations:
A profile name containing
../../../could write files outside the settings directory. Profile names can originate from imported.toxfiles where the filename becomes the name (src/widget/tool/profileimporter.cpp:83).Command injection in autorun - XDG (
src/platform/autorun_xdg.cpp:28-29,44-61)The profile name appears unescaped in both the
.desktopfilename and theExec=line. A profile name containing newlines could inject arbitrary desktop file keys.Command injection in autorun - Windows (
src/platform/autorun_win.cpp:41-45)A profile name containing
"breaks out of the quoting in the registry Run key value.Suggested Fix
Add a profile name validation function and use it at all entry points:
Apply this validation in:
Profile::createProfile()Profile::renameProfile()ProfileImporter::importProfile()For autorun entries, additionally escape the profile name for the target format (desktop file spec / Windows command line).
Impact
A crafted
.toximport file could write files outside the profile directory. If autorun is enabled, the profile name can inject commands that execute on login.