pallets / werkzeug

The comprehensive WSGI web application library.
https://werkzeug.palletsprojects.com
BSD 3-Clause "New" or "Revised" License
6.63k stars 1.73k forks source link

Confused about the security.safe_join function #2927

Closed masterbbud closed 1 month ago

masterbbud commented 1 month ago

I'm using werkzeug's utils.send_from_directory() function to send a file with a multilevel "path" value. For example, my call to send_from_directory() might look like:

send_from_directory("C:\directory", "subdir\file.html", environment)

In this case, send_from_directory returns a 404 NotFound, since the call to safe_join in line 564 returns None.

# utils.send_from_directory: 564
path_str = safe_join(os.fspath(directory), os.fspath(path))

The call to safe_join is rejected because the subpath contains a \ character, which is included in the list of _os_alt_seps (defined in security.py) to mark it as "insecure".

This seems incorrect. Why is the separator / manually ignored from the _os_alt_seps definition in line 13, but not \? It's important to note that I'm running on Windows, and \ is the default path separator. I believe that a single slash \ in the path to join in should not be considered an "unsafe" access - but correct me if this is an incorrect assumption.

davidism commented 1 month ago

The second path in send_from_directory would be a URL path, not an OS path. URL paths are separated by /.