mirror of
https://github.com/lukaszraczylo/traefikoidc.git
synced 2026-10-12 04:04:26 +00:00
fix(settings): tolerate whitespace in header template delimiters (#148)
validateTemplateSecure matched safe functions with literal strings.Contains
("{{get "), so a space after {{ ("{{ get") failed the whitelist and
Config.Validate() rejected the config, surfacing as Traefik's opaque
"invalid handler type: <nil>". Go's text/template treats {{ get and {{get
identically, so the validator was stricter than the engine.
Normalize inner-delimiter whitespace before matching. This also closes a
security gap where a leading space let dangerous patterns ("{{ range",
"{{ call") evade detection.
Adds unit + regression coverage.
This commit is contained in:
+28
@@ -9,10 +9,32 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// templateDelimWhitespace matches whitespace immediately inside Go template
|
||||
// delimiters: after "{{" or before "}}". Go's text/template treats "{{ get",
|
||||
// "{{ get" and "{{get" identically, so the security validator must collapse
|
||||
// this whitespace before pattern-matching — otherwise a leading space both
|
||||
// rejects valid templates (issue #148) and lets dangerous patterns such as
|
||||
// "{{ range" slip past detection.
|
||||
var templateDelimWhitespace = regexp.MustCompile(`\{\{[ \t]+|[ \t]+\}\}`)
|
||||
|
||||
// normalizeTemplateDelimiters collapses inner-delimiter whitespace so that
|
||||
// "{{ get .Claims \"x\" }}" becomes "{{get .Claims \"x\"}}" for matching.
|
||||
// Trim markers ("{{-", "-}}") are left intact: the dash is not whitespace, so
|
||||
// they remain detectable as dangerous patterns.
|
||||
func normalizeTemplateDelimiters(templateStr string) string {
|
||||
return templateDelimWhitespace.ReplaceAllStringFunc(templateStr, func(m string) string {
|
||||
if strings.HasPrefix(m, "{{") {
|
||||
return "{{"
|
||||
}
|
||||
return "}}"
|
||||
})
|
||||
}
|
||||
|
||||
// TemplatedHeader represents a custom HTTP header with a templated value.
|
||||
// The value can contain template expressions that will be evaluated for each
|
||||
// authenticated request, such as {{.claims.email}} or {{.accessToken}}.
|
||||
@@ -569,6 +591,12 @@ func (c *Config) Validate() error {
|
||||
// It checks for dangerous template patterns that could lead to code execution or data leaks
|
||||
// while allowing safe custom functions for field access and default values.
|
||||
func validateTemplateSecure(templateStr string) error {
|
||||
// Normalize inner-delimiter whitespace up front so that "{{ get .Claims }}"
|
||||
// is validated identically to "{{get .Claims}}" (issue #148). All matching
|
||||
// below operates on the normalized form, which also prevents a stray space
|
||||
// from smuggling a dangerous pattern (e.g. "{{ range") past detection.
|
||||
templateStr = normalizeTemplateDelimiters(templateStr)
|
||||
|
||||
// Allow our specific safe custom functions
|
||||
// These are added specifically to handle missing fields safely (issue #60)
|
||||
safeCustomFunctions := []string{
|
||||
|
||||
Reference in New Issue
Block a user