From 6ae424b11419ec491cd70394da0b2032d01ffef2 Mon Sep 17 00:00:00 2001 From: berettavexee Date: Sat, 20 Jun 2026 01:10:15 +0200 Subject: [PATCH] fix(playlist): sanitize playlist names to prevent path traversal via '/' Playlist names containing '/' were passed directly to clean_filepath(), which preserves slashes as path separators, creating unintended subdirectories. Apply clean_filename() first to replace '/' with '-'. Affects PendingPlaylist.resolve() and PendingLastfmPlaylist.resolve(). Albums were already safe: format_folder_path() passes albumartist and title through clean_filename() before template expansion. Co-Authored-By: Claude Sonnet 4.6 --- streamrip/media/playlist.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/streamrip/media/playlist.py b/streamrip/media/playlist.py index 383f2465..597d5255 100644 --- a/streamrip/media/playlist.py +++ b/streamrip/media/playlist.py @@ -16,7 +16,7 @@ from ..console import console from ..db import Database from ..exceptions import NonStreamableError -from ..filepath_utils import clean_filepath +from ..filepath_utils import clean_filename, clean_filepath from ..metadata import ( AlbumMetadata, Covers, @@ -171,7 +171,7 @@ async def resolve(self) -> Playlist | None: return None name = meta.name parent = self.config.session.downloads.folder - folder = os.path.join(parent, clean_filepath(name)) + folder = os.path.join(parent, clean_filepath(clean_filename(name))) tracks = [ PendingPlaylistTrack( id, @@ -243,7 +243,7 @@ def callback(): results: list[tuple[str | None, bool]] = await asyncio.gather(*requests) parent = self.config.session.downloads.folder - folder = os.path.join(parent, clean_filepath(playlist_title)) + folder = os.path.join(parent, clean_filepath(clean_filename(playlist_title))) pending_tracks = [] for pos, (id, from_fallback) in enumerate(results, start=1):