-
Notifications
You must be signed in to change notification settings - Fork 347
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Filter sensitive data from inspect(Tesla.Client.t) #534
base: master
Are you sure you want to change the base?
Filter sensitive data from inspect(Tesla.Client.t) #534
Conversation
2516dff
to
058cbd6
Compare
Do you mind expanding on that, do you mean you leaked to some 3rd party provider? I am not opposed to the idea. The curious part is that this issue would be all over Elixir code bases, so I am not sure what is the right call here. As far as I can tell you would modify your logger to hide sensitive information, but I may be wrong. Gonna lean on @teamon for some feedback about it. |
I tend to have a custom implementation of Inspect protocol on a per-project basis, often something as simple as: defimpl Inspect, for: Tesla.Client do
@moduledoc """
Implement custom Inspect protocol for Tesla.Client
to prevent leaking secrets added with Tesla.Middleware.Headers
to AppSignal or logs.
"""
import Inspect.Algebra
def inspect(client, opts) do
attrs = client |> Map.take([:adapter]) |> Map.to_list()
concat(["#Tesla.Client<", to_doc(attrs, opts), ">"])
end
end The problem with implementing it directly into tesla package is that as far as I know one wouldn't be able to override it anymore. |
A solid argument is that Ecto does the same https://github.com/elixir-ecto/ecto/blob/d52039037ae8d3ba66034c35c08fc4d56c621447/lib/ecto/changeset.ex#L3134-L3172 (from Kyle Steger) but then as @teamon pointed out, what happens when we have other middleware that wants to accomplish the same? We can't redact anymore something? |
It's possible to write another middleware, I think what is proposed here provides immediate benefit and prevents known secret data from being leaked in logs. Gets a thumb in my book |
Leaked to our application monitoring as part of its exception handling.
That's unfortunately not possible in this case. Exception is raised, Appsignal
How about hiding it behind a compile-time flag? I'd assume that the vast majority of users does not have a custom implementation, so defaulting it to
|
Also, as a side note: We have since discovered that we also use the |
Agree with this, but having a solution when opting out without so much rework should be taken into consideration as well.
What if the input is an struct instead of a keyword list, then you implement the redacting for such struct, example: {MyMiddlewareName, %MyMiddlewareName.Config{token: "..."}} So you implement the protocol for Would that work? If that strategy work, we could decide to commit to what we have, and maybe recommend people to do such a thing if they want to control redacting things. Thoughts? |
Gentlemen, any update on this? I'm happy to rework it in any way you conceive, but I do believe the status quo is an unnecessary pitfall / security risk for uncautious people (like me). |
15c5618
to
1aef34b
Compare
@maltoe sorry it took me this long to get back to this issue, but I have other duties. From my perspective, the tricky situation with this PR is that we are taking over control of the From the library perspective, How do we ensure that this implementation of the That may not be a concern, but I am unsure. This leads us to two possible solutions,
IMPORTANTI pushed some changes showcasing the usage of If you wish to continue helping in the subject, we must do the same for Let me know if you can help with the task. Otherwise, I can take over. |
Sorry if my last comment came across too pushy. I'm sure you have and thank you for your work on tesla, it's an awesome tool 🛠️ 💜 !
My 2 cents: I'm wondering whether we're "overthinking" it - the original code in this PR was my attempt at fixing the "leak" while leaving some useful information in the Hence, how about going back to what @teamon originally said in #534 (comment) and providing an extremely simplistic default implementation (e.g. hiding all middlewares including the internal ones) with an opt-out? That way you prevent leaks even from external middlewares, protect the innocents, and people don't have to rework much at all when they opt-out 😬 Otherwise, I also like your struct approach (though Thanks again for considering & best wishes. |
2bca420
to
fe7207c
Compare
Coming back to this, We should refrain from doing anything about this, which is a fundamental problem for Elixir. In the best case, a scapegoat exists, and changing the behavior of the Inspect is good enough; adding This is also why Logger filters exist: You can clean up and remove things there to ensure that you do not leak information. I am not opposed 100% yet to trying to fix it, but looking at the code and whatnot, I am somewhat thinking of pushing the responsibility to copy+paste @teamon example or simply use the existing tool from Elixir, such as the Logger filters to deal with the situation |
I've recently ended up with something like this: defimpl Inspect, for: Tesla.Client do
@moduledoc """
Implement custom Inspect protocol for Tesla.Client
to prevent leaking secrets added to headers
"""
@conceal [
{Tesla.Middleware.BasicAuth, [:password]},
{Tesla.Middleware.BearerAuth, [:token]},
{Tesla.Middleware.DigestAuth, [:password]}
]
def inspect(client, opts) do
client =
Map.update!(client, :pre, fn middlewares ->
Enum.map(middlewares, fn {module, fun, [opts]} ->
case @conceal[module] do
nil ->
{module, fun, opts}
attrs ->
{module, fun,
Enum.reduce(attrs, opts, fn attr, acc ->
acc
|> Access.get_and_update(attr, fn val -> {val, "*****"} end)
|> elem(1)
end)}
end
end)
end)
Inspect.Map.inspect(client, opts)
end
end Maybe there is a room for some |
Hi 👋
We recently discovered - luckily before going to production - that we leaked secret tokens for an API integration, as we were doing something like this
The resulting
MatchError
in case of network failures etc. would include the inspectedTesla.Client
struct which in turn included thesupersecret
token.We thought implementing
Inspect
within Tesla itself and filtering some options would be a more sensible default for all users, hence this PR.Best,
malte
Todos
Tesla.Middleware.BasicAuth.Options
structTesla.Middleware.BearerAuth.Options
structTesla.Middleware.DigestAuth.Options
struct