jdellitt

jdellitt

Sensitive data in Phoenix.Socket.Message when genserver exits

We have a LiveView that presents a form and collects some sensitive information from the currently logged in user and sends it out to an external API for verification. This API recently returned an unexpected response that we weren’t handling and caused the process to crash. Unfortunately, the error logs contain the last message sent, which was a Phoenix.Socket.Message containing all of the sensitive form data.

I’ve simplified the log a bit, but imagine other forms of PII being included.

GenServer #PID<0.13441.0> terminating
....REDACTED....
    (phoenix_live_view 0.19.5) lib/phoenix_live_view/channel.ex:401: anonymous fn/3 in Phoenix.LiveView.Channel.view_handle_event/3
    (telemetry 1.2.1) /app/deps/telemetry/src/telemetry.erl:321: :telemetry.span/3
    (phoenix_live_view 0.19.5) lib/phoenix_live_view/channel.ex:221: Phoenix.LiveView.Channel.handle_info/2
    (stdlib 5.0.2) gen_server.erl:1077: :gen_server.try_handle_info/3
    (stdlib 5.0.2) gen_server.erl:1165: :gen_server.handle_msg/6
    (stdlib 5.0.2) proc_lib.erl:241: :proc_lib.init_p_do_apply/3
Last message: %Phoenix.Socket.Message{topic: "lv:phx-F3uiIJTtxFjUFIHi", event: "event", payload: %{"event" => "submit", "type" => "form", "value" => "form%5Bfirst_name%5D=FIRST&form%5Blast_name%5D=LAST"}

Is there any way to prevent this with LiveView or the underlying logger or would I be better off not using LiveView to collect this information?

Marked As Solved

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

I’m not actually sure that’ll help. The logger in play for @jdellitt’s situation is the standard elixir logger that fires when a genserver crashes, and a liveview happens to be a specialized genserver. Perhaps it’d be possible to implement the Inspect protocol for Phoenix.Socket.Message and elide that info?

Also Liked

jdellitt

jdellitt

Thanks @benwilson512! I was able to add a custom Inspect protocol and just drop the form values if present. Note, I’m not currently checking for the form event type in the payload, but it’d probably be best to do so.

  defimpl Inspect, for: Phoenix.Socket.Message do
    @msg "Form values redacted for security purposes."

    def inspect(%Phoenix.Socket.Message{} = msg, opts) do
      {_, updated} =
        get_and_update_in(msg, [Access.key(:payload, nil), Access.key("value", nil)], fn
          nil -> :pop
          v -> {v, @msg}
        end)

      Inspect.Any.inspect(updated, opts)
    end
  end
mpope

mpope

Also try the sensitive process_flag.

Last Post!

pdgonzalez872

pdgonzalez872

TIL! Could you please give and example of how that is called/works? I tried a couple of variations and still see the state when we get a raise/exit:

IEx session:

random $ iex
Erlang/OTP 25 [erts-13.1.1] [source] [64-bit] [smp:10:10] [ds:10:10:10] [async-threads:1] [jit]

Interactive Elixir (1.14.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> defmodule MyApp.Periodically do
...(1)>   @moduledoc "From docs"
...(1)>   use GenServer
...(1)>
...(1)>   def start_link(_) do
...(1)>     GenServer.start_link(__MODULE__, %{})
...(1)>   end
...(1)>
...(1)>   @impl true
...(1)>   def init(state) do
...(1)>     :erlang.process_flag(:sensitive, true)
...(1)>     state = Map.put(state, :sensitive, "SHEEP")
...(1)>     schedule_work()
...(1)>
...(1)>     {:ok, state}
...(1)>   end
...(1)>
...(1)>   @impl true
...(1)>   def handle_info(:work, state) do
...(1)>     IO.puts("HI, #{DateTime.utc_now()}")
...(1)>     raise "BAH"
...(1)>     {:noreply, state}
...(1)>   end
...(1)>
...(1)>   defp schedule_work do
...(1)>     Process.send_after(self(), :work, 1000)
...(1)>   end
...(1)> end
{:module, MyApp.Periodically,
 <<70, 79, 82, 49, 0, 0, 20, 140, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 2, 87,
   0, 0, 0, 59, 25, 69, 108, 105, 120, 105, 114, 46, 77, 121, 65, 112, 112, 46,
   80, 101, 114, 105, 111, 100, 105, 99, 97, ...>>, {:schedule_work, 0}}
iex(2)>
nil
iex(3)> fun = fn ->
...(3)>   MyApp.Periodically.start_link(%{})
...(3)> end
#Function<43.3316493/0 in :erl_eval.expr/6>
iex(4)> fun.()
{:ok, #PID<0.150.0>}
HI, 2023-08-16 17:49:08.560683Z
iex(5)>
12:49:08.599 [error] GenServer #PID<0.150.0> terminating
** (RuntimeError) BAH
    iex:21: MyApp.Periodically.handle_info/2
    (stdlib 4.1.1) gen_server.erl:1123: :gen_server.try_dispatch/4
    (stdlib 4.1.1) gen_server.erl:1200: :gen_server.handle_msg/6
    (stdlib 4.1.1) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Last message: :work
State: %{sensitive: "SHEEP"}
** (EXIT from #PID<0.111.0>) shell process exited with reason: an exception was raised:
    ** (RuntimeError) BAH
        iex:21: MyApp.Periodically.handle_info/2
        (stdlib 4.1.1) gen_server.erl:1123: :gen_server.try_dispatch/4
        (stdlib 4.1.1) gen_server.erl:1200: :gen_server.handle_msg/6
        (stdlib 4.1.1) proc_lib.erl:240: :proc_lib.init_p_do_apply/3

Interactive Elixir (1.14.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)>

Can you point me in the right direction @mpope? Am I doing something wrong?

Where Next?

Popular in Questions Top

nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
RisingFromAshes
I’ve read in another post that it may be possible with a router helper - but I couldn’t find an appropriate one, and tbh, I’m still just ...
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
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

Other popular topics Top

jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 40165 209
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
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New

We're in Beta

About us Mission Statement