Files
doormile_backend/cors_test.go

81 lines
2.6 KiB
Go

package main
import "testing"
// Which Origin headers count as "this machine".
//
// This exists because Flutter Web's dev server binds a random high port on every
// launch, so no fixed allowlist can name it — the app hit
// PreflightMissingAllowOriginHeader from http://localhost:65256 and would have
// hit it again from a different port tomorrow.
//
// The reason it is worth a test rather than a one-line helper: the obvious
// implementation is a prefix or substring match on "localhost", and that quietly
// admits http://localhost.attacker.com — a completely different machine that
// merely starts with the right word. Combined with AllowCredentials, that would
// let an attacker-controlled page make authenticated calls as the signed-in user.
// A parsed-host comparison is the only version that is actually safe, and this
// pins it.
func TestLoopbackOriginsAreAllowed(t *testing.T) {
for _, origin := range []string{
"http://localhost:65256", // the port Flutter Web picked; it changes every run
"http://localhost:5173",
"http://localhost",
"https://localhost:8443",
"http://127.0.0.1:3000",
"http://127.0.0.1",
"http://[::1]:8080",
} {
if !isLoopbackOrigin(origin) {
t.Errorf("%q is this machine and should be allowed in development", origin)
}
}
}
func TestLookalikeOriginsAreRefused(t *testing.T) {
// Every one of these contains "localhost" or "127.0.0.1" as a substring and
// is a different host. A prefix or Contains check would admit all of them.
for _, origin := range []string{
"http://localhost.attacker.com",
"https://localhost.evil.io:443",
"http://notlocalhost",
"http://mylocalhost:3000",
"http://127.0.0.1.attacker.com",
"http://evil.com/?x=http://localhost:3000",
"http://evil.com#localhost",
} {
if isLoopbackOrigin(origin) {
t.Errorf("%q is NOT this machine and must be refused", origin)
}
}
}
func TestNonHTTPSchemesAreRefused(t *testing.T) {
// An Origin is a scheme/host/port triple. Anything else is either a browser
// that will not send it or something forged, and neither should be trusted.
for _, origin := range []string{
"file://localhost",
"ftp://localhost:21",
"javascript:alert(1)",
"chrome-extension://abcdefghijklmnop",
} {
if isLoopbackOrigin(origin) {
t.Errorf("%q is not an http(s) origin and must be refused", origin)
}
}
}
func TestMalformedOriginsAreRefused(t *testing.T) {
for _, origin := range []string{
"",
"null", // what a sandboxed iframe sends
"not a url at all",
"://missing-scheme",
} {
if isLoopbackOrigin(origin) {
t.Errorf("%q is not a usable origin and must be refused", origin)
}
}
}