Skip to content

[Bug]+security: drop shell=True from subprocess calls #1339

@reddraconi

Description

@reddraconi

Checklist

  • I am using an up-to-date version.
  • I have read the documentation.
  • I have searched existing issues.

TagStudio Version

9.5.6

Operating System & Version

Fedora 43 x86_64

Description

I've gotten some time back from work and wanted to finish up the features I started back around December. As I did, I ran some security checks and found that, on the Windows path, the shell=True can lead to process injections when the command string is being built and sent to cmd.exe. One the POSIX path, it looks like we're vulnerable to backtick substitution.

Since Windows has weird rules about valid characters in file and path names (&, ^, %) that get interpreted by cmd.exe, this can lead to command injections when TagStudio opens a mal-named file, path, library, or when ripgrep is called during a library scan.

To fix this up, I updated the subprocess commands to use lists of arguments and removed shell=True. I didn't touch anything for regular file names, just stuff that was being passed to the shell.

Demo attached.

Expected Behavior

Don't have command injection issues due to malformed/malicious file paths or file names.

Steps to Reproduce

Pre fix:
Windows:

  1. In Settings, enable the "use Windows start command" toggle
  2. Create a folder name containing &:
    C:\Users\<you>\Pictures\album & calc & test.
  3. Add an image to the folder and import it into a TagStudio library.
  4. Click the file's "Open" action.
  5. Calc.exe should open

Linux:

  1. Create a library directory containing a $(…) command substitution:
    mkdir -p '/tmp/My$(gnome-calculator)Library/.TagStudio'.
  2. Open that directory as a TagStudio library and trigger a refresh
  3. gnome-calc should open

Post-fix:
Both of these should fail since the paths are now lists of strings rather than direct commands.

Logs

I wrote this up on my Linux box, since my Windows machine died (again).

I ensured:

  • TagStudio still opened files scans libraries, opens files in my file manager, and refreshes my library via ripgrep
  • The existing test suite passed everything that was already passing
  • ruff and mypy came back clean.

I have a PR coming for this now.

exploit_demo.py

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type: BugSomething isn't working as intended

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions