fix(config): remove trailing newlines in regexes (#373)
Closes #372 Fun YAML fact of the day: What is the difference between how these two expressions are parsed? ```yaml foo: > bar ``` ```yaml foo: >- bar ``` They are invisible in yaml, but when you evaluate them to JSON the difference is obvious: ```json { "foo": "bar\n" } ``` ```json { "foo": "bar" } ``` User-Agent strings, URL path values, and HTTP headers _do_ end in newlines in HTTP/1.1 wire form, but that newline is usually stripped before the server actually handles it. Also HTTP/2 is a thing and does not terminate header values with newlines. This change makes Anubis more aggressively detect mistaken uses of the yaml `>` operator and nudges the user into using the yaml `>-` operator which does not append the trailing newline. I had honestly forgotten about this YAML behavior because it wasn't relevant for so long. Oops! Glad I released a beta. Whenever you get into this state, Anubis will throw a config parsing error and then give you a message hinting at the folly of your ways. ``` config.Bot: regular expression ends with newline (try >- instead of > in yaml) ``` Big thanks to https://yaml-multiline.info, this helped me realize my folly instantly. @aiverson, this is official permission to say "told you so". Signed-off-by: Xe Iaso <me@xeiaso.net>
This commit is contained in:
parent
c669b47b57
commit
ef52550e70
8 changed files with 61 additions and 9 deletions
|
|
@ -110,11 +110,11 @@ func NewUserAgentChecker(rexStr string) (Checker, error) {
|
|||
}
|
||||
|
||||
func NewHeaderMatchesChecker(header, rexStr string) (Checker, error) {
|
||||
rex, err := regexp.Compile(rexStr)
|
||||
rex, err := regexp.Compile(strings.TrimSpace(rexStr))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: regex %s failed parse: %w", ErrMisconfiguration, rexStr, err)
|
||||
}
|
||||
return &HeaderMatchesChecker{header, rex, internal.SHA256sum(header + ": " + rexStr)}, nil
|
||||
return &HeaderMatchesChecker{strings.TrimSpace(header), rex, internal.SHA256sum(header + ": " + rexStr)}, nil
|
||||
}
|
||||
|
||||
func (hmc *HeaderMatchesChecker) Check(r *http.Request) (bool, error) {
|
||||
|
|
@ -135,7 +135,7 @@ type PathChecker struct {
|
|||
}
|
||||
|
||||
func NewPathChecker(rexStr string) (Checker, error) {
|
||||
rex, err := regexp.Compile(rexStr)
|
||||
rex, err := regexp.Compile(strings.TrimSpace(rexStr))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: regex %s failed parse: %w", ErrMisconfiguration, rexStr, err)
|
||||
}
|
||||
|
|
@ -155,7 +155,7 @@ func (pc *PathChecker) Hash() string {
|
|||
}
|
||||
|
||||
func NewHeaderExistsChecker(key string) Checker {
|
||||
return headerExistsChecker{key}
|
||||
return headerExistsChecker{strings.TrimSpace(key)}
|
||||
}
|
||||
|
||||
type headerExistsChecker struct {
|
||||
|
|
@ -180,11 +180,11 @@ func NewHeadersChecker(headermap map[string]string) (Checker, error) {
|
|||
|
||||
for key, rexStr := range headermap {
|
||||
if rexStr == ".*" {
|
||||
result = append(result, headerExistsChecker{key})
|
||||
result = append(result, headerExistsChecker{strings.TrimSpace(key)})
|
||||
continue
|
||||
}
|
||||
|
||||
rex, err := regexp.Compile(rexStr)
|
||||
rex, err := regexp.Compile(strings.TrimSpace(rexStr))
|
||||
if err != nil {
|
||||
errs = append(errs, fmt.Errorf("while compiling header %s regex %s: %w", key, rexStr, err))
|
||||
continue
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue