Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

net/http: CrossOriginProtection insecure bypass patterns not limited to exact matches #75054

Closed
Labels
BugReportIssues describing a possible bug in the Go implementation. FixPendingIssues that have a fix which has not yet been reviewed or submitted. NeedsFixThe path to resolution is known, but the work has not been done. Security
Milestone
@gazerro

Description

The AddInsecureBypassPattern method of http.CrossOriginProtection, introduced in version 1.25, shows unexpected behavior.

This method is supposed to allow requests matching a given pattern to bypass protection. The issue is that more requests than expected end up being bypassed.

For example, if you define a ServeMux with two paths, /hello and /hello/:

mux := http.NewServeMux()
mux.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("/hello"))
})
mux.HandleFunc("/hello/", func(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("/hello/"))
})

and you configure the bypass for /hello/:

c := http.NewCrossOriginProtection()
c.AddInsecureBypassPattern("/hello/")
h := c.Handler(mux)

the result is that /hello also gets bypassed. Here's a complete example:

package main
import (
	"fmt"
	"net/http"
	"net/http/httptest"
)
func main() {
	mux := http.NewServeMux()
	mux.HandleFunc("/hello/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("/hello/"))
	})
	mux.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("/hello"))
	})
	c := http.NewCrossOriginProtection()
	c.AddInsecureBypassPattern("/hello/")
	h := c.Handler(mux)
	r := httptest.NewRequest("POST", "http://example.test/hello", nil)
	r.Header.Set("Sec-Fetch-Site", "cross-site")
	r.Header.Set("Origin", "https://evil.test")
	rec := httptest.NewRecorder()
	h.ServeHTTP(rec, r)
	fmt.Println(rec.Code, rec.Body.String())
}

Why this happens

CrossOriginProtection uses an internal ServeMux to check the bypass pattern. For /hello/, ServeMux would internally redirect /hello to /hello/. As a result, the internal check finds a non-empty match and CrossOriginProtection skips validation.

However, CrossOriginProtection does not actually rewrite or redirect the request path; it forwards the original one. Since the downstream mux defines a real handler for /hello, the request is served without protection.

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugReportIssues describing a possible bug in the Go implementation. FixPendingIssues that have a fix which has not yet been reviewed or submitted. NeedsFixThe path to resolution is known, but the work has not been done. Security

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      AltStyle によって変換されたページ (->オリジナル) /