Skip to content

Commit 343627e

Browse files
authored
Do not leak directory info if append_index_html_on_directories = false (#421)
If append_index_html_on_directories is false, no info about directories should be leaked. Before this commit, one could identify directories by checking for temporary redirects (like testcase redirect_to_trailing_slash_on_dir()). This commit prevents the redirect and directly returns 404 Not found instead.
1 parent 3d3bb02 commit 343627e

File tree

2 files changed

+24
-3
lines changed

2 files changed

+24
-3
lines changed

tower-http/src/services/fs/serve_dir/open_file.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -257,9 +257,13 @@ async fn maybe_redirect_or_append_path(
257257
) -> Option<OpenFileOutput> {
258258
if !uri.path().ends_with('/') {
259259
if is_dir(path_to_file).await {
260-
let location =
261-
HeaderValue::from_str(&append_slash_on_path(uri.clone()).to_string()).unwrap();
262-
Some(OpenFileOutput::Redirect { location })
260+
if append_index_html_on_directories {
261+
let location =
262+
HeaderValue::from_str(&append_slash_on_path(uri.clone()).to_string()).unwrap();
263+
Some(OpenFileOutput::Redirect { location })
264+
} else {
265+
Some(OpenFileOutput::FileNotFound)
266+
}
263267
} else {
264268
None
265269
}

tower-http/src/services/fs/serve_dir/tests.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,23 @@ async fn empty_directory_without_index() {
398398
assert!(body.is_empty());
399399
}
400400

401+
#[tokio::test]
402+
async fn empty_directory_without_index_no_information_leak() {
403+
let svc = ServeDir::new("..").append_index_html_on_directories(false);
404+
405+
let req = Request::builder()
406+
.uri("/test-files")
407+
.body(Body::empty())
408+
.unwrap();
409+
let res = svc.oneshot(req).await.unwrap();
410+
411+
assert_eq!(res.status(), StatusCode::NOT_FOUND);
412+
assert!(res.headers().get(header::CONTENT_TYPE).is_none());
413+
414+
let body = body_into_text(res.into_body()).await;
415+
assert!(body.is_empty());
416+
}
417+
401418
async fn body_into_text<B>(body: B) -> String
402419
where
403420
B: HttpBody<Data = bytes::Bytes> + Unpin,

0 commit comments

Comments
 (0)