gohugoio/hugo · error

failed to compile whitelist pattern

Error message

failed to compile whitelist pattern %q: %w

What it means

config/security.NewWhitelist (config/security/whitelist.go:89) compiles each supplied pattern as a Go regexp, after optionally stripping a '!' negation prefix (hglob.NegationPrefix). This wraps regexp.Compile failure with the offending pattern. Whitelists back the security config allow/deny lists (e.g. security.exec.allow, security.http.urls).

Solutions

  1. Validate each whitelist pattern with regexp.Compile in isolation before adding it to config.
  2. Remember patterns are regex, not globs: use '.*' for 'any', and escape literal dots with '\.'.
  3. If you intended a negation, prefix with '!' (hglob.NegationPrefix) only once.
  4. Strip the pattern down to the simplest form and re-add complexity once it compiles.

Example fix

// before
[security.exec]
allow = ['^.*$', '*.sh']  // '*.sh' is glob syntax -> invalid regex

// after
[security.exec]
allow = ['^.*$', '.*\.sh$']
Defensive patterns

Strategy: validation

Validate before calling

func ValidateWhitelistPatterns(patterns ...string) error {
    for _, p := range patterns {
        raw := strings.TrimPrefix(p, "!") // hglob.NegationPrefix
        if _, err := regexp.Compile(raw); err != nil {
            return fmt.Errorf("pattern %q: %w", p, err)
        }
    }
    return nil
}

Try / catch

w, err := security.NewWhitelist(patterns...)
if err != nil {
    return fmt.Errorf("security whitelist: %w", err)
}

Prevention

When it happens

Trigger: Setting a security allow/deny list entry with invalid regexp syntax such as an unclosed character class '[a-z', a dangling quantifier '*', or an unbalanced parenthesis.

Common situations: Typing a glob-style pattern where a regex is expected (e.g. '*.js' instead of '.*\.js'); copy-pasting a pattern from a glob-based tool; unescaped metacharacters meant literally.

Related errors


AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09). Data as JSON: /api/errors/7cd510f1b287aa4a. Report an issue: GitHub.

Appendix: source

Thrown at config/security/whitelist.go:91

			acceptSome = true
			patternsStrings = append(patternsStrings, ps)
		}
	}

	if !acceptSome {
		return Whitelist{acceptNone: true}, nil
	}

	var allow, deny []*regexp.Regexp
	for _, p := range patternsStrings {
		raw := p
		negate := strings.HasPrefix(p, hglob.NegationPrefix)
		if negate {
			raw = p[len(hglob.NegationPrefix):]
		}
		re, err := regexp.Compile(raw)
		if err != nil {
			return Whitelist{}, fmt.Errorf("failed to compile whitelist pattern %q: %w", p, err)
		}
		if negate {
			deny = append(deny, re)
		} else {
			allow = append(allow, re)
		}
	}

	return Whitelist{allow: allow, deny: deny, patternsStrings: patternsStrings}, nil
}

// MustNewWhitelist creates a new Whitelist from zero or more patterns and panics on error.
func MustNewWhitelist(patterns ...string) Whitelist {
	w, err := NewWhitelist(patterns...)
	if err != nil {
		panic(err)
	}
	return w

View on GitHub (pinned to 52c9bd7908)