Skip to content

Profile name not sanitized in file paths and autorun entries #715

@grisutheguru

Description

@grisutheguru

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions