aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGrégoire Lodi <pro@lodi.me>2025-03-05 09:44:46 +0000
committerGopher Robot <gobot@golang.org>2025-03-05 11:26:39 -0800
commit061efaa8a761458eaa41119ffd59033738cf141c (patch)
tree9b9d168aeba7ca7cc5fd596352dac45a6a4f425d /src
parent37026a7c563c580bef0fac1e5b60e9498650e3a2 (diff)
downloadgo-061efaa8a761458eaa41119ffd59033738cf141c.tar.xz
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: 04b5019dfb629820621f3776d6f22fd754171565 GitHub-Pull-Request: golang/go#72108 Reviewed-on: https://go-review.googlesource.com/c/go/+/654975 Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Damien Neil <dneil@google.com> Reviewed-by: Damien Neil <dneil@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/net/http/fs.go10
-rw-r--r--src/net/http/fs_test.go21
2 files changed, 30 insertions, 1 deletions
diff --git a/src/net/http/fs.go b/src/net/http/fs.go
index 48ba05a664..92bd94f72d 100644
--- a/src/net/http/fs.go
+++ b/src/net/http/fs.go
@@ -67,6 +67,11 @@ func mapOpenError(originalErr error, name string, sep rune, stat func(string) (f
return originalErr
}
+// errInvalidUnsafePath is returned by Dir.Open when the call to
+// filepath.Localize fails. filepath.Localize returns an error if the path
+// cannot be represented by the operating system.
+var errInvalidUnsafePath = errors.New("http: invalid or unsafe file path")
+
// Open implements [FileSystem] using [os.Open], opening files for reading rooted
// and relative to the directory d.
func (d Dir) Open(name string) (File, error) {
@@ -76,7 +81,7 @@ func (d Dir) Open(name string) (File, error) {
}
path, err := filepath.Localize(path)
if err != nil {
- return nil, errors.New("http: invalid or unsafe file path")
+ return nil, errInvalidUnsafePath
}
dir := string(d)
if dir == "" {
@@ -768,6 +773,9 @@ func toHTTPError(err error) (msg string, httpStatus int) {
if errors.Is(err, fs.ErrPermission) {
return "403 Forbidden", StatusForbidden
}
+ if errors.Is(err, errInvalidUnsafePath) {
+ return "404 page not found", StatusNotFound
+ }
// Default:
return "500 Internal Server Error", StatusInternalServerError
}
diff --git a/src/net/http/fs_test.go b/src/net/http/fs_test.go
index 3149ca35ac..9b34ad080e 100644
--- a/src/net/http/fs_test.go
+++ b/src/net/http/fs_test.go
@@ -733,6 +733,27 @@ func testFileServerZeroByte(t *testing.T, mode testMode) {
}
}
+func TestFileServerNullByte(t *testing.T) { run(t, testFileServerNullByte) }
+func testFileServerNullByte(t *testing.T, mode testMode) {
+ ts := newClientServerTest(t, mode, FileServer(Dir("testdata"))).ts
+
+ for _, path := range []string{
+ "/file%00",
+ "/%00",
+ "/file/qwe/%00",
+ } {
+ res, err := ts.Client().Get(ts.URL + path)
+ if err != nil {
+ t.Fatal(err)
+ }
+ res.Body.Close()
+ if res.StatusCode != 404 {
+ t.Errorf("Get(%q): got status %v, want 404", path, res.StatusCode)
+ }
+
+ }
+}
+
func TestFileServerNamesEscape(t *testing.T) { run(t, testFileServerNamesEscape) }
func testFileServerNamesEscape(t *testing.T, mode testMode) {
ts := newClientServerTest(t, mode, FileServer(Dir("testdata"))).ts