Skip to content

Commit b9547a8

Browse files
authored
Allow tidewave.ai in CSP if toolbar is enabled (#254)
1 parent 452645b commit b9547a8

2 files changed

Lines changed: 31 additions & 7 deletions

File tree

lib/tidewave.ex

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,25 +87,34 @@ defmodule Tidewave do
8787
defp maybe_rewrite_csp(conn) do
8888
case Plug.Conn.get_resp_header(conn, "content-security-policy") do
8989
[csp | _] ->
90-
csp = rewrite_csp(csp)
90+
csp = rewrite_csp(conn, csp)
9191
Plug.Conn.put_resp_header(conn, "content-security-policy", csp)
9292

9393
_ ->
9494
conn
9595
end
9696
end
9797

98-
defp rewrite_csp(csp) do
98+
defp rewrite_csp(conn, csp) do
9999
policy_directives = String.split(csp, ";", trim: true)
100100

101+
toolbar_host =
102+
case conn.private.tidewave_config do
103+
%{toolbar: true} ->
104+
Application.get_env(:tidewave, :client_url, "https://tidewave.ai") <> " "
105+
106+
_ ->
107+
""
108+
end
109+
101110
for policy_directive <- policy_directives,
102111
policy_directive = String.trim(policy_directive),
103112
not String.starts_with?(policy_directive, "frame-ancestors") do
104113
case String.split(policy_directive, " ", parts: 2) do
105114
["script-src", directives] ->
106115
case :binary.match(directives, "'unsafe-eval'") do
107-
:nomatch -> "script-src 'unsafe-eval' #{directives}"
108-
_ -> "script-src #{directives}"
116+
:nomatch -> "script-src #{toolbar_host}'unsafe-eval' #{directives}"
117+
_ -> "script-src #{toolbar_host}#{directives}"
109118
end
110119

111120
[policy, directives] ->

test/tidewave_test.exs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,21 +114,36 @@ defmodule TidewaveTest do
114114
assert Plug.Conn.get_resp_header(conn, "x-frame-options") == []
115115
end
116116

117-
test "updates CSP header if set" do
117+
test "updates CSP header if set (no toolbar)" do
118118
conn =
119119
conn(:get, "/foo")
120120
|> Plug.Conn.put_resp_header(
121121
"content-security-policy",
122122
"default-src 'self' http://example.com; connect-src 'none'; script-src 'self'; frame-ancestors 'none'"
123123
)
124-
|> Tidewave.call(Tidewave.init([]))
124+
|> Tidewave.call(Tidewave.init(toolbar: false))
125125
|> Plug.Conn.send_resp(200, "foo")
126126

127127
assert Plug.Conn.get_resp_header(conn, "content-security-policy") == [
128128
"default-src 'self' http://example.com; connect-src 'none'; script-src 'unsafe-eval' 'self'"
129129
]
130130
end
131131

132+
test "updates CSP header if set (toolbar)" do
133+
conn =
134+
conn(:get, "/foo")
135+
|> Plug.Conn.put_resp_header(
136+
"content-security-policy",
137+
"default-src 'self' http://example.com; connect-src 'none'; script-src 'self'; frame-ancestors 'none'"
138+
)
139+
|> Tidewave.call(Tidewave.init(toolbar: true))
140+
|> Plug.Conn.send_resp(200, "foo")
141+
142+
assert Plug.Conn.get_resp_header(conn, "content-security-policy") == [
143+
"default-src 'self' http://example.com; connect-src 'none'; script-src https://tidewave.ai 'unsafe-eval' 'self'"
144+
]
145+
end
146+
132147
test "updates CSP headers with flags and trailing space" do
133148
conn =
134149
conn(:get, "/foo")
@@ -140,7 +155,7 @@ defmodule TidewaveTest do
140155
|> Plug.Conn.send_resp(200, "foo")
141156

142157
assert Plug.Conn.get_resp_header(conn, "content-security-policy") ==
143-
["upgrade-insecure-requests; script-src 'unsafe-eval' 'self'; "]
158+
["upgrade-insecure-requests; script-src https://tidewave.ai 'unsafe-eval' 'self'; "]
144159
end
145160

146161
describe "/mcp" do

0 commit comments

Comments
 (0)