Skip to content

Commit 061efaa

Browse files
lodi-ggopherbot
authored andcommitted
net/http: make http.FileServer return 404 when a path is invalid/unsafe
This PR adds error handling in net/http toHTTPError to return a 404 instead of a 500 when net/http fs.Dir.Open throws the error http: invalid or unsafe file path. Fixes #72091 Change-Id: I7941c8fca5160a4a82732dc1d05b9b95eac84fbf GitHub-Last-Rev: 04b5019 GitHub-Pull-Request: #72108 Reviewed-on: https://go-review.googlesource.com/c/go/+/654975 Reviewed-by: Dmitri Shuralyov <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Auto-Submit: Damien Neil <[email protected]> Reviewed-by: Damien Neil <[email protected]>
1 parent 37026a7 commit 061efaa

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

src/net/http/fs.go

+9-1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ func mapOpenError(originalErr error, name string, sep rune, stat func(string) (f
6767
return originalErr
6868
}
6969

70+
// errInvalidUnsafePath is returned by Dir.Open when the call to
71+
// filepath.Localize fails. filepath.Localize returns an error if the path
72+
// cannot be represented by the operating system.
73+
var errInvalidUnsafePath = errors.New("http: invalid or unsafe file path")
74+
7075
// Open implements [FileSystem] using [os.Open], opening files for reading rooted
7176
// and relative to the directory d.
7277
func (d Dir) Open(name string) (File, error) {
@@ -76,7 +81,7 @@ func (d Dir) Open(name string) (File, error) {
7681
}
7782
path, err := filepath.Localize(path)
7883
if err != nil {
79-
return nil, errors.New("http: invalid or unsafe file path")
84+
return nil, errInvalidUnsafePath
8085
}
8186
dir := string(d)
8287
if dir == "" {
@@ -768,6 +773,9 @@ func toHTTPError(err error) (msg string, httpStatus int) {
768773
if errors.Is(err, fs.ErrPermission) {
769774
return "403 Forbidden", StatusForbidden
770775
}
776+
if errors.Is(err, errInvalidUnsafePath) {
777+
return "404 page not found", StatusNotFound
778+
}
771779
// Default:
772780
return "500 Internal Server Error", StatusInternalServerError
773781
}

src/net/http/fs_test.go

+21
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,27 @@ func testFileServerZeroByte(t *testing.T, mode testMode) {
733733
}
734734
}
735735

736+
func TestFileServerNullByte(t *testing.T) { run(t, testFileServerNullByte) }
737+
func testFileServerNullByte(t *testing.T, mode testMode) {
738+
ts := newClientServerTest(t, mode, FileServer(Dir("testdata"))).ts
739+
740+
for _, path := range []string{
741+
"/file%00",
742+
"/%00",
743+
"/file/qwe/%00",
744+
} {
745+
res, err := ts.Client().Get(ts.URL + path)
746+
if err != nil {
747+
t.Fatal(err)
748+
}
749+
res.Body.Close()
750+
if res.StatusCode != 404 {
751+
t.Errorf("Get(%q): got status %v, want 404", path, res.StatusCode)
752+
}
753+
754+
}
755+
}
756+
736757
func TestFileServerNamesEscape(t *testing.T) { run(t, testFileServerNamesEscape) }
737758
func testFileServerNamesEscape(t *testing.T, mode testMode) {
738759
ts := newClientServerTest(t, mode, FileServer(Dir("testdata"))).ts

0 commit comments

Comments
 (0)