Skip to content

Commit

Permalink
Fix Windows path traversal in autorefresh mode
Browse files Browse the repository at this point in the history
It should be reiterated that "autorefresh" mode is not intended for
production use and it's possible that other security issues could be
exposed, particularly on non-standard filesystems. Production mode,
where WhiteNoise scans all available files on startup, provides a much
smaller attack surface and is therefore much safer.

Closes #197
  • Loading branch information
evansd committed Dec 24, 2018
1 parent 8a374b4 commit 4d8a3ab
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 3 deletions.
5 changes: 5 additions & 0 deletions tests/test_whitenoise.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,11 @@ def test_handles_missing_path_info_key(self):
environ={}, start_response=lambda *args: None)
self.assertTrue(response)

def test_cant_read_absolute_paths_on_windows(self):
response = self.server.get(
r'/{}/C:/Windows/System.ini'.format(TestServer.PREFIX))
self.assert_is_default_response(response)

def assert_is_default_response(self, response):
self.assertIn('Hello world!', response.text)

Expand Down
9 changes: 6 additions & 3 deletions whitenoise/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ def serve(static_file, environ, start_response):

def add_files(self, root, prefix=None):
root = decode_if_byte_string(root, force_text=True)
root = os.path.abspath(root)
root = root.rstrip(os.path.sep) + os.path.sep
prefix = decode_if_byte_string(prefix)
prefix = ensure_leading_trailing_slash(prefix)
Expand Down Expand Up @@ -140,7 +141,9 @@ def find_file(self, url):
def candidate_paths_for_url(self, url):
for root, prefix in self.directories:
if url.startswith(prefix):
yield os.path.join(root, url[len(prefix):])
path = os.path.join(root, url[len(prefix):])
if os.path.commonprefix((root, path)) == root:
yield path

def find_file_at_path(self, path, url):
if self.is_compressed_variant(path):
Expand Down Expand Up @@ -168,8 +171,8 @@ def find_file_at_path_with_indexes(self, path, url):
@staticmethod
def url_is_canonical(url):
"""
Check that the URL path does not contain any elements which might be
used in a path traversal attack
Check that the URL path is in canonical format i.e. has normalised
slashes and no path traversal elements
"""
if '\\' in url:
return False
Expand Down

0 comments on commit 4d8a3ab

Please sign in to comment.