-
-
Notifications
You must be signed in to change notification settings - Fork 947
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
Make secure_filename()
escape reserved Windows filenames
#2422
Comments
secure_filename()
escape reserved filenames on Windows
secure_filename()
escape reserved filenames on Windowssecure_filename()
escape reserved Windows filenames
I was reading a bit about this, and it is actually possible to both create and delete such files on Windows by using proper escaping. Maybe just a documentation note would be enough? I don't expect many to deploy Falcon on a Windows server in production, but of course you never know. If we do decide to implement this check, we ought to restrict this behaviour to the Windows platform to make sure we avoid a breaking change elsewhere. See also: |
just documenting that special file names in windows are not handled is likely fine |
This is what is defined in the stdlib's (3.13) _reserved_chars = frozenset(
{chr(i) for i in range(32)} |
{'"', '*', ':', '<', '>', '?', '|', '/', '\\'}
)
_reserved_names = frozenset(
{'CON', 'PRN', 'AUX', 'NUL', 'CONIN$', 'CONOUT$'} |
{f'COM{c}' for c in '123456789\xb9\xb2\xb3'} |
{f'LPT{c}' for c in '123456789\xb9\xb2\xb3'}
)
def isreserved(path):
"""Return true if the pathname is reserved by the system."""
# Refer to "Naming Files, Paths, and Namespaces":
# https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
path = os.fsdecode(splitroot(path)[2]).replace(altsep, sep)
return any(_isreservedname(name) for name in reversed(path.split(sep)))
def _isreservedname(name):
"""Return true if the filename is reserved by the system."""
# Trailing dots and spaces are reserved.
if name[-1:] in ('.', ' '):
return name not in ('.', '..')
# Wildcards, separators, colon, and pipe (*?"<>/\:|) are reserved.
# ASCII control characters (0-31) are reserved.
# Colon is reserved for file streams (e.g. "name:stream[:type]").
if _reserved_chars.intersection(name):
return True
# DOS device names are reserved (e.g. "nul" or "nul .txt"). The rules
# are complex and vary across Windows versions. On the side of
# caution, return True for names that may not be reserved.
return name.partition('.')[0].rstrip(' ').upper() in _reserved_names Most of the things char-related are irrelevant as we already replace them (although probably check that trailing dot case), so we could just check for these reserved names if we detect the Windows platform. |
@CaselIT noticed that we didn't hold Windows hand regarding device file names, like
https://github.com/pallets/werkzeug/blob/7868bef5d978093a8baa0784464ebe5d775ae92a/src/werkzeug/utils.py#L229-L237
(Originally posted by @CaselIT in #2421 (comment).)
The text was updated successfully, but these errors were encountered: