Skip to content

Commit

Permalink
Add redact errors option in normal mode
Browse files Browse the repository at this point in the history
  • Loading branch information
beatrichartz committed Sep 24, 2023
1 parent 4f76a8b commit 63b5d88
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 5 deletions.
15 changes: 10 additions & 5 deletions lib/csv.ex
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ defmodule CSV do
length. Defaults to `false`.
* `:unescape_formulas` – When set to `true`, will remove formula escaping
inserted to prevent [CSV Injection](https://owasp.org/www-community/attacks/CSV_Injection).
* `:redact_errors` – When set to `true`, will redact csv data in
message output of errors. This is to address scenarios where errors are
propagated in a stream and accidental logging of sensitive data needs
to be prevented. Defaults to `false`.
## Examples
Expand Down Expand Up @@ -149,7 +153,7 @@ defmodule CSV do
| {:escape_character, char()}
| {:escape_max_lines, integer()}

@spec decode(Enumerable.t(), [decode_options()]) :: Enumerable.t()
@spec decode(Enumerable.t(), [decode_options() | {:redact_errors, boolean()}]) :: Enumerable.t()
def decode(stream, options \\ []) do
stream |> Decoder.decode(options) |> inline_errors!(options)
end
Expand Down Expand Up @@ -305,15 +309,16 @@ defmodule CSV do

defp inline_errors!(stream, options) do
escape_max_lines = options |> Keyword.get(:escape_max_lines, @escape_max_lines)
redact_errors = options |> Keyword.get(:redact_errors, false)

stream |> Stream.map(&yield_or_inline!(&1, escape_max_lines))
stream |> Stream.map(&yield_or_inline!(&1, escape_max_lines, redact_errors))
end

defp yield_or_inline!({:error, mod, args}, _) do
{:error, mod.exception(args ++ [mode: :normal, unredact: true]).message}
defp yield_or_inline!({:error, mod, args}, _, redact_errors) do
{:error, mod.exception(args ++ [mode: :normal, unredact: !redact_errors]).message}
end

defp yield_or_inline!(value, _), do: value
defp yield_or_inline!(value, _, _), do: value

@doc """
Encode a table stream into a stream of RFC 4180 compliant CSV lines for
Expand Down
13 changes: 13 additions & 0 deletions test/csv_exceptions_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,19 @@ defmodule CSVExceptionsTest do
]
end

test "decodes in normal mode redacting error messages when configured" do
stream = ~w(a,be a" c,d) |> to_line_stream
result = CSV.decode(stream, redact_errors: true) |> Enum.to_list()

assert result == [
ok: ~w(a be),
error:
"Stray escape character on line 2:\n\n**redacted**\n\n" <>
"This error often happens when the wrong separator or escape character has been applied.\n",
ok: ~w(c d)
]
end

test "decodes in strict mode raising errors" do
stream = ~w(a,be a c,d) |> to_line_stream

Expand Down

0 comments on commit 63b5d88

Please sign in to comment.