Skip to content

CORS and websocket origin allowlists match unanchored, so 'https://example.com' also allows 'https://example.com.evil.net' #1052

Description

@lbellows

Both origin allowlists compile config entries with regexp.MustCompile and match with MatchString, which is a substring match unless the operator remembers to anchor:

  • auth/cors.go:45compileAllowedCORSOrigins, used by AllowOriginFunc
  • api/stream/stream.go:183compileAllowedWebSocketOrigins, used by Upgrader.CheckOrigin

So a natural-looking value matches any hostname that merely contains it:

$ GOTIFY_SERVER_CORS_ALLOWORIGINS='https://gotify.example.com' gotify serve

$ curl -sD- -o/dev/null -H 'Origin: https://gotify.example.com' localhost:8792/version
Access-Control-Allow-Origin: https://gotify.example.com
$ curl -sD- -o/dev/null -H 'Origin: https://gotify.example.com.evil.net' localhost:8792/version
Access-Control-Allow-Origin: https://gotify.example.com.evil.net      # <-- allowed
$ curl -sD- -o/dev/null -H 'Origin: http://evil.net' localhost:8792/version
(no ACAO header)

Impact is limited — AllowCredentials is never set, so the cookie is not sent cross-origin, and an attacker still needs a token to read anything — but the allowlist does not mean what an operator reading the env var name would assume, and the same footgun applies to GOTIFY_SERVER_STREAM_ALLOWEDORIGINS on the websocket.

Options, in rough order of preference:

  1. Anchor automatically: wrap each entry as ^(?:…)$ before compiling (breaks any existing config that relies on a trailing .*, so it would need a release note).
  2. Keep the regex but warn at startup when an entry is not anchored.
  3. Document the anchoring requirement in the config docs, at minimum.

Happy to send a PR for whichever you prefer.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    a:bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions