-
-
Notifications
You must be signed in to change notification settings - Fork 115
feat(csp): patch CSP meta tags and update PatchHeaders signature #478
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughRefactors CSP patching to operate on the full *http.Response, adds streaming rewrite support for , returns (nonce, error), surfaces patch errors, and updates injector callsites and tests to use the new API and error handling. No exported type names changed; PatchHeaders signature changed. Changes
Sequence Diagram(s)sequenceDiagram
participant Injector
participant CSP as csp.PatchHeaders
participant Res as http.Response
participant Meta as meta tags
participant Headers as response headers
Injector->>CSP: PatchHeaders(Res, kind)
note right of CSP: generate nonce (if needed)
CSP->>Meta: scan & stream-rewrite <meta http-equiv="Content-Security-Policy">
alt meta patched
Meta-->>CSP: meta changed
else meta unchanged
Meta-->>CSP: no-op
end
CSP->>Headers: rewrite CSP header values via patchPolicies
alt any patch applied
Headers-->>CSP: headers changed
CSP-->>Injector: (nonce, nil)
Injector->>Injector: execute templates using nonce
else no patches
CSP-->>Injector: ("", nil)
Injector->>Injector: continue without nonce
end
opt error during patch
CSP-->>Injector: ("", error)
Injector-->>Injector: return wrapped error
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Areas to focus review on:
Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🧰 Additional context used🧠 Learnings (2)📚 Learning: 2025-09-05T11:40:45.127ZApplied to files:
📚 Learning: 2025-09-08T15:48:08.326ZApplied to files:
🧬 Code graph analysis (1)internal/csp/patch.go (1)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (1)
internal/extendedcss/injector.go (1)
97-100: Preserve error wrapping with%w.We’re standardizing on
%wso callers can unwrap the root cause. Please changefmt.Errorf("patch CSP headers: %v", err)to use%w, matching the other injectors.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
internal/cosmetic/injector.go(1 hunks)internal/csp/patch.go(4 hunks)internal/csp/patch_test.go(5 hunks)internal/cssrule/injector.go(1 hunks)internal/extendedcss/injector.go(1 hunks)internal/scriptlet/injector.go(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (6)
internal/csp/patch.go (1)
internal/httprewrite/rawbody.go (1)
StreamRewrite(27-46)
internal/extendedcss/injector.go (1)
internal/csp/patch.go (2)
PatchHeaders(31-51)InlineScript(24-24)
internal/cosmetic/injector.go (1)
internal/csp/patch.go (2)
PatchHeaders(31-51)InlineStyle(25-25)
internal/csp/patch_test.go (1)
internal/csp/patch.go (3)
PatchHeaders(31-51)InlineScript(24-24)InlineStyle(25-25)
internal/scriptlet/injector.go (1)
internal/csp/patch.go (2)
PatchHeaders(31-51)InlineScript(24-24)
internal/cssrule/injector.go (1)
internal/csp/patch.go (2)
PatchHeaders(31-51)InlineStyle(25-25)
anfragment
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello @kasyap1234, sorry for the late reply.
LGTM overall, just a few minor comments below.
| // In case of multiple lines/policies, the browsers will select the most restrictive one. | ||
| // For this reason, we modify each independently so they all allow the inline tag. | ||
| // See more: https://content-security-policy.com/examples/multiple-csp-headers/. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we preserve this, and the other comments within the function?
internal/csp/patch.go
Outdated
| var newValue string | ||
| if bestValue == "'none'" { | ||
| switch bestValue { | ||
| case "", "'none'": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe the "" case will never be triggered:
| case "", "'none'": | |
| case "'none'": |
internal/csp/patch.go
Outdated
| contentType := res.Header.Get("Content-Type") | ||
| if contentType == "" { | ||
| return false, nil | ||
| } | ||
|
|
||
| mediaType, _, err := mime.ParseMediaType(contentType) | ||
| if err != nil || !strings.EqualFold(mediaType, "text/html") { | ||
| return false, nil | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this is somewhat redundant in practice due to this check a couple levels above:
https://github.com/ZenPrivacy/zen-desktop/blob/master/internal/filter/filter.go#L313
| defer src.Close() | ||
|
|
||
| z := html.NewTokenizer(src) | ||
| for { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One potential performance optimization within the loop – since <meta http-equiv> can only be present in <head>, we can directly copy the remains of src to dst without the overhead of tokenization after we encounter </head> or <body>.
See an example here:
https://github.com/ZenPrivacy/zen-desktop/blob/master/internal/httprewrite/html.go#L56-L65
|
Hey @kasyap1234! Sorry for not notifying you earlier – we've transferred most of the Go packages from this repository to |
What does this PR do?
This PR adds support for patching Content-Security-Policy (CSP) directives defined in HTML
<meta http-equiv="Content-Security-Policy">tags, in addition to those set via HTTP headers.Previously,
csp.PatchHeadersonly handled CSPs in response headers, which caused injection failures on websites that define their CSPs using meta tags (e.g., LinkedIn).To fix this, the
PatchHeadersfunction now accepts a*http.Responseinstead ofhttp.Header, enabling unified handling of both header-based and meta-based CSPs.BREAKING CHANGE:
PatchHeaders(h http.Header, kind inlineKind) (nonce string)→PatchHeaders(res *http.Response, kind inlineKind) (string, error)How did you verify your code works?
<meta http-equiv="Content-Security-Policy">tags.What are the relevant issues?
Closes #442