Skip to content

Commit 665d74c

Browse files
authored
Scrub payload["value"] for LiveView form submit events (#6267)
1 parent f6760b3 commit 665d74c

File tree

3 files changed

+91
-4
lines changed

3 files changed

+91
-4
lines changed

lib/phoenix/logger.ex

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,20 @@ defmodule Phoenix.Logger do
172172

173173
defp discard_values(%{} = map, params) do
174174
Enum.into(map, %{}, fn {k, v} ->
175-
if is_binary(k) and String.contains?(k, params) do
176-
{k, "[FILTERED]"}
177-
else
178-
{k, discard_values(v, params)}
175+
cond do
176+
is_binary(k) and String.contains?(k, params) ->
177+
{k, "[FILTERED]"}
178+
179+
is_binary(v) and String.contains?(v, params) ->
180+
new_value =
181+
Enum.reduce(params, v, fn param, v ->
182+
Regex.replace(~r/#{Regex.escape(param)}=([^&]*)(&?)/, v, "#{param}=[FILTERED]\\2")
183+
end)
184+
185+
{k, new_value}
186+
187+
true ->
188+
{k, discard_values(v, params)}
179189
end
180190
end)
181191
end

lib/phoenix/socket/message.ex

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,19 @@ defmodule Phoenix.Socket.Message do
3535
raise Phoenix.Socket.InvalidMessageError, "missing key #{inspect(err.key)}"
3636
end
3737
end
38+
39+
defimpl Inspect do
40+
def inspect(%Phoenix.Socket.Message{} = msg, opts) do
41+
processed_msg = process_message(msg)
42+
Inspect.Any.inspect(processed_msg, opts)
43+
end
44+
45+
defp process_message(%{payload: payload} = msg) when is_map(payload) do
46+
%{msg | payload: Phoenix.Logger.filter_values(payload)}
47+
end
48+
49+
defp process_message(msg), do: msg
50+
end
3851
end
3952

4053
defmodule Phoenix.Socket.Reply do

test/phoenix/socket/message_test.exs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
defmodule Phoenix.Socket.MessageTest do
2+
use ExUnit.Case, async: true
3+
doctest Phoenix.Socket.Message
4+
5+
alias Phoenix.Socket.Message
6+
7+
describe "inspect/2 custom implementation" do
8+
test "filters sensitive values in form submit events" do
9+
message = %Message{
10+
topic: "lv:1",
11+
event: "event",
12+
payload: %{
13+
"event" => "submit",
14+
"type" => "form",
15+
"value" => "username=john&password=secret123&[email protected]"
16+
},
17+
ref: "1",
18+
join_ref: "1"
19+
}
20+
21+
inspected = inspect(message)
22+
23+
assert inspected =~ "password=[FILTERED]"
24+
assert inspected =~ "username=john"
25+
assert inspected =~ "[email protected]"
26+
end
27+
28+
test "filters sensitive values at the end of form submit events" do
29+
message = %Message{
30+
topic: "lv:1",
31+
event: "event",
32+
payload: %{
33+
"event" => "submit",
34+
"type" => "form",
35+
"value" => "username=john&password=secret123"
36+
},
37+
ref: "1",
38+
join_ref: "1"
39+
}
40+
41+
inspected = inspect(message)
42+
43+
assert inspected =~ "username=john"
44+
assert inspected =~ "password=[FILTERED]\""
45+
end
46+
47+
test "handles malformed query strings gracefully" do
48+
message = %Message{
49+
topic: "lv:1",
50+
event: "event",
51+
payload: %{
52+
"event" => "submit",
53+
"type" => "form",
54+
"value" => "invalid=query=string&password=secret"
55+
},
56+
ref: "1",
57+
join_ref: "1"
58+
}
59+
60+
inspected = inspect(message)
61+
assert is_binary(inspected)
62+
end
63+
end
64+
end

0 commit comments

Comments
 (0)