Skip to content

Commit 1edc8ca

Browse files
committed
CORS middleware should compile allowOrigin regexp at creation.
1 parent 5d98929 commit 1edc8ca

File tree

3 files changed

+29
-5
lines changed

3 files changed

+29
-5
lines changed

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,6 @@ benchmark: ## Run benchmarks
3131
help: ## Display this help screen
3232
@grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
3333

34-
goversion ?= "1.19"
35-
test_version: ## Run tests inside Docker with given version (defaults to 1.19 oldest supported). Example: make test_version goversion=1.19
34+
goversion ?= "1.20"
35+
test_version: ## Run tests inside Docker with given version (defaults to 1.20 oldest supported). Example: make test_version goversion=1.20
3636
@docker run --rm -it -v $(shell pwd):/project golang:$(goversion) /bin/sh -c "cd /project && make init check"

middleware/cors.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,25 @@ func CORSWithConfig(config CORSConfig) echo.MiddlewareFunc {
147147
config.AllowMethods = DefaultCORSConfig.AllowMethods
148148
}
149149

150-
allowOriginPatterns := []string{}
150+
allowOriginPatterns := make([]*regexp.Regexp, 0, len(config.AllowOrigins))
151151
for _, origin := range config.AllowOrigins {
152+
if origin == "*" {
153+
continue // "*" is handled differently and does not need regexp
154+
}
152155
pattern := regexp.QuoteMeta(origin)
153156
pattern = strings.ReplaceAll(pattern, "\\*", ".*")
154157
pattern = strings.ReplaceAll(pattern, "\\?", ".")
155158
pattern = "^" + pattern + "$"
156-
allowOriginPatterns = append(allowOriginPatterns, pattern)
159+
160+
re, err := regexp.Compile(pattern)
161+
if err != nil {
162+
// this is to preserve previous behaviour - invalid patterns were just ignored.
163+
// If we would turn this to panic, users with invalid patterns
164+
// would have applications crashing in production due unrecovered panic.
165+
// TODO: this should be turned to error/panic in `v5`
166+
continue
167+
}
168+
allowOriginPatterns = append(allowOriginPatterns, re)
157169
}
158170

159171
allowMethods := strings.Join(config.AllowMethods, ",")
@@ -239,7 +251,7 @@ func CORSWithConfig(config CORSConfig) echo.MiddlewareFunc {
239251
}
240252
if checkPatterns {
241253
for _, re := range allowOriginPatterns {
242-
if match, _ := regexp.MatchString(re, origin); match {
254+
if match := re.MatchString(origin); match {
243255
allowOrigin = origin
244256
break
245257
}

middleware/cors_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,18 @@ func TestCORS(t *testing.T) {
3131
name: "ok, wildcard AllowedOrigin with no Origin header in request",
3232
notExpectHeaders: map[string]string{echo.HeaderAccessControlAllowOrigin: ""},
3333
},
34+
{
35+
name: "ok, invalid pattern is ignored",
36+
givenMW: CORSWithConfig(CORSConfig{
37+
AllowOrigins: []string{
38+
"\xff", // Invalid UTF-8 makes regexp.Compile to error
39+
"*.example.com",
40+
},
41+
}),
42+
whenMethod: http.MethodOptions,
43+
whenHeaders: map[string]string{echo.HeaderOrigin: "http://aaa.example.com"},
44+
expectHeaders: map[string]string{echo.HeaderAccessControlAllowOrigin: "http://aaa.example.com"},
45+
},
3446
{
3547
name: "ok, specific AllowOrigins and AllowCredentials",
3648
givenMW: CORSWithConfig(CORSConfig{

0 commit comments

Comments
 (0)