Initial commit
This commit is contained in:
commit
542ebdea34
40 changed files with 4592 additions and 0 deletions
81
checker/rules_sri.go
Normal file
81
checker/rules_sri.go
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
// 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(&sriRule{}) }
|
||||
|
||||
// sriRule reports cross-origin <script>/<link> tags that lack an
|
||||
// integrity= attribute. Same-origin assets don't need SRI (the user
|
||||
// already trusts the origin to deliver them).
|
||||
type sriRule struct{}
|
||||
|
||||
func (r *sriRule) Name() string { return "http.sri" }
|
||||
func (r *sriRule) Description() string {
|
||||
return "Reports cross-origin script and stylesheet tags that are missing Subresource Integrity (integrity=) attributes."
|
||||
}
|
||||
|
||||
func (r *sriRule) Evaluate(ctx context.Context, obs sdk.ObservationGetter, _ sdk.CheckerOptions) []sdk.CheckState {
|
||||
data, errSt := loadHTTPData(ctx, obs)
|
||||
if errSt != nil {
|
||||
return []sdk.CheckState{*errSt}
|
||||
}
|
||||
|
||||
// Only the first HTTPS probe is parsed for HTML; that's the one we
|
||||
// evaluate here.
|
||||
var resources []HTMLResource
|
||||
var subject string
|
||||
for _, p := range data.Probes {
|
||||
if p.Scheme == "https" && len(p.Resources) > 0 {
|
||||
resources = p.Resources
|
||||
subject = p.Address
|
||||
break
|
||||
}
|
||||
}
|
||||
if subject == "" {
|
||||
return []sdk.CheckState{unknownState("http.sri.no_html", "No HTML body could be parsed for SRI evaluation.")}
|
||||
}
|
||||
|
||||
var missing []HTMLResource
|
||||
crossOriginTotal := 0
|
||||
for _, res := range resources {
|
||||
if !res.CrossOrigin {
|
||||
continue
|
||||
}
|
||||
crossOriginTotal++
|
||||
if res.Integrity == "" {
|
||||
missing = append(missing, res)
|
||||
}
|
||||
}
|
||||
|
||||
if crossOriginTotal == 0 {
|
||||
return []sdk.CheckState{passState("http.sri.no_cross_origin", "No cross-origin assets reference the page.")}
|
||||
}
|
||||
if len(missing) == 0 {
|
||||
return []sdk.CheckState{passState("http.sri.ok", fmt.Sprintf("All %d cross-origin assets carry integrity attributes.", crossOriginTotal))}
|
||||
}
|
||||
|
||||
var states []sdk.CheckState
|
||||
for _, res := range missing {
|
||||
states = append(states, sdk.CheckState{
|
||||
Status: sdk.StatusWarn,
|
||||
Code: "http.sri.missing",
|
||||
Subject: subject,
|
||||
Message: fmt.Sprintf("<%s> from %s lacks integrity= attribute", res.Tag, res.URL),
|
||||
Meta: map[string]any{
|
||||
"tag": res.Tag,
|
||||
"url": res.URL,
|
||||
"fix": "Generate an SRI hash and add `integrity=\"sha384-...\" crossorigin=\"anonymous\"`.",
|
||||
},
|
||||
})
|
||||
}
|
||||
return states
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue