From 2c2382e1fdcd193508f777acfca1d8dc39b6bbda Mon Sep 17 00:00:00 2001 From: Gunir <134402102+gunir@users.noreply.github.com> Date: Sat, 13 Dec 2025 15:55:06 +0700 Subject: [PATCH 1/3] Create csp.go - Implementing $csp from uBlockOrigin This PR implement a missing piece $csp modifier from uBO: https://github.com/gorhill/uBlock/wiki/Static-filter-syntax#csp Signed-off-by: Gunir <134402102+gunir@users.noreply.github.com> --- networkrules/rulemodifiers/csp.go | 44 +++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 networkrules/rulemodifiers/csp.go diff --git a/networkrules/rulemodifiers/csp.go b/networkrules/rulemodifiers/csp.go new file mode 100644 index 0000000..150a21e --- /dev/null +++ b/networkrules/rulemodifiers/csp.go @@ -0,0 +1,44 @@ +package rulemodifiers + +import ( + "errors" + "net/http" + "strings" +) + +type CSPModifier struct { + policy string +} + +var _ ModifyingModifier = (*CSPModifier)(nil) + +func (m *CSPModifier) Parse(modifier string) error { + if !strings.HasPrefix(modifier, "csp=") { + return errors.New("invalid csp modifier") + } + m.policy = strings.TrimPrefix(modifier, "csp=") + if m.policy == "" { + return errors.New("empty csp policy") + } + return nil +} + +func (m *CSPModifier) ModifyReq(req *http.Request) bool { + // CSP is a response header, so we do nothing to the request. + return false +} + +func (m *CSPModifier) ModifyRes(res *http.Response) (bool, error) { + // We use Add() instead of Set() because if the site already has a CSP, + // browsers enforce the "intersection" of all policies (most restrictive wins). + res.Header.Add("Content-Security-Policy", m.policy) + return true, nil +} + +func (m *CSPModifier) Cancels(modifier Modifier) bool { + other, ok := modifier.(*CSPModifier) + if !ok { + return false + } + return m.policy == other.policy +} From 104dd41eb973decdd1573b95cbd4677d9cf9f7af Mon Sep 17 00:00:00 2001 From: Gunir <134402102+gunir@users.noreply.github.com> Date: Sat, 13 Dec 2025 15:55:51 +0700 Subject: [PATCH 2/3] Update rule.go - Register csp modifier Signed-off-by: Gunir <134402102+gunir@users.noreply.github.com> --- networkrules/rule/rule.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/networkrules/rule/rule.go b/networkrules/rule/rule.go index 66e123f..d3998b9 100644 --- a/networkrules/rule/rule.go +++ b/networkrules/rule/rule.go @@ -83,6 +83,9 @@ func (rm *Rule) ParseModifiers(modifiers []string) error { modifier = &rulemodifiers.ScrambleJSModifier{} case isKind("jsonprune"): modifier = &rulemodifiers.JSONPruneModifier{} + // [NEW] Register the CSP Modifier + case isKind("csp"): + modifier = &rulemodifiers.CSPModifier{} case isKind("all"): // TODO: should act as "popup" modifier once it gets implemented continue From 1b8c81b679555c070402fe1c8857ee64e82ec29b Mon Sep 17 00:00:00 2001 From: Gunir <134402102+gunir@users.noreply.github.com> Date: Sat, 17 Jan 2026 10:19:47 +0700 Subject: [PATCH 3/3] Update networkrules/rule/rule.go Co-authored-by: Ansar Smagul Signed-off-by: Gunir <134402102+gunir@users.noreply.github.com> --- networkrules/rule/rule.go | 1 - 1 file changed, 1 deletion(-) diff --git a/networkrules/rule/rule.go b/networkrules/rule/rule.go index d3998b9..6a6c1f4 100644 --- a/networkrules/rule/rule.go +++ b/networkrules/rule/rule.go @@ -83,7 +83,6 @@ func (rm *Rule) ParseModifiers(modifiers []string) error { modifier = &rulemodifiers.ScrambleJSModifier{} case isKind("jsonprune"): modifier = &rulemodifiers.JSONPruneModifier{} - // [NEW] Register the CSP Modifier case isKind("csp"): modifier = &rulemodifiers.CSPModifier{} case isKind("all"):