Added content security policy structure

- Added content security policy header generators structure (current not in used)
This commit is contained in:
Toby Chui
2025-07-07 13:25:07 +08:00
parent 691cb603ce
commit c091b9d1ca

View File

@@ -0,0 +1,123 @@
package permissionpolicy
import (
"net/http"
"strings"
)
/*
Content Security Policy
This is a content security policy header modifier that changes
the request content security policy fields
author: tobychui
//TODO: intergrate this with the dynamic proxy module
*/
type ContentSecurityPolicy struct {
DefaultSrc []string `json:"default_src"`
ScriptSrc []string `json:"script_src"`
StyleSrc []string `json:"style_src"`
ImgSrc []string `json:"img_src"`
ConnectSrc []string `json:"connect_src"`
FontSrc []string `json:"font_src"`
ObjectSrc []string `json:"object_src"`
MediaSrc []string `json:"media_src"`
FrameSrc []string `json:"frame_src"`
WorkerSrc []string `json:"worker_src"`
ChildSrc []string `json:"child_src"`
ManifestSrc []string `json:"manifest_src"`
PrefetchSrc []string `json:"prefetch_src"`
FormAction []string `json:"form_action"`
FrameAncestors []string `json:"frame_ancestors"`
BaseURI []string `json:"base_uri"`
Sandbox []string `json:"sandbox"`
ReportURI []string `json:"report_uri"`
ReportTo []string `json:"report_to"`
UpgradeInsecureRequests bool `json:"upgrade_insecure_requests"`
BlockAllMixedContent bool `json:"block_all_mixed_content"`
}
// GetDefaultContentSecurityPolicy returns a ContentSecurityPolicy struct with default permissive settings
func GetDefaultContentSecurityPolicy() *ContentSecurityPolicy {
return &ContentSecurityPolicy{
DefaultSrc: []string{"*"},
ScriptSrc: []string{"*"},
StyleSrc: []string{"*"},
ImgSrc: []string{"*"},
ConnectSrc: []string{"*"},
FontSrc: []string{"*"},
ObjectSrc: []string{"*"},
MediaSrc: []string{"*"},
FrameSrc: []string{"*"},
WorkerSrc: []string{"*"},
ChildSrc: []string{"*"},
ManifestSrc: []string{"*"},
PrefetchSrc: []string{"*"},
FormAction: []string{"*"},
FrameAncestors: []string{"*"},
BaseURI: []string{"*"},
Sandbox: []string{},
ReportURI: []string{},
ReportTo: []string{},
UpgradeInsecureRequests: false,
BlockAllMixedContent: false,
}
}
// ToHeader converts a ContentSecurityPolicy struct into a CSP header key-value pair
func (csp *ContentSecurityPolicy) ToHeader() []string {
directives := []string{}
addDirective := func(name string, sources []string) {
if len(sources) > 0 {
directives = append(directives, name+" "+strings.Join(sources, " "))
}
}
addDirective("default-src", csp.DefaultSrc)
addDirective("script-src", csp.ScriptSrc)
addDirective("style-src", csp.StyleSrc)
addDirective("img-src", csp.ImgSrc)
addDirective("connect-src", csp.ConnectSrc)
addDirective("font-src", csp.FontSrc)
addDirective("object-src", csp.ObjectSrc)
addDirective("media-src", csp.MediaSrc)
addDirective("frame-src", csp.FrameSrc)
addDirective("worker-src", csp.WorkerSrc)
addDirective("child-src", csp.ChildSrc)
addDirective("manifest-src", csp.ManifestSrc)
addDirective("prefetch-src", csp.PrefetchSrc)
addDirective("form-action", csp.FormAction)
addDirective("frame-ancestors", csp.FrameAncestors)
addDirective("base-uri", csp.BaseURI)
if len(csp.Sandbox) > 0 {
directives = append(directives, "sandbox "+strings.Join(csp.Sandbox, " "))
}
if len(csp.ReportURI) > 0 {
addDirective("report-uri", csp.ReportURI)
}
if len(csp.ReportTo) > 0 {
addDirective("report-to", csp.ReportTo)
}
if csp.UpgradeInsecureRequests {
directives = append(directives, "upgrade-insecure-requests")
}
if csp.BlockAllMixedContent {
directives = append(directives, "block-all-mixed-content")
}
headerValue := strings.Join(directives, "; ")
return []string{"Content-Security-Policy", headerValue}
}
// InjectContentSecurityPolicyHeader injects the CSP header into the response
func InjectContentSecurityPolicyHeader(w http.ResponseWriter, csp *ContentSecurityPolicy) {
if csp == nil || w.Header().Get("Content-Security-Policy") != "" {
return
}
headerKV := csp.ToHeader()
w.Header().Set(headerKV[0], headerKV[1])
}