kerryb

kerryb

Working content security policy for Phoenix channels?

Hi,

I use sobelow to highlight potential security issues, and the latest version has started warning if no content-security-policy header is set. I fixed that by adding a custom header:

@csp "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline' 'unsafe-eval'"

pipeline :browser do
  # ...
  plug :put_secure_browser_headers, %{"content-security-policy" => @csp}
  # ...

However, this has stopped channels from working. I’ve tried adding various versions of ws://localhost:4000 and the like, but with no success.

Does anyone have a working CSP header for use with channels?

For bonus points, what’s the best way to get the hostname to use in the policy, assuming it needs to be different in production? I could just set a config value in the environment, but is it already available somewhere?

Thanks!

Kerry

Most Liked

iautom8things

iautom8things

Just wanted to comment on this, if someone else stumbles across this thread looking for help on fixing sobelow warning about config.CSP even though you’re setting it:

$ mix sobelow -d Config.CSP

# ...

Missing Content-Security-Policy is flagged by sobelow when a pipeline
implements the :put_secure_browser_headers plug, but does not provide a
Content-Security-Policy header in the custom headers map.

# ...

This is referring to this:

You can obviously set headers in different places, so sobelow is just looking that if you have a pipeline that calls plug :put_secure_browser_headers in your Router, that you also include a map with %{"Content-Security-Policy" => "..."} so it should look like this:

plug :put_secure_browser_headers, %{"Content-Security-Policy" => "..."}
kerryb

kerryb

Thanks! The root of my problem was putting the ws:// URI in quotes, but the struct_url thing was really helpful too. FWIW I ended up with this:

defmodule MyAppWeb.CSPHeader do
  import Plug.Conn

  def init(opts), do: opts

  def call(conn, _opts) do
    put_resp_header conn, "content-security-policy", csp(conn)
  end

  defp csp(conn) do
    "default-src 'self'; \
    connect-src 'self' #{ws_url conn} #{ws_url conn, "wss"}; \
    script-src 'self' 'unsafe-inline' 'unsafe-eval'; \
    style-src 'self' 'unsafe-inline' 'unsafe-eval'"
  end

  defp ws_url(conn, protocol \\ "ws") do
    endpoint = Phoenix.Controller.endpoint_module(conn)
    %{endpoint.struct_url | scheme: protocol} |> URI.to_string()
  end
end
ryh

ryh

You can pull this information from the conn. There may be a better way to do this… for example, there is no check to see if the endpoint is/should be wss.

def ws_url(conn) do
  endpoint = Phoenix.Controller.endpoint_module(conn)
  
  %{endpoint.struct_url | scheme: "ws"} |> URI.to_string()
end

Have you tried connect-src? Apparently you must define it for each scheme you use. More information here.

Here’s what it might look like:

@csp "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline' 'unsafe-eval'; connect-src ws://localhost:4000/"

I tried testing this, but I can’t tell if it works or not.

Where Next?

Popular in Questions Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
Kurisu
For example for a current url like http://localhost:4000/cosmetic/products?_utf8=✓&query=perfume&page=2, I would like to get: ...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
Lily
In templates/appointment/index.html.eex: <%= for appointment <- @appointments do %> <tr> <td><%= appoi...
New
hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a > b) do {:ok, "a"} end if (a < b) do {:ok, b} end if (a == b) do {:ok, "equa...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

Other popular topics Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New
greenz1
I have a phoenix application from which a user can download multiple(5-6) files of size 1MB. I couldn’t find anything related to sending ...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

Latest on Elixir Forum

We're in Beta

About us Mission Statement