Skip to content

Commit

Permalink
Merge pull request from GHSA-v5gw-mw7f-84px
Browse files Browse the repository at this point in the history
  • Loading branch information
aminalaee committed May 16, 2023
1 parent 24c1fac commit 1797de4
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 6 deletions.
2 changes: 1 addition & 1 deletion starlette/staticfiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ def lookup_path(
else:
full_path = os.path.realpath(joined_path)
directory = os.path.realpath(directory)
if os.path.commonprefix([full_path, directory]) != directory:
if os.path.commonpath([full_path, directory]) != directory:
# Don't allow misbehaving clients to break out of the static files
# directory.
continue
Expand Down
42 changes: 37 additions & 5 deletions tests/test_staticfiles.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import os
import pathlib
import stat
import tempfile
import time
from pathlib import Path

import anyio
import pytest
Expand All @@ -28,13 +28,12 @@ def test_staticfiles(tmpdir, test_client_factory):
assert response.text == "<file content>"


def test_staticfiles_with_pathlib(tmpdir, test_client_factory):
base_dir = pathlib.Path(tmpdir)
path = base_dir / "example.txt"
def test_staticfiles_with_pathlib(tmp_path: Path, test_client_factory):
path = tmp_path / "example.txt"
with open(path, "w") as file:
file.write("<file content>")

app = StaticFiles(directory=base_dir)
app = StaticFiles(directory=tmp_path)
client = test_client_factory(app)
response = client.get("/example.txt")
assert response.status_code == 200
Expand Down Expand Up @@ -516,3 +515,36 @@ def test_staticfiles_disallows_path_traversal_with_symlinks(tmpdir):

assert exc_info.value.status_code == 404
assert exc_info.value.detail == "Not Found"


def test_staticfiles_avoids_path_traversal(tmp_path: Path):
statics_path = tmp_path / "static"
statics_disallow_path = tmp_path / "static_disallow"

statics_path.mkdir()
statics_disallow_path.mkdir()

static_index_file = statics_path / "index.html"
statics_disallow_path_index_file = statics_disallow_path / "index.html"
static_file = tmp_path / "static1.txt"

static_index_file.write_text("<h1>Hello</h1>")
statics_disallow_path_index_file.write_text("<h1>Private</h1>")
static_file.write_text("Private")

app = StaticFiles(directory=statics_path)

# We can't test this with 'httpx', so we test the app directly here.
path = app.get_path({"path": "/../static1.txt"})
with pytest.raises(HTTPException) as exc_info:
anyio.run(app.get_response, path, {"method": "GET"})

assert exc_info.value.status_code == 404
assert exc_info.value.detail == "Not Found"

path = app.get_path({"path": "/../static_disallow/index.html"})
with pytest.raises(HTTPException) as exc_info:
anyio.run(app.get_response, path, {"method": "GET"})

assert exc_info.value.status_code == 404
assert exc_info.value.detail == "Not Found"

0 comments on commit 1797de4

Please sign in to comment.