system: You are an expert security code reviewer. You will be shown a source code file along with a multi-select question listing several CWE (Common Weakness Enumeration) categories. Your task is to identify which of the listed CWEs are present in the code.

OUTPUT FORMAT: Respond with the letter(s) of all correct options, sorted alphabetically and comma-separated, wrapped in a single \boxed{...}. Examples: `\boxed{A}` for one correct, `\boxed{A,C}` for two, `\boxed{A,C,E}` for three. Output the boxed answer ONLY -- no explanation, no other text.

user: ```python
"""
Module for creating Song objects by interacting with Spotify API
or by parsing a query.

To use this module you must first initialize the SpotifyClient.
"""

import json
import concurrent.futures

from typing import List, Optional

from spotdl.types import Playlist, Album, Artist, Saved
from spotdl.types.song import SongList, Song


class QueryError(Exception):
    """
    Base class for all exceptions related to query.
    """


def get_search_results(search_term: str) -> List[Song]:
    """
    Creates a list of Song objects from a search term.

    ### Arguments
    - search_term: the search term to use

    ### Returns
    - a list of Song objects
    """

    return Song.list_from_search_term(search_term)


def parse_query(
    query: List[str],
    threads: int = 1,
) -> List[Song]:
    """
    Parse query and return list containing song object

    ### Arguments
    - query: List of strings containing query
    - threads: Number of threads to use

    ### Returns
    - List of song objects
    """

    songs: List[Song] = get_simple_songs(query)

    results = []
    with concurrent.futures.ThreadPoolExecutor(max_workers=threads) as executor:
        for song in executor.map(reinit_song, songs):
            results.append(song)

    return results


def create_empty_song(
    name: Optional[str] = None,
    artists: Optional[List[str]] = None,
    album_name: Optional[str] = None,
    album_artist: Optional[str] = None,
    genres: Optional[List[str]] = None,
    disc_number: Optional[int] = None,
    disc_count: Optional[int] = None,
    duration: Optional[int] = None,
    year: Optional[int] = None,
    date: Optional[str] = None,
    track_number: Optional[int] = None,
    tracks_count: Optional[int] = None,
    isrc: Optional[str] = None,
    song_id: Optional[str] = None,
    cover_url: Optional[str] = None,
    explicit: Optional[bool] = None,
    publisher: Optional[str] = None,
    url: Optional[str] = None,
    copyright_text: Optional[str] = None,
    download_url: Optional[str] = None,
    song_list: Optional["SongList"] = None,
) -> Song:
    """
    Create an empty song.

    ### Arguments
    - name: Name of the song
    - artists: List of artists
    - album_name: Name of the album
    - album_artist: Name of the album artist
    - genres: List of genres
    - disc_number: Disc number
    - disc_count: Disc count
    - duration: Duration of the song in seconds
    - year: Year of release
    - date: Date of release
    - track_number: Track number
    - tracks_count: Number of tracks
    - isrc: ISRC code
    - song_id: Spotify song ID
    - cover_url: URL of the cover art
    - explicit: Explicit flag
    - publisher: Publisher
    - url: URL of the song
    - copyright_text: Copyright text
    - download_url: Download URL
    - song_list: Song list

    ### Returns
    - Song object
    """

    return Song(
        name=name,  # type: ignore
        artists=artists,  # type: ignore
        artist=None if artists is None else artists[0],  # type: ignore
        album_name=album_name,  # type: ignore
        album_artist=album_artist,  # type: ignore
        genres=genres,  # type: ignore
        disc_number=disc_number,  # type: ignore
        disc_count=disc_count,  # type: ignore
        duration=duration,  # type: ignore
        year=year,  # type: ignore
        date=date,  # type: ignore
        track_number=track_number,  # type: ignore
        tracks_count=tracks_count,  # type: ignore
        isrc=isrc,  # type: ignore
        song_id=song_id,  # type: ignore
        cover_url=cover_url,  # type: ignore
        explicit=explicit,  # type: ignore
        publisher=publisher,  # type: ignore
        url=url,  # type: ignore
        copyright_text=copyright_text,
        download_url=download_url,
        song_list=song_list,
    )


def get_simple_songs(
    query: List[str],
) -> List[Song]:
    """
    Parse query and return list containing simple song objects

    ### Arguments
    - query: List of strings containing query

    ### Returns
    - List of simple song objects
    """

    songs: List[Song] = []
    lists: List[SongList] = []
    for request in query:
        if (
            "youtube.com/watch?v=" in request
            or "youtu.be/" in request
            and "open.spotify.com" in request
            and "track" in request
            and "|" in request
        ):
            split_urls = request.split("|")
            if (
                len(split_urls) <= 1
                or "youtube" not in split_urls[0]
                and "youtu.be" not in split_urls[0]
                or "spotify" not in split_urls[1]
            ):
                raise QueryError(
                    'Incorrect format used, please use "YouTubeURL|SpotifyURL"'
                )

            songs.append(
                create_empty_song(url=split_urls[1], download_url=split_urls[0])
            )
        elif "open.spotify.com" in request and "track" in request:
            songs.append(create_empty_song(url=request))  # type: ignore
        elif "open.spotify.com" in request and "playlist" in request:
            lists.append(Playlist.create_basic_list(request))
        elif "open.spotify.com" in request and "album" in request:
            lists.append(Album.create_basic_list(request))
        elif "open.spotify.com" in request and "artist" in request:
            lists.append(Artist.create_basic_list(request))
        elif "album:" in request:
            lists.append(Album.from_search_term(request))
        elif request == "saved":
            lists.append(Saved.create_basic_list())
        elif request.endswith(".spotdl"):
            with open(request, "r", encoding="utf-8") as save_file:
                for track in json.load(save_file):
                    # Append to songs
                    songs.append(Song.from_dict(track))
        else:
            songs.append(Song.from_search_term(request))

    for song_list in lists:
        songs.extend(
            [create_empty_song(url=url, song_list=song_list) for url in song_list.urls]
        )  # type: ignore

    return songs


def reinit_song(song: Song, playlist_numbering: bool = False) -> Song:
    """
    Update song object with new data
    from Spotify

    ### Arguments
    - song: Song object
    - playlist_numbering: bool, default value is False

    ### Returns
    - Updated song object
    """

    data = song.json
    new_data = Song.from_url(data["url"]).json
    data.update((k, v) for k, v in new_data.items() if v is not None)

    if data.get("song_list"):
        # Reinitialize the correct song list object
        if song.song_list:
            song_list = song.song_list.__class__(**data["song_list"])
            data["song_list"] = song_list
            data["list_position"] = song_list.urls.index(song.url)
            if playlist_numbering:
                data["track_number"] = data["list_position"] + 1
                data["tracks_count"] = len(song_list.urls)
                data["album_name"] = song_list.name
                if isinstance(song_list, Playlist):
                    data["album_artist"] = song_list.author_name
                    data["cover_url"] = song_list.cover_url
                data["disc_number"] = 1
                data["disc_count"] = 1

    # return reinitialized song object
    return Song(**data)

```

Which of the following CWE vulnerability categories are present in this code? Multiple options may be correct.

  A) CWE-601: URL Redirection to Untrusted Site ('Open Redirect')
  B) CWE-1004: Sensitive Cookie Without 'HttpOnly' Flag
  C) CWE-215: Insertion of Sensitive Information Into Debugging Code
  D) CWE-94: Improper Control of Generation of Code ('Code Injection')
  E) CWE-20: Improper Input Validation
  F) CWE-312: Cleartext Storage of Sensitive Information
Answer: E