Add RFC 6265bis cookie checks: name prefixes and per-cookie size
This commit is contained in:
parent
01bdadd2ab
commit
2250902a94
4 changed files with 329 additions and 3 deletions
160
checker/rules_cookies_rfc6265bis_test.go
Normal file
160
checker/rules_cookies_rfc6265bis_test.go
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
// This file is part of the happyDomain (R) project.
|
||||
// Copyright (c) 2020-2026 happyDomain
|
||||
// Authors: Pierre-Olivier Mercier, et al.
|
||||
|
||||
package checker
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
sdk "git.happydns.org/checker-sdk-go/checker"
|
||||
)
|
||||
|
||||
func TestCookiePrefixesRule_NoHTTPS(t *testing.T) {
|
||||
data := &HTTPData{Probes: []HTTPProbe{httpProbe("a:80")}}
|
||||
states := runRule(t, &cookiePrefixesRule{}, data, nil)
|
||||
mustStatus(t, states, sdk.StatusUnknown)
|
||||
if !hasCode(states, "http.cookie_prefixes.no_https") {
|
||||
t.Errorf("missing no_https code: %+v", states)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCookiePrefixesRule_NoPrefixed(t *testing.T) {
|
||||
p := httpsProbe("a:443")
|
||||
p.Cookies = []CookieInfo{{Name: "sid", Secure: true, HttpOnly: true, SameSite: "Lax"}}
|
||||
states := runRule(t, &cookiePrefixesRule{}, &HTTPData{Probes: []HTTPProbe{p}}, nil)
|
||||
mustStatus(t, states, sdk.StatusInfo)
|
||||
if !hasCode(states, "http.cookie_prefixes.none") {
|
||||
t.Errorf("missing 'none' code: %+v", states)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCookiePrefixesRule_HostOK(t *testing.T) {
|
||||
p := httpsProbe("a:443")
|
||||
p.Cookies = []CookieInfo{
|
||||
{Name: "__Host-sid", Secure: true, HttpOnly: true, SameSite: "Strict", Path: "/"},
|
||||
{Name: "__Secure-tok", Secure: true, HttpOnly: true, SameSite: "Lax", Path: "/app"},
|
||||
}
|
||||
states := runRule(t, &cookiePrefixesRule{}, &HTTPData{Probes: []HTTPProbe{p}}, nil)
|
||||
mustStatus(t, states, sdk.StatusOK)
|
||||
if !hasCode(states, "http.cookie_prefixes.ok") {
|
||||
t.Errorf("missing ok code: %+v", states)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCookiePrefixesRule_SecureMissingSecure(t *testing.T) {
|
||||
p := httpsProbe("a:443")
|
||||
p.Cookies = []CookieInfo{{Name: "__Secure-x", Secure: false, HttpOnly: true, SameSite: "Lax"}}
|
||||
states := runRule(t, &cookiePrefixesRule{}, &HTTPData{Probes: []HTTPProbe{p}}, nil)
|
||||
mustStatus(t, states, sdk.StatusWarn)
|
||||
if !hasCode(states, "http.cookie_prefixes.invalid_secure") {
|
||||
t.Errorf("missing invalid_secure code: %+v", states)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCookiePrefixesRule_HostViolations(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
cookie CookieInfo
|
||||
want []string
|
||||
}{
|
||||
{
|
||||
name: "no Secure",
|
||||
cookie: CookieInfo{Name: "__Host-a", Secure: false, Path: "/"},
|
||||
want: []string{"missing Secure"},
|
||||
},
|
||||
{
|
||||
name: "Domain set",
|
||||
cookie: CookieInfo{Name: "__Host-a", Secure: true, Domain: "example.test", Path: "/"},
|
||||
want: []string{"Domain attribute is forbidden"},
|
||||
},
|
||||
{
|
||||
name: "wrong Path",
|
||||
cookie: CookieInfo{Name: "__Host-a", Secure: true, Path: "/app"},
|
||||
want: []string{`Path must be "/"`},
|
||||
},
|
||||
{
|
||||
name: "all three",
|
||||
cookie: CookieInfo{Name: "__Host-a", Secure: false, Domain: "x", Path: "/x"},
|
||||
want: []string{"missing Secure", "Domain attribute is forbidden", `Path must be "/"`},
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
p := httpsProbe("a:443")
|
||||
p.Cookies = []CookieInfo{c.cookie}
|
||||
states := runRule(t, &cookiePrefixesRule{}, &HTTPData{Probes: []HTTPProbe{p}}, nil)
|
||||
mustStatus(t, states, sdk.StatusWarn)
|
||||
if !hasCode(states, "http.cookie_prefixes.invalid_host") {
|
||||
t.Fatalf("missing invalid_host code: %+v", states)
|
||||
}
|
||||
for _, w := range c.want {
|
||||
if !strings.Contains(states[0].Message, w) {
|
||||
t.Errorf("message missing %q: %s", w, states[0].Message)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCookiePrefixesRule_LoadFailure(t *testing.T) {
|
||||
states := (&cookiePrefixesRule{}).Evaluate(t.Context(), &fakeObs{failGet: true}, nil)
|
||||
if len(states) != 1 || states[0].Status != sdk.StatusError {
|
||||
t.Fatalf("expected single error state, got %+v", states)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCookieSizeRule_NoHTTPS(t *testing.T) {
|
||||
data := &HTTPData{Probes: []HTTPProbe{httpProbe("a:80")}}
|
||||
states := runRule(t, &cookieSizeRule{}, data, nil)
|
||||
mustStatus(t, states, sdk.StatusUnknown)
|
||||
}
|
||||
|
||||
func TestCookieSizeRule_None(t *testing.T) {
|
||||
data := &HTTPData{Probes: []HTTPProbe{httpsProbe("a:443")}}
|
||||
states := runRule(t, &cookieSizeRule{}, data, nil)
|
||||
mustStatus(t, states, sdk.StatusOK)
|
||||
if !hasCode(states, "http.cookie_size.none") {
|
||||
t.Errorf("missing 'none' code: %+v", states)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCookieSizeRule_OK(t *testing.T) {
|
||||
p := httpsProbe("a:443")
|
||||
p.Cookies = []CookieInfo{
|
||||
{Name: "small", Size: 200},
|
||||
{Name: "borderline", Size: MaxCookieSize}, // exactly the limit is acceptable
|
||||
}
|
||||
states := runRule(t, &cookieSizeRule{}, &HTTPData{Probes: []HTTPProbe{p}}, nil)
|
||||
mustStatus(t, states, sdk.StatusOK)
|
||||
if !hasCode(states, "http.cookie_size.ok") {
|
||||
t.Errorf("missing ok code: %+v", states)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCookieSizeRule_TooLarge(t *testing.T) {
|
||||
p := httpsProbe("a:443")
|
||||
p.Cookies = []CookieInfo{
|
||||
{Name: "small", Size: 100},
|
||||
{Name: "huge", Size: MaxCookieSize + 1},
|
||||
}
|
||||
states := runRule(t, &cookieSizeRule{}, &HTTPData{Probes: []HTTPProbe{p}}, nil)
|
||||
if len(states) != 1 {
|
||||
t.Fatalf("got %d states, want 1 (only the oversized cookie)", len(states))
|
||||
}
|
||||
mustStatus(t, states, sdk.StatusWarn)
|
||||
if !hasCode(states, "http.cookie_size.too_large") {
|
||||
t.Errorf("missing too_large code: %+v", states)
|
||||
}
|
||||
if !strings.Contains(states[0].Message, "huge") {
|
||||
t.Errorf("message should mention cookie name: %q", states[0].Message)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCookieSizeRule_LoadFailure(t *testing.T) {
|
||||
states := (&cookieSizeRule{}).Evaluate(t.Context(), &fakeObs{failGet: true}, nil)
|
||||
if len(states) != 1 || states[0].Status != sdk.StatusError {
|
||||
t.Fatalf("expected single error state, got %+v", states)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue