Open Darth-Knoppix opened 10 months ago
+1 to this. My app is complaining rather verbosely in the chrome console when I load a page with a live svelte component on it
Couple of question:
style
and script
tags (might as well do the main div tag too) solve this issue? This would mean you'd have to pass it manually every time for every Svelte componentGood questions, generating a nonce seems easy enough with:
# endpoint.ex
defmodule MyApp.Endpoint do
use Phoenix.Endpoint, otp_app: :myapp
defp generate_nonce() do
:crypto.strong_rand_bytes(16) |> Base.encode64()
end
plug Plug.Static,
at: "/",
from: :myapp,
gzip: false,
only: MyAppWeb.static_paths(),
headers: %{
"content-security-policy" =>
"default-src 'self'; style-src 'self' 'nonce-" <> generate_nonce() <> "';"
}
end
but passing that to the svelte component is another matter. I wonder though, can it be assigned to the socket
? which is always being passed in 🤔
I don't know why this has cropped up for me all of a sudden. I had my first test app with live_svelte, a fairly sophisticated svelte component doing an address search / autocomplete. I was really impressed, you have created a great tool that fills a gap IMO.
Then I brought that svelte component into a bigger, more serious app which is the one that is complaining. I am going to investigate if there is a package / configuration that has a higher level of paranoia.
In fact, the third party javascript I am calling in inside my svelte, won't even load:
The component:
<script>
import { onMount } from 'svelte'
import placekitAutocomplete from '@placekit/autocomplete-js'
export let live
export let apiKey
export let placeHolder
export let defaultValue
let pk
let input
onMount(() => {
if (!placeHolder) {
placeHolder = 'Search...'
}
if (input) {
pk = placekitAutocomplete(apiKey, {
target: input,
countries: ['au'],
placeholder: 'Search for an address',
})
pk.configure({
format: {
value: item =>
`${item.name} ${item.city}, ${item.administrative} ${item.zipcode}`,
},
})
pk.on('pick', (value, location, index) => {
console.log('full address data', location)
live.pushEvent('geocoded-address', { location }, () => {})
})
}
})
</script>
<input
type="search"
bind:this={input}
class="mt-2 block w-full rounded-md text-zinc-900 focus:ring-0 sm:text-sm sm:leading-6 phx-no-feedback:border-zinc-300 phx-no-feedback:focus:border-zinc-400 border-zinc-300 focus:border-zinc-400"
placeholder={placeHolder}
value={defaultValue}
/>
Gives me these errors in the console:
placekit-autocomplete.esm.mjs:47 Refused to connect to 'https://api.placekit.co/search' because it violates the following Content Security Policy directive: "default-src 'self'". Note that 'connect-src' was not explicitly set, so 'default-src' is used as a fallback.
As well as complaints about inline styles.
I'll keep digging and see what I can come up with
In case anyone else has similar content security policy (CSP) issues, I was able to work around it like this:
I created a plug in myapp_web/plugs/csp_header.ex
defmodule MyAppWeb.Plugs.CSPHeader do
import Plug.Conn
def init(opts), do: opts
def call(conn, _opts) do
csp_header =
"default-src 'self'; connect-src 'self' https://api.placekit.co; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;"
conn
|> put_resp_header("content-security-policy", csp_header)
end
end
And then added it in router.ex
to the browser pipeline:
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_live_flash
plug :put_root_layout, html: {MyAppWeb.Layouts, :root}
plug :protect_from_forgery
plug :put_secure_browser_headers, %{
"content-security-policy" => "default-src 'self'; img-src * data:;"
}
plug :fetch_current_user
plug MyAppWeb.Plugs.CSPHeader
end
The unsafe
aspect is unfortunate, I will need to keep digging on this. But here is a workaround, such as it is.
Context
The
svelte
Live View component renders<style>
and<script>
tags inline. This can cause issues when using a content security policy because it's inline.Opportunity
If additional attributes could be added to these tags, it would allow for a more strict CSP header, specifically adding a
nonce-*
attribute, reference.Example output
Header
Svelte render output