diff --git a/modules/caddyhttp/vars.go b/modules/caddyhttp/vars.go index f19ca16fc..68aaca331 100644 --- a/modules/caddyhttp/vars.go +++ b/modules/caddyhttp/vars.go @@ -181,33 +181,46 @@ func (m VarsMatcher) MatchWithError(r *http.Request) (bool, error) { vars := r.Context().Value(VarsCtxKey).(map[string]any) repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer) + var fromPlaceholder bool + var matcherValExpanded, valExpanded, varStr, v string + var varValue any for key, vals := range m { - var varValue any if strings.HasPrefix(key, "{") && strings.HasSuffix(key, "}") && strings.Count(key, "{") == 1 { varValue, _ = repl.Get(strings.Trim(key, "{}")) + fromPlaceholder = true } else { varValue = vars[key] + fromPlaceholder = false + } + + switch vv := varValue.(type) { + case string: + varStr = vv + case fmt.Stringer: + varStr = vv.String() + case error: + varStr = vv.Error() + case nil: + varStr = "" + default: + varStr = fmt.Sprintf("%v", vv) + } + + // Only expand placeholders in values from literal variable names + // (e.g. map outputs). Values resolved from placeholder keys are + // already final and must not be re-expanded, as that would allow + // user input like {env.SECRET} to be evaluated. + valExpanded = varStr + if !fromPlaceholder { + valExpanded = repl.ReplaceAll(varStr, "") } // see if any of the values given in the matcher match the actual value - for _, v := range vals { - matcherValExpanded := repl.ReplaceAll(v, "") - var varStr string - switch vv := varValue.(type) { - case string: - varStr = vv - case fmt.Stringer: - varStr = vv.String() - case error: - varStr = vv.Error() - case nil: - varStr = "" - default: - varStr = fmt.Sprintf("%v", vv) - } - if varStr == matcherValExpanded { + for _, v = range vals { + matcherValExpanded = repl.ReplaceAll(v, "") + if valExpanded == matcherValExpanded { return true, nil } } @@ -310,9 +323,11 @@ func (m MatchVarsRE) Match(r *http.Request) bool { func (m MatchVarsRE) MatchWithError(r *http.Request) (bool, error) { vars := r.Context().Value(VarsCtxKey).(map[string]any) repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer) + + var fromPlaceholder, match bool + var valExpanded, varStr string + var varValue any for key, val := range m { - var varValue any - var fromPlaceholder bool if strings.HasPrefix(key, "{") && strings.HasSuffix(key, "}") && strings.Count(key, "{") == 1 { @@ -320,9 +335,9 @@ func (m MatchVarsRE) MatchWithError(r *http.Request) (bool, error) { fromPlaceholder = true } else { varValue = vars[key] + fromPlaceholder = false } - var varStr string switch vv := varValue.(type) { case string: varStr = vv @@ -340,11 +355,11 @@ func (m MatchVarsRE) MatchWithError(r *http.Request) (bool, error) { // (e.g. map outputs). Values resolved from placeholder keys are // already final and must not be re-expanded, as that would allow // user input like {env.SECRET} to be evaluated. - valExpanded := varStr + valExpanded = varStr if !fromPlaceholder { valExpanded = repl.ReplaceAll(varStr, "") } - if match := val.Match(valExpanded, repl); match { + if match = val.Match(valExpanded, repl); match { return match, nil } }