From c091b9d1cabec334b1d054820827739861b1f920 Mon Sep 17 00:00:00 2001 From: Toby Chui Date: Mon, 7 Jul 2025 13:25:07 +0800 Subject: [PATCH] Added content security policy structure - Added content security policy header generators structure (current not in used) --- .../permissionpolicy/contentsecuritypolicy.go | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 src/mod/dynamicproxy/permissionpolicy/contentsecuritypolicy.go diff --git a/src/mod/dynamicproxy/permissionpolicy/contentsecuritypolicy.go b/src/mod/dynamicproxy/permissionpolicy/contentsecuritypolicy.go new file mode 100644 index 0000000..1de8e70 --- /dev/null +++ b/src/mod/dynamicproxy/permissionpolicy/contentsecuritypolicy.go @@ -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]) +}