From 07b487c5cd7fafbad06d693782b2867f21150ffa Mon Sep 17 00:00:00 2001 From: Samantha Date: Sat, 22 Jun 2024 12:01:17 +0100 Subject: [PATCH] resolve comments --- checks/hsts.go | 49 ++++++++++++++++++--------------------------- checks/hsts_test.go | 26 ++++++++++++------------ 2 files changed, 32 insertions(+), 43 deletions(-) diff --git a/checks/hsts.go b/checks/hsts.go index da24593..19ace02 100644 --- a/checks/hsts.go +++ b/checks/hsts.go @@ -8,17 +8,6 @@ import ( "unicode" ) -const ( - StrictTransportSecurity = "Strict-Transport-Security" - includeSubDomains = "includeSubDomains" - preload = "preload" - NilHeadersError = "Site does not serve any HSTS headers." - MaxAgeError = "HSTS max-age is less than 10886400." - SubdomainsError = "HSTS header does not include all subdomains." - PreloadError = "HSTS header does not contain the preload directive." - HstsSuccess = "Site is compatible with the HSTS preload list!" -) - type HSTSResponse struct { Message string `json:"message"` Compatible bool `json:"compatible"` @@ -45,37 +34,41 @@ func (h *Hsts) Validate(ctx context.Context, url string) (*HSTSResponse, error) } defer resp.Body.Close() - hstsHeader := resp.Header.Get(StrictTransportSecurity) + hstsHeader := resp.Header.Get("Strict-Transport-Security") if hstsHeader == "" { - return &HSTSResponse{ - Message: NilHeadersError, - }, nil + return &HSTSResponse{Message: "Site does not serve any HSTS headers."}, nil } - maxAge := extractMaxAgeFromHeader(hstsHeader) - if maxAge == "" { - return &HSTSResponse{Message: MaxAgeError}, nil + if !strings.Contains(hstsHeader, "max-age") { + return &HSTSResponse{Message: "HSTS max-age is less than 10886400."}, nil } - maxAgeInt, err := convertMaxAgeStringToInt(maxAge) + var maxAgeString string + for _, h := range strings.Split(hstsHeader, " ") { + if strings.Contains(h, "max-age=") { + maxAgeString = extractMaxAgeFromHeader(h) + } + } + + maxAge, err := strconv.Atoi(maxAgeString) if err != nil { return nil, err } - if maxAgeInt < 10886400 { - return &HSTSResponse{Message: MaxAgeError}, nil + if maxAge < 10886400 { + return &HSTSResponse{Message: "HSTS max-age is less than 10886400."}, nil } - if !strings.Contains(hstsHeader, includeSubDomains) { - return &HSTSResponse{Message: SubdomainsError}, nil + if !strings.Contains(hstsHeader, "includeSubDomains") { + return &HSTSResponse{Message: "HSTS header does not include all subdomains."}, nil } - if !strings.Contains(hstsHeader, preload) { - return &HSTSResponse{Message: PreloadError}, nil + if !strings.Contains(hstsHeader, "preload") { + return &HSTSResponse{Message: "HSTS header does not contain the preload directive."}, nil } return &HSTSResponse{ - Message: HstsSuccess, + Message: "Site is compatible with the HSTS preload list!", Compatible: true, HSTSHeader: hstsHeader, }, nil @@ -92,7 +85,3 @@ func extractMaxAgeFromHeader(header string) string { return maxAge.String() } - -func convertMaxAgeStringToInt(maxAge string) (int, error) { - return strconv.Atoi(maxAge) -} diff --git a/checks/hsts_test.go b/checks/hsts_test.go index b06687a..e64eb59 100644 --- a/checks/hsts_test.go +++ b/checks/hsts_test.go @@ -16,13 +16,13 @@ func TestValidate(t *testing.T) { t.Parallel() client := testutils.MockClient(&http.Response{ - Header: http.Header{StrictTransportSecurity: []string{""}}}) + Header: http.Header{"Strict-Transport-Security": []string{""}}}) h := NewHsts(client) actual, err := h.Validate(context.Background(), "test.com") assert.NoError(t, err) - assert.Equal(t, NilHeadersError, actual.Message) + assert.Equal(t, "Site does not serve any HSTS headers.", actual.Message) assert.False(t, actual.Compatible) assert.Empty(t, actual.HSTSHeader) }) @@ -31,13 +31,13 @@ func TestValidate(t *testing.T) { t.Parallel() client := testutils.MockClient(&http.Response{ - Header: http.Header{StrictTransportSecurity: []string{"includeSubDomains; preload"}}}) + Header: http.Header{"Strict-Transport-Security": []string{"includeSubDomains; preload"}}}) h := NewHsts(client) actual, err := h.Validate(context.Background(), "test.com") assert.NoError(t, err) - assert.Equal(t, MaxAgeError, actual.Message) + assert.Equal(t, "HSTS max-age is less than 10886400.", actual.Message) assert.False(t, actual.Compatible) assert.Empty(t, actual.HSTSHeader) }) @@ -46,13 +46,13 @@ func TestValidate(t *testing.T) { t.Parallel() client := testutils.MockClient(&http.Response{ - Header: http.Header{StrictTransportSecurity: []string{"max-age=47; includeSubDomains; preload"}}}) + Header: http.Header{"Strict-Transport-Security": []string{"max-age=47; includeSubDomains; preload"}}}) h := NewHsts(client) actual, err := h.Validate(context.Background(), "test.com") assert.NoError(t, err) - assert.Equal(t, MaxAgeError, actual.Message) + assert.Equal(t, "HSTS max-age is less than 10886400.", actual.Message) assert.False(t, actual.Compatible) assert.Empty(t, actual.HSTSHeader) }) @@ -61,13 +61,13 @@ func TestValidate(t *testing.T) { t.Parallel() client := testutils.MockClient(&http.Response{ - Header: http.Header{StrictTransportSecurity: []string{"max-age=47474747; preload"}}}) + Header: http.Header{"Strict-Transport-Security": []string{"max-age=47474747; preload"}}}) h := NewHsts(client) actual, err := h.Validate(context.Background(), "test.com") assert.NoError(t, err) - assert.Equal(t, SubdomainsError, actual.Message) + assert.Equal(t, "HSTS header does not include all subdomains.", actual.Message) assert.False(t, actual.Compatible) assert.Empty(t, actual.HSTSHeader) }) @@ -76,13 +76,13 @@ func TestValidate(t *testing.T) { t.Parallel() client := testutils.MockClient(&http.Response{ - Header: http.Header{StrictTransportSecurity: []string{"max-age=47474747; includeSubDomains"}}}) + Header: http.Header{"Strict-Transport-Security": []string{"max-age=47474747; includeSubDomains"}}}) h := NewHsts(client) actual, err := h.Validate(context.Background(), "test.com") assert.NoError(t, err) - assert.Equal(t, PreloadError, actual.Message) + assert.Equal(t, "HSTS header does not contain the preload directive.", actual.Message) assert.False(t, actual.Compatible) assert.Empty(t, actual.HSTSHeader) }) @@ -91,13 +91,13 @@ func TestValidate(t *testing.T) { t.Parallel() client := testutils.MockClient(&http.Response{ - Header: http.Header{StrictTransportSecurity: []string{"max-age=47474747; includeSubDomains; preload"}}}) + Header: http.Header{"Strict-Transport-Security": []string{"max-age=47474747; includeSubDomains; preload"}}}) h := NewHsts(client) actual, err := h.Validate(context.Background(), "test.com") assert.NoError(t, err) - assert.Equal(t, HstsSuccess, actual.Message) + assert.Equal(t, "Site is compatible with the HSTS preload list!", actual.Message) assert.True(t, actual.Compatible) assert.NotEmpty(t, actual.HSTSHeader) }) @@ -111,7 +111,7 @@ func TestExtractMaxAgeFromHeader(t *testing.T) { header string expected string }{ - {"give valid header", "max-age=47474747; includeSubDomains; preload", "47474747"}, + {"give valid header", "max-age=47474747;", "47474747"}, {"given an empty header", "", ""}, } { tc := tc