Initial commit
This commit is contained in:
commit
542ebdea34
40 changed files with 4592 additions and 0 deletions
64
checker/rules_wellknown.go
Normal file
64
checker/rules_wellknown.go
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
// This file is part of the happyDomain (R) project.
|
||||
// Copyright (c) 2020-2026 happyDomain
|
||||
// Authors: Pierre-Olivier Mercier, et al.
|
||||
|
||||
package checker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
sdk "git.happydns.org/checker-sdk-go/checker"
|
||||
)
|
||||
|
||||
func init() { RegisterRule(&securityTxtRule{}) }
|
||||
|
||||
// securityTxtRule reports whether /.well-known/security.txt is published
|
||||
// (RFC 9116). Absence is an Info, not a Warn: many sites legitimately
|
||||
// have no security disclosure pipeline, but it is now the expected place
|
||||
// for researchers to look first.
|
||||
type securityTxtRule struct{}
|
||||
|
||||
func (r *securityTxtRule) Name() string { return "http.security_txt" }
|
||||
func (r *securityTxtRule) Description() string {
|
||||
return "Reports whether /.well-known/security.txt (RFC 9116) is published."
|
||||
}
|
||||
|
||||
func (r *securityTxtRule) Evaluate(ctx context.Context, obs sdk.ObservationGetter, _ sdk.CheckerOptions) []sdk.CheckState {
|
||||
data, errSt := loadHTTPData(ctx, obs)
|
||||
if errSt != nil {
|
||||
return []sdk.CheckState{*errSt}
|
||||
}
|
||||
wk, ok, err := LoadExtension[WellKnownData](data, ObservationKeyWellKnown)
|
||||
if err != nil {
|
||||
return []sdk.CheckState{{Status: sdk.StatusError, Code: "http.security_txt.decode_error", Message: err.Error()}}
|
||||
}
|
||||
if !ok {
|
||||
return []sdk.CheckState{unknownState("http.security_txt.no_data", "Well-known collector did not run.")}
|
||||
}
|
||||
probe := wk.URIs["/.well-known/security.txt"]
|
||||
switch {
|
||||
case probe.StatusCode == 200 && probe.Bytes > 0:
|
||||
return []sdk.CheckState{{
|
||||
Status: sdk.StatusOK,
|
||||
Code: "http.security_txt.ok",
|
||||
Subject: data.Domain,
|
||||
Message: fmt.Sprintf("/.well-known/security.txt is published (%d bytes).", probe.Bytes),
|
||||
}}
|
||||
case probe.StatusCode == 200:
|
||||
return []sdk.CheckState{{
|
||||
Status: sdk.StatusWarn,
|
||||
Code: "http.security_txt.empty",
|
||||
Subject: data.Domain,
|
||||
Message: "/.well-known/security.txt responded 200 but is empty.",
|
||||
}}
|
||||
default:
|
||||
return []sdk.CheckState{{
|
||||
Status: sdk.StatusInfo,
|
||||
Code: "http.security_txt.missing",
|
||||
Subject: data.Domain,
|
||||
Message: fmt.Sprintf("/.well-known/security.txt is not published (status %d).", probe.StatusCode),
|
||||
Meta: map[string]any{"fix": "Publish /.well-known/security.txt per RFC 9116 (Contact:, Expires:, …)."},
|
||||
}}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue