Skip to content

Commit 8089b61

Browse files
committed
fix: CSP and script-tag for Matomo analytics and AdSense
script-tag only destructured :src and :nonce, silently dropping extra attributes like :async and :crossorigin needed by the AdSense tag. Changed to pass through all attributes. CSP connect-src blocked Matomo tracker requests to t.dungeonmastersvault.com and frame-src (defaulting to 'self') blocked Google ad iframes. Added the required domains to connect-src and frame-src. https://claude.ai/code/session_011qVDwDfCBzuUQSLFff1V66
1 parent 5773332 commit 8089b61

3 files changed

Lines changed: 21 additions & 5 deletions

File tree

src/clj/orcpub/csp.clj

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
The resulting CSP:
3131
- Uses 'strict-dynamic' for script-src (only nonced scripts execute)
3232
- Allows Google Fonts for styles and fonts
33+
- Allows Matomo analytics (connect-src, img-src)
34+
- Allows Google AdSense iframes (frame-src)
3335
- Restricts all other sources to 'self'
3436
- Blocks object embeds, restricts base-uri, frame-ancestors, and form-action"
3537
[nonce & {:keys [dev-mode?]}]
@@ -38,7 +40,9 @@
3840
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; "
3941
"font-src 'self' https://fonts.gstatic.com; "
4042
"img-src 'self' data: https:; "
41-
"connect-src 'self'" (when dev-mode? " ws://localhost:3449") "; "
43+
"connect-src 'self' https://t.dungeonmastersvault.com https://pagead2.googlesyndication.com"
44+
(when dev-mode? " ws://localhost:3449") "; "
45+
"frame-src 'self' https://googleads.g.doubleclick.net https://tpc.googlesyndication.com; "
4246
"object-src 'none'; "
4347
"base-uri 'self'; "
4448
"frame-ancestors 'self'; "

src/clj/orcpub/index.clj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@
2121

2222
(defn script-tag
2323
"Generate a script tag with optional nonce for CSP strict mode.
24-
For external scripts, pass :src. For inline scripts, pass content as body."
25-
[{:keys [src nonce]} & body]
26-
(let [attrs (cond-> {}
27-
src (assoc :src src)
24+
For external scripts, pass :src. For inline scripts, pass content as body.
25+
Extra attributes (e.g. :async, :crossorigin) are passed through to the tag."
26+
[{:keys [nonce] :as opts} & body]
27+
(let [attrs (cond-> (dissoc opts :nonce)
2828
nonce (assoc :nonce nonce))]
2929
(if (seq body)
3030
(into [:script attrs] body)

test/clj/orcpub/csp_test.clj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,18 @@
4343
(is (str/includes? header "form-action 'self'")
4444
"Should restrict form-action")))
4545

46+
(testing "Header allows Matomo analytics"
47+
(let [header (csp/build-csp-header "test-nonce")]
48+
(is (str/includes? header "https://t.dungeonmastersvault.com")
49+
"connect-src should allow Matomo tracker")))
50+
51+
(testing "Header allows AdSense iframes"
52+
(let [header (csp/build-csp-header "test-nonce")]
53+
(is (str/includes? header "https://googleads.g.doubleclick.net")
54+
"frame-src should allow Google ad iframes")
55+
(is (str/includes? header "https://tpc.googlesyndication.com")
56+
"frame-src should allow Google syndication iframes")))
57+
4658
(testing "Production mode does not include WebSocket"
4759
(let [header (csp/build-csp-header "test")]
4860
(is (not (str/includes? header "ws://"))

0 commit comments

Comments
 (0)