CVE-2017-20146 (published 2022-12-27T22:15Z)

Usage of the CORS handler may apply improper CORS headers, allowing the requester to explicitly control the value of the Access-Control-Allow-Origin header, which bypasses the expected behavior of the Same Origin Policy.

CVSS v3 base score: 9.8, CRITICAL (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-346
cwe_name: Origin Validation Error
description: The product does not properly verify that the source of data or communication is valid.
extended_description: 
            
            
            
         
         

Fix information:
repo_url: https://github.com/gorilla/handlers
commit_details: repo_url: https://github.com/gorilla/handlers
author: Evan J Johnson
author_date: 2017-11-01 10:43:35-07:00
msg: [bugfix] Don't return the origin header when configured to * (#116)

There's no reason to allow for a server to reflect all origin headers.
This has caused numerous security problems in the past.
 - https://github.com/cyu/rack-cors/issues/126
 - https://nodesecurity.io/advisories/148
 - https://github.com/captncraig/cors/commit/cc1cf75f5e3c06124602f2aa7893c8f3b1eef0b7

Some helpful blog posts on the topic:
 - https://ejj.io/misconfigured-cors/
 - http://blog.portswigger.net/2016/10/exploiting-cors-misconfigurations-for.html
repository: repo_url: https://github.com/gorilla/handlers
repo_name: gorilla/handlers
description: Package gorilla/handlers is a collection of useful middleware for Go HTTP services & web applications 🛃
repo_language: Go
owner: gorilla
file_changes: filename: cors.go
change_type: ModificationType.MODIFY
diff: @@ -110,7 +110,17 @@ func (ch *cors) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 		w.Header().Set(corsVaryHeader, corsOriginHeader)
 	}
 
-	w.Header().Set(corsAllowOriginHeader, origin)
+	returnOrigin := origin
+	for _, o := range ch.allowedOrigins {
+		// A configuration of * is different than explicitly setting an allowed
+		// origin. Returning arbitrary origin headers an an access control allow
+		// origin header is unsafe and is not required by any use case.
+		if o == corsOriginMatchAll {
+			returnOrigin = "*"
+			break
+		}
+	}
+	w.Header().Set(corsAllowOriginHeader, returnOrigin)
 
 	if r.Method == corsOptionMethod {
 		return

programming_language: Go
filename: cors_test.go
change_type: ModificationType.MODIFY
diff: @@ -327,10 +327,45 @@ func TestCORSHandlerWithCustomValidator(t *testing.T) {
 		return false
 	}
 
-	CORS(AllowedOriginValidator(originValidator))(testHandler).ServeHTTP(rr, r)
+	// Specially craft a CORS object.
+	handleFunc := func(h http.Handler) http.Handler {
+		c := &cors{
+			allowedMethods: defaultCorsMethods,
+			allowedHeaders: defaultCorsHeaders,
+			allowedOrigins: []string{"http://a.example.com"},
+			h:              h,
+		}
+		AllowedOriginValidator(originValidator)(c)
+		return c
+	}
+
+	handleFunc(testHandler).ServeHTTP(rr, r)
 	header := rr.HeaderMap.Get(corsAllowOriginHeader)
 	if header != r.URL.String() {
 		t.Fatalf("bad header: expected %s to be %s, got %s.", corsAllowOriginHeader, r.URL.String(), header)
 	}
 
 }
+
+func TestCORSAllowStar(t *testing.T) {
+	r := newRequest("GET", "http://a.example.com")
+	r.Header.Set("Origin", r.URL.String())
+	rr := httptest.NewRecorder()
+
+	testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
+	originValidator := func(origin string) bool {
+		if strings.HasSuffix(origin, ".example.com") {
+			return true
+		}
+		return false
+	}
+
+	CORS(AllowedOriginValidator(originValidator))(testHandler).ServeHTTP(rr, r)
+	header := rr.HeaderMap.Get(corsAllowOriginHeader)
+	// Because * is the default CORS policy (which is safe), we should be
+	// expect a * returned here as the Access Control Allow Origin header
+	if header != "*" {
+		t.Fatalf("bad header: expected %s to be %s, got %s.", corsAllowOriginHeader, r.URL.String(), header)
+	}
+
+}

programming_language: Go