Skip to content

Implement cache busting#43

Merged
anfragment merged 20 commits intomasterfrom
anfragment/cache-busting
Feb 1, 2026
Merged

Implement cache busting#43
anfragment merged 20 commits intomasterfrom
anfragment/cache-busting

Conversation

@anfragment
Copy link
Member

@anfragment anfragment commented Jan 29, 2026

What does this PR do?

  • Reworks page injections to use remote <script> and <link> tags instead of inline elements, enabling instant cache invalidation.
  • Refactors injections to inject all assets through asset.Engine, which manages downstream asset stores.
  • Introduces asset.Server, which hosts the injected assets on a local HTTPS server.

How did you verify your code works?

Manual testing in Zen.

What are the relevant issues?

Resolves #39.

@coderabbitai
Copy link

coderabbitai bot commented Jan 29, 2026

Walkthrough

Adds an HTTPS asset server and Engine, shifts injector APIs from in-place HTML injection to per-host asset retrieval (GetAsset), centralizes document injection via a new documentInjector, converts CSP patching to a batch API with per-resource nonces, adjusts certificate generation for IP vs DNS, updates PAC, fixes an import path, and removes several injector tests.

Changes

Cohort / File(s) Summary
Asset server & engine
asset/asset.go, asset/engine.go, asset/server.go
Adds an Engine (NewEngine, AddRule, Inject, Resolve) and a TLS HTTPS Server (NewServer, ListenAndServe, Stop, ServeHTTP) to serve assets by Referer, set content-type/cache headers, and resolve assets via engine.
Injector API refactor (GetAsset)
internal/asset/scriptlet/injector.go, internal/asset/jsrule/injector.go, internal/asset/cssrule/injector.go, internal/asset/cosmetic/injector.go, internal/asset/extendedcss/injector.go
Replaces per-request Inject(req,res) with GetAsset(hostname) returning bytes/errors; removes in-place CSP/meta patching and HTML template injection; bundles converted to raw bytes where applicable.
Filter consolidation
filter/filter.go
Introduces documentInjector interface, replaces multiple injector fields with a single injector in Filter, updates NewFilter signature, and delegates AddRule/Inject handling to unified injector.
CSP batch patching
csp/patch.go, csp/patch_test.go, csp/meta.go
Refactors CSP to PatchOperation and PatchHeadersBatch, adds NewNonce(), replaces inlineKind with exported Script/Style, and updates header/meta patching to process multiple operations and safer nonce/URL insertion; tests updated.
Certificate generation
certgen/get.go
GetCertificate now distinguishes IP vs DNS: sets template.IPAddresses for IP hosts and template.DNSNames for domain hosts.
PAC & proxy
sysproxy/pac.go
PAC template now early-returns DIRECT for localhost/127.0.0.1/::1 to bypass proxying.
Import path fix
internal/asset/cosmetic/cosmetic.go
Switched extendedcss import from public module path to internal package path.
Tests removed
cosmetic/injector_test.go, cssrule/injector_test.go, scriptlet/injector_test.go
Deleted injector tests that validated CSP/nonce wiring and HTML injection behavior.
Misc
asset/asset.go
Adds a small package constant (host = "127.0.0.1").

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • spellcascade
🚥 Pre-merge checks | ✅ 3 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Out of Scope Changes check ❓ Inconclusive Most changes align with issue #39 objectives, but some modifications appear peripherally related: test file removals, CSP batch patching refactors, and sysproxy PAC changes lack clear connection to cache busting goals. Clarify whether test removals (cosmetic/cssrule/scriptlet tests) and sysproxy PAC localhost bypass changes are intentional refactoring or potentially out-of-scope.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Implement cache busting' directly and clearly summarizes the main objective of the PR - implementing cache busting through external asset injection.
Description check ✅ Passed The description covers all required template sections: clearly explains the purpose (reworks injections for cache invalidation), describes testing approach (manual testing), and links the relevant issue (#39).
Linked Issues check ✅ Passed The PR implements all objectives from issue #39: uses external resources via asset.Server on port 26514 with HTTPS, implements referer-based asset selection, sets Cache-Control headers, and refactors injections through asset.Engine.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch anfragment/cache-busting

🧹 Recent nitpick comments
asset/server.go (1)

156-157: Consider handling the w.Write error.

The error return from w.Write(body) is discarded. While this is common in HTTP handlers (the client may have disconnected), logging the error could help diagnose issues in production.

♻️ Proposed fix
 	w.WriteHeader(http.StatusOK)
-	w.Write(body)
+	if _, err := w.Write(body); err != nil {
+		log.Printf("assetserver: failed to write response body: %v", err)
+	}
📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0cf134e and bf09595.

📒 Files selected for processing (1)
  • asset/server.go
🧰 Additional context used
🧬 Code graph analysis (1)
asset/server.go (1)
asset/engine.go (1)
  • Engine (39-51)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Lint Go (windows-latest)
🔇 Additional comments (5)
asset/server.go (5)

1-13: LGTM!

Clean import block with only necessary standard library packages.


15-17: LGTM!

Clean interface definition enabling dependency injection for certificate generation.


19-25: LGTM!

Well-encapsulated struct with appropriate fields for managing the HTTPS server.


81-88: LGTM!

Defensive nil checks and graceful shutdown via context are good practices.


98-106: Origin fallback properly addresses stripped Referer scenarios.

The implementation correctly falls back to the Origin header when Referer is absent, handling pages with Referrer-Policy: no-referrer or browser extensions that strip the header.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@anfragment anfragment marked this pull request as draft January 29, 2026 22:52
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@certgen/get.go`:
- Around line 56-60: Normalize the host inside GetCertificate before IP
detection: strip IPv6 brackets and any port (use net.SplitHostPort with fallback
to trim surrounding '[' ']' for IPv6) then run net.ParseIP on the cleaned host
so SANs are valid; assign template.IPAddresses for parsed IPs and
template.DNSNames for the cleaned hostname. Also fix the undefined variable in
the TLS callback in asset/server.go by extracting the hostname from the
*tls.ClientHelloInfo parameter (use its ServerName field) instead of referencing
a non-existent host variable.

In `@sysproxy/pac.go`:
- Around line 11-14: The PAC template created in template.New("pac").Parse (the
FindProxyForURL function) only bypasses proxy for "127.0.0.1" and "localhost"
and should also treat all 127/8 IPv4 loopback addresses and the IPv6 loopback as
DIRECT; update the PAC logic to (1) normalize the host (strip brackets for IPv6
literals and lower-case), (2) check IPv6 loopback (e.g., host === "::1" or host
=== "[::1]"), and (3) use isInNet(host, "127.0.0.0", "255.0.0.0") to cover the
whole 127/8 range before falling back to other proxy rules in FindProxyForURL so
local services on 127.x.x.x or ::1 are not proxied.
🧹 Nitpick comments (5)
asset/server.go (3)

76-80: Use errors.Is for error comparison.

The comparison err != http.ErrServerClosed should use errors.Is to properly handle wrapped errors.

♻️ Proposed fix
 go func() {
-	if err := s.httpServer.Serve(ln); err != nil && err != http.ErrServerClosed {
+	if err := s.httpServer.Serve(ln); err != nil && !errors.Is(err, http.ErrServerClosed) {
 		log.Printf("assetserver: error serving: %v", err)
 	}
 }()

132-133: Consider handling w.Write error.

The error returned by w.Write is ignored. While failures here are typically unrecoverable (client disconnected), logging at debug level could aid troubleshooting.

♻️ Proposed fix
 w.WriteHeader(http.StatusOK)
-w.Write(body)
+if _, err := w.Write(body); err != nil {
+	log.Printf("assetserver: write error for %q: %v", r.URL.Path, err)
+}

62-66: The GetCertificate callback ignores ClientHelloInfo.

The callback always generates a certificate for the fixed host constant, ignoring the actual ServerName from the TLS handshake. This is likely intentional since the asset server only serves on one host, but consider adding a comment to clarify this design choice.

asset/engine.go (2)

117-122: Consider using html/template for safer HTML construction.

While the current implementation is likely safe (nonces are internally generated, URLs are from constants), using html/template would provide automatic escaping and be more resilient to future changes.

♻️ Suggested approach
// Alternative using html/template for automatic escaping
import "html/template"

var injectionTmpl = template.Must(template.New("injection").Parse(
	`<script nonce="{{.ScriptNonce}}" src="{{.ScriptletsURL}}"></script>` +
	`<script nonce="{{.ScriptNonce}}" src="{{.JsRuleURL}}"></script>` +
	// ... etc
))

139-156: Simplify error-returning branches in Resolve.

The else branches explicitly return err which is always nil at that point. Consider restructuring for clarity.

♻️ Proposed fix
 case scriptletsPath:
-	if body, err = e.scriptlets.GetAsset(hostname); err != nil {
+	body, err = e.scriptlets.GetAsset(hostname)
+	if err != nil {
 		return "", nil, fmt.Errorf("scriptlets asset: %w", err)
-	} else {
-		return "application/javascript; charset=utf-8", body, err
 	}
+	return "application/javascript; charset=utf-8", body, nil
 case extendedCSSPath:
-	if body, err = e.extendedCSS.GetAsset(hostname); err != nil {
+	body, err = e.extendedCSS.GetAsset(hostname)
+	if err != nil {
 		return "", nil, fmt.Errorf("extended CSS asset: %w", err)
-	} else {
-		return "application/javascript; charset=utf-8", body, err
 	}
+	return "application/javascript; charset=utf-8", body, nil
 case jsRulePath:
-	if body, err = e.jsRules.GetAsset(hostname); err != nil {
+	body, err = e.jsRules.GetAsset(hostname)
+	if err != nil {
 		return "", nil, fmt.Errorf("js rules: %w", err)
-	} else {
-		return "application/javascript; charset=utf-8", body, err
 	}
+	return "application/javascript; charset=utf-8", body, nil
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 88c60ae and 6e58be0.

📒 Files selected for processing (26)
  • asset/asset.go
  • asset/engine.go
  • asset/server.go
  • certgen/get.go
  • cosmetic/injector_test.go
  • cssrule/injector_test.go
  • filter/filter.go
  • internal/asset/cosmetic/cosmetic.go
  • internal/asset/cosmetic/injector.go
  • internal/asset/cosmetic/sanitizer.go
  • internal/asset/cosmetic/sanitizer_test.go
  • internal/asset/cssrule/injector.go
  • internal/asset/extendedcss/bundle.js
  • internal/asset/extendedcss/extendedcss.go
  • internal/asset/extendedcss/injector.go
  • internal/asset/jsrule/injector.go
  • internal/asset/scriptlet/addrule.go
  • internal/asset/scriptlet/arglist.go
  • internal/asset/scriptlet/arglist_test.go
  • internal/asset/scriptlet/argsplit.go
  • internal/asset/scriptlet/argsplit_test.go
  • internal/asset/scriptlet/bundle.js
  • internal/asset/scriptlet/injector.go
  • internal/asset/scriptlet/injector_internal_test.go
  • scriptlet/injector_test.go
  • sysproxy/pac.go
💤 Files with no reviewable changes (3)
  • scriptlet/injector_test.go
  • cssrule/injector_test.go
  • cosmetic/injector_test.go
🧰 Additional context used
🧬 Code graph analysis (3)
internal/asset/cssrule/injector.go (4)
internal/asset/cosmetic/injector.go (1)
  • Injector (25-27)
internal/asset/extendedcss/injector.go (1)
  • Injector (32-37)
internal/asset/jsrule/injector.go (1)
  • Injector (19-21)
internal/asset/scriptlet/injector.go (1)
  • Injector (26-31)
internal/asset/scriptlet/injector.go (4)
internal/asset/cosmetic/injector.go (1)
  • Injector (25-27)
internal/asset/cssrule/injector.go (1)
  • Injector (26-28)
internal/asset/extendedcss/injector.go (1)
  • Injector (32-37)
internal/asset/jsrule/injector.go (1)
  • Injector (19-21)
internal/asset/jsrule/injector.go (4)
internal/asset/cosmetic/injector.go (1)
  • Injector (25-27)
internal/asset/cssrule/injector.go (1)
  • Injector (26-28)
internal/asset/extendedcss/injector.go (1)
  • Injector (32-37)
internal/asset/scriptlet/injector.go (1)
  • Injector (26-31)
🔇 Additional comments (13)
asset/asset.go (1)

1-3: LGTM: clear internal host constant.

internal/asset/cosmetic/cosmetic.go (1)

3-7: LGTM: internal import path aligns with refactor.

internal/asset/cosmetic/injector.go (1)

57-67: LGTM: clean asset retrieval API.

internal/asset/cssrule/injector.go (1)

54-64: LGTM: asset retrieval looks good.

internal/asset/scriptlet/injector.go (1)

53-72: LGTM: scriptlet asset builder is clear and consistent.

internal/asset/jsrule/injector.go (1)

28-30: LGTM: IIFE wrapping and asset return are consistent.

Also applies to: 56-75

internal/asset/extendedcss/injector.go (1)

78-98: LGTM!

The GetAsset method correctly handles the case when no rules exist by returning (nil, nil), and properly builds the JavaScript asset by concatenating the bundle with a self-executing function that calls window.extendedCSS with JSON-encoded rules. The use of json.Marshal ensures proper escaping of the rules string.

filter/filter.go (3)

35-39: Clean interface abstraction.

The consolidation into a single documentInjector interface simplifies the Filter's dependencies and provides a clear contract for rule handling and injection.


114-124: LGTM!

The delegation pattern is correct: try the injector first, and if it doesn't handle the rule (handled == false), fall back to parsing as a network rule. Error propagation is appropriate.


179-182: LGTM!

Treating injection errors as recoverable and logging them while continuing response processing is the right approach—asset injection failures shouldn't block the user from receiving the response.

asset/engine.go (2)

44-71: LGTM - Clean constructor with proper error handling.

The constructor properly initializes all injectors and constructs asset URLs. The use of url.Parse followed by JoinPath is a safe way to build URLs.


74-104: LGTM - Well-structured rule dispatch.

The switch-based rule dispatch is clear and correctly gates cssrule and jsrule behind filterListTrusted for security. Each case returns (true, nil) on success or (true, err) on failure, properly indicating the rule was handled.

asset/server.go (1)

43-43: Remove the concern about undefined host variable—it is properly defined.

The host constant is defined at asset/asset.go:3 as a package-level constant (const host = "127.0.0.1"), making it accessible throughout the asset package. Line 43 correctly references this constant.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@anfragment anfragment self-assigned this Jan 31, 2026
@anfragment anfragment marked this pull request as ready for review January 31, 2026 13:57
Copy link

@coderabbitai coderabbitai bot left a 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

🤖 Fix all issues with AI agents
In `@asset/server.go`:
- Around line 56-78: The ListenAndServe docstring says it blocks but the
implementation spawns a goroutine and returns immediately; change it so the
method actually blocks by removing the goroutine and invoking
s.httpServer.Serve(ln) directly and returning its error (handle
http.ErrServerClosed the same way as in the goroutine before returning), or
alternatively update the comment to reflect non-blocking behavior—make the
change in Server.ListenAndServe where tlsConfig, ln, and the call to
s.httpServer.Serve(ln) are used.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6e58be0 and 56402c4.

📒 Files selected for processing (7)
  • asset/engine.go
  • asset/server.go
  • csp/meta.go
  • csp/patch.go
  • csp/patch_test.go
  • filter/filter.go
  • sysproxy/pac.go
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2026-01-29T18:08:27.308Z
Learnt from: anfragment
Repo: ZenPrivacy/zen-core PR: 40
File: filter/filter.go:209-212
Timestamp: 2026-01-29T18:08:27.308Z
Learning: Filter list rules in ad-blocking filter lists (e.g., EasyList, uBlock Origin lists) are typically short and don't exceed 300 characters in length. The default bufio.Scanner buffer size (64KB) is sufficient for parsing these rules without needing to be increased.

Applied to files:

  • filter/filter.go
🧬 Code graph analysis (3)
filter/filter.go (3)
networkrules/networkrules.go (1)
  • New (31-36)
filter/whitelistserver/server.go (1)
  • New (22-24)
internal/redacted/redacted_prod.go (1)
  • Redacted (8-10)
asset/server.go (1)
asset/engine.go (1)
  • Engine (39-51)
csp/meta.go (1)
csp/patch.go (1)
  • PatchOperation (24-28)
🔇 Additional comments (9)
sysproxy/pac.go (1)

11-18: Local loopback bypass coverage looks complete.
Covers localhost variants, IPv6 loopback, and 127/8 as intended.

csp/meta.go (1)

14-75: Batch meta CSP patching reads clean.
Sequential operations with a “changed” guard avoid unnecessary meta rewrites.

csp/patch_test.go (1)

11-75: Tests align with batch CSP patching.
Nonce insertion, unsafe-inline URL inclusion, and meta/header scenarios are all exercised.

Also applies to: 131-133, 174-177, 208-212, 240-243

filter/filter.go (2)

41-90: Injector consolidation and nil-guards look good.
The unified interface and constructor checks make the injection path clearer and safer.


223-234: Injection flow delegation is clear.
Rules are routed through the injector first, and injection errors are treated as recoverable.

Also applies to: 287-291

csp/patch.go (2)

30-48: Batch CSP patching flow and safeNonce logic look consistent.
The per-operation patching and directive prioritization read well.

Also applies to: 61-126, 137-193


50-58: No changes needed – crypto/rand.Read() never returns errors.

Per Go's design, rand.Read() is specified to always fill the buffer and never return an error. If the underlying OS RNG fails, rand.Read() crashes the program irrecoverably rather than returning an error. Error handling at the call site is unnecessary and not meaningful. The current implementation is correct.

Likely an incorrect or invalid review comment.

asset/engine.go (1)

53-147: Engine wiring and CSP patch ops look cohesive.
Centralized injector routing plus batched CSP patching is clean.

asset/server.go (1)

90-162: ServeHTTP flow and headers look good.
Method checks, referer parsing, and Cache-Control: no-store align with the cache-busting design.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

spellcascade
spellcascade previously approved these changes Jan 31, 2026
Copy link
Member

@spellcascade spellcascade left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. I've left a minor comment, it's up to you

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@asset/server.go`:
- Around line 90-100: The ServeHTTP method on Server currently sets overly
permissive CORS headers (Access-Control-Allow-Origin: "*",
Access-Control-Allow-Headers: "*", Access-Control-Allow-Methods: "GET, OPTIONS")
which allows any site to read asset contents; update ServeHTTP to remove or
restrict these headers (remove the wildcard headers or replace with a
configurable trusted-origin check) and preserve only necessary behavior for
OPTIONS preflight handling in ServeHTTP so normal <script>/<link> asset loading
still works without exposing asset contents to all origins.

In `@csp/patch.go`:
- Around line 30-47: The doc comment for PatchHeadersBatch is incorrect: it
claims the function "Returns the generated patch operations with nonces" whereas
PatchHeadersBatch(res *http.Response, operations []PatchOperation) only consumes
the provided operations and returns an error. Update the comment above
PatchHeadersBatch to accurately describe that it mutates CSP headers and meta
tags for multiple resources using the supplied operations (type PatchOperation)
and returns an error if patchMetaCSPsBatch fails, removing any wording that
implies it returns operations or nonces.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 56402c4 and af9ede2.

📒 Files selected for processing (2)
  • asset/server.go
  • csp/patch.go
🧰 Additional context used
🧬 Code graph analysis (1)
asset/server.go (1)
asset/engine.go (1)
  • Engine (39-51)
🔇 Additional comments (9)
csp/patch.go (7)

16-28: Clear Script/Style tagging and PatchOperation shape.
The exported constants and structured operation payload make call sites explicit.


61-74: LGTM: header patching keeps multi-value headers intact.
The delete-and-readd flow preserves multiple header values cleanly.


76-125: LGTM: directive selection and token append logic are clear.
The specificity selection plus appendToken usage reads well.


136-150: LGTM: safeNonce preserves semantics when unsafe-inline is present.
This avoids inadvertently changing CSP behavior.


163-169: LGTM: appendToken handles empty/'none' lists correctly.
Simple and predictable behavior.


171-192: LGTM: directive priority matches script/style specificity.
The ordering logic looks correct for elem vs fallback directives.


50-58: The review comment is based on an incorrect premise about crypto/rand.Read behavior.

According to Go's crypto/rand documentation, Read() does not return an error in normal operation. The docs explicitly state: "Read fills b … It never returns an error, and always fills b entirely." If an underlying read failure occurs on legacy systems, the process will panic rather than return an error. Therefore, ignoring the error return value is not a security concern—there is no error to handle in practical scenarios.

The current code is correct as-is. The proposed change to return (string, error) would add unnecessary complexity and require updating call sites in asset/engine.go and test files without providing any actual safety benefit.

Likely an incorrect or invalid review comment.

asset/server.go (2)

62-79: TLS listener setup looks good.

Min TLS version and dedicated listener with http.Server.Serve is solid.


81-88: Graceful shutdown guard is fine.

Nil checks and Shutdown(ctx) are appropriate.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Copy link

@coderabbitai coderabbitai bot left a 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

🤖 Fix all issues with AI agents
In `@csp/patch.go`:
- Around line 49-57: Change NewNonce to return (string, error) and handle the
error from rand.Read: in func NewNonce() call rand.Read(b[:]) and if it returns
a non-nil error return "", err, otherwise return the base64 nonce and nil; then
update all call sites to propagate the error—specifically update the Inject
method in asset/engine.go to accept and forward the nonce error (Inject already
returns error) and modify the five places it calls NewNonce to handle the error,
and update the nine test call sites in csp/patch_test.go to handle the new
(string, error) result (fail the test or use t.Fatal on error).
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between af9ede2 and 1c762d2.

📒 Files selected for processing (1)
  • csp/patch.go
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Lint Go (windows-latest)
🔇 Additional comments (6)
csp/patch.go (6)

16-28: LGTM: tagKind and PatchOperation are clear and aligned with batch patching.


30-47: LGTM: batch header patching flow is straightforward.


60-124: LGTM: per-operation header policy patching is consistent.


135-149: LGTM: safeNonce logic is aligned with CSP3 precedence.


162-168: LGTM: appendToken handles 'none' correctly.


170-191: LGTM: directive priority ordering is sensible.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

CORS is only triggered by a specific subset of cross-origin requests. <style> and <link> tags do not trigger CORS: https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS#what_requests_use_cors
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@asset/server.go`:
- Around line 27-40: The NewServer function references an undefined host
variable when building addr and later certificate selection; update NewServer to
accept a host parameter (e.g., add host string to the signature of NewServer)
and use that host when calling net.JoinHostPort and when passing values to
certGenerator-related calls (keep checks for port, engine, certGenerator
intact); update all callers of NewServer to provide the host argument so
compilation and correct cert selection succeed.
- Around line 98-107: The handler currently rejects requests when r.Referer() is
empty; instead, fall back to using the Origin request header before returning
400: if r.Referer() is empty, read raw = r.Header.Get("Origin") and if that is
non-empty parse it into refererURL (same variable) and handle parse errors
similarly (log with raw and return invalid referer); only return missing referer
error if both Referer and Origin are absent or Origin parse fails. Update the
code paths that reference refererURL so they work unchanged when Origin was
used, and add/adjust tests to verify behavior when Referer is stripped but
Origin is present.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1c762d2 and 0cf134e.

📒 Files selected for processing (1)
  • asset/server.go
🧰 Additional context used
🧬 Code graph analysis (1)
asset/server.go (2)
asset/engine.go (1)
  • Engine (39-51)
internal/ruletree/byteset/byteset.go (1)
  • Set (4-4)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Lint Go (windows-latest)
🔇 Additional comments (2)
asset/server.go (2)

15-25: Clean interface + struct definition.
Looks good and keeps the server state tight.


81-88: Stop implementation is safe and minimal.
Nil checks + graceful shutdown are solid.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Copy link
Member

@spellcascade spellcascade left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@anfragment anfragment merged commit eeaf873 into master Feb 1, 2026
15 checks passed
@anfragment anfragment deleted the anfragment/cache-busting branch February 1, 2026 16:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cache busting

2 participants