diff options
| author | Xe Iaso <me@xeiaso.net> | 2025-04-26 10:01:15 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-04-26 14:01:15 +0000 |
| commit | ef52550e70a44c318dca8a406750589f67fac0eb (patch) | |
| tree | d00e403f38960ab9f86c8dadf41907099ecad391 /lib/policy/checker.go | |
| parent | c669b47b570d222a9a902705adeff8fb26c989c4 (diff) | |
| download | anubis-1.17.0-beta2.tar.xz anubis-1.17.0-beta2.zip | |
fix(config): remove trailing newlines in regexes (#373)v1.17.0-beta31.17.0-beta2
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>
Diffstat (limited to 'lib/policy/checker.go')
| -rw-r--r-- | lib/policy/checker.go | 12 |
1 files changed, 6 insertions, 6 deletions
diff --git a/lib/policy/checker.go b/lib/policy/checker.go index ad98ced..51223cd 100644 --- a/lib/policy/checker.go +++ b/lib/policy/checker.go @@ -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 |
