Hey All, it has been quite a long time since my last post. I apologize for that. Today, I will be keeping things short and sweet.

Custom Honeybadger filters for Tokens

Honeybadger is a service for “Exception, uptime, and cron monitoring, all in one place”. At InfluxData, we use this service to monitor our application and recieve notifications when things go wrong. Sometimes, we receive a bit too much information, such as Bearer Tokens.

Leaking tokens is a serious security concern. Bad faith actors can use that token to manipulate your systems or systems you are connected to. Once a token has been exposed, you need to fix the issue and rotate your tokens.

In this case, we want to redact any token going to Honeybadger.

Fortunately, the Honeybadger Elixir Repo has an easy way for us to create a custom filters. Let’s do that now.

defmoudle MyApp.MyFilter do
  use Honeybadger.Filter.Mixin

  def filter_error_message(message) do
    Regex.replace(~r/(Token|Bearer) [^"]+/, message, "\\1 redacted")
  end
end

This will filter error messages before being sent to Honeybadger and check for Token <token> or Bearer <token> and replace them with Token redacted. What is nice is that this covers Tesla, HTTPoison and probably any other HTTP library you pick. All the error messages are just strings. That means we can expect escaped strings and can capture the values up until we hit the closing ".

So, let’s write a few tests for these scenarios:

NOTE: We are looking for typical Bearer <token> and Token <token>. Error messages are truncated as they are quite large.

defmodule MyApp.HoneybadgerFilterTest do
  use ExUnit.Case, async: true
  alias MyApp.HoneybadgerFilter

  describe "filter_error_message" do
    test "replaces general tokens" do
      token = "some.jwt.abc123"
      message = "[token: \"#{token}\"]"
      actual = HoneybadgerFilter.filter_error_message(message)
      assert actual =~ "[token: \"redacted\"]"
      refute actual =~ token
    end

    test "replaces bearer tokens" do
      token = "some.jwt.abc123"
      message = "{\"Authorization\", \"Bearer #{token}\"}"
      actual = HoneybadgerFilter.filter_error_message(message)
      assert actual =~ "{\"Authorization\", \"Bearer redacted\"}"
      refute actual =~ token
    end
  end
end

The tests will cover and probably any other HTTP library you pick.

Conclusion

Adding custom filters for Honeybadger can be very straightforward. With a little of regex(I am sorry), you can safely export errors without leaking tokens!

Thanks!

Nick

Back