Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

aura: Sanitize filenames in image IDs #4160

Merged
merged 2 commits into from
Nov 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion beetsplug/aura.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

from mimetypes import guess_type
import re
import os.path
from os.path import isfile, getsize

from beets.plugins import BeetsPlugin
Expand Down Expand Up @@ -595,6 +596,24 @@ def single_resource(self, artist_id):
return self.single_resource_document(artist_resource)


def safe_filename(fn):
"""Check whether a string is a simple (non-path) filename.

For example, `foo.txt` is safe because it is a "plain" filename. But
`foo/bar.txt` and `../foo.txt` and `.` are all non-safe because they
can traverse to other directories other than the current one.
"""
# Rule out any directories.
if os.path.basename(fn) != fn:
return False

# In single names, rule out Unix directory traversal names.
if fn in ('.', '..'):
return False

return True


class ImageDocument(AURADocument):
"""Class for building documents for /images/(id) endpoints."""

Expand All @@ -616,6 +635,8 @@ def get_image_path(image_id):
parent_type = id_split[0]
parent_id = id_split[1]
img_filename = "-".join(id_split[2:])
if not safe_filename(img_filename):
return None

# Get the path to the directory parent's images are in
if parent_type == "album":
Expand All @@ -631,7 +652,7 @@ def get_image_path(image_id):
# Images for other resource types are not supported
return None

img_path = dir_path + "/" + img_filename
img_path = os.path.join(dir_path, img_filename)
# Check the image actually exists
if isfile(img_path):
return img_path
Expand Down
5 changes: 5 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ Other new things:

* Permissions plugin now sets cover art permissions to the file permissions.

Fixes:

* :doc:`/plugins/aura`: Fix a potential security hole when serving image
files. :bug:`4160`

1.5.0 (August 19, 2021)
-----------------------

Expand Down