Skip to content

Path traversal: playlist names containing '/' create unintended subdirectories #3

Description

@berettavexee

Description

Playlist names containing a forward slash (/) are passed to clean_filepath() without prior slash substitution, causing the OS to interpret them as path separators. This creates unintended subdirectories and, with a crafted name, could write files outside the intended download folder (path traversal).

Root cause

streamrip/filepath_utils.py defines two functions:

  • clean_filename(fn) — replaces / with - before sanitizing. Used for track filenames and album/artist components in format_folder_path.
  • clean_filepath(fn) — calls sanitize_filepath() which preserves / as a legitimate path separator. Used directly for playlist folder names.

In streamrip/media/playlist.py:

# line 176 — Deezer/Qobuz/Tidal playlists
folder = os.path.join(parent, clean_filepath(name))

# line 248 — last.fm playlists
folder = os.path.join(parent, clean_filepath(playlist_title))

Neither call goes through clean_filename first, so a playlist named Best of 80s/90s creates:

~/StreamripDownloads/Best of 80s/
└── 90s/
    └── track.flac

A crafted name like ../../sensitive_dir could escape the download root entirely.

Albums are not affected

AlbumMetadata.format_folder_path() (streamrip/metadata/album.py:71,76) passes albumartist and title through clean_filename() before the template is expanded, so slashes in album/artist names are already replaced with -.

Fix

Replace / with - (or U+2215) in the playlist name before passing it to clean_filepath, or use clean_filename for the single-component case:

# playlist.py line 176
folder = os.path.join(parent, clean_filepath(clean_filename(name)))

# playlist.py line 248
folder = os.path.join(parent, clean_filepath(clean_filename(playlist_title)))

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions