View Source Sentry.Scrubber (Sentry v13.2.0)

Shared, framework-agnostic helpers for scrubbing sensitive data before it is sent to Sentry.

Available since v13.1.0.

This module owns the default sensitive key lists, the placeholder used in place of redacted values, the credit-card detection heuristic, and the recursive map/list traversal used by the rest of the SDK to redact values. Integrations such as Sentry.PlugContext, Sentry.PlugCapture, and Sentry.LiveViewHook delegate to the functions exposed here so that scrubbing rules live in a single place.

Defaults

The default sensitive parameter keys (used for body params, query strings, and arbitrary maps) are:

  • "password"
  • "passwd"
  • "secret"

The default sensitive header keys are:

  • "authorization"
  • "authentication"
  • "cookie"

Values matching a credit-card-like pattern (13–16 digits, optionally separated by spaces or dashes) are also replaced with the placeholder.

Custom scrubbing

The map/query/header functions accept an optional :keys option that overrides the default list of sensitive keys. This makes it possible to compose custom scrubbers on top of the defaults:

def scrub(map) do
  map
  |> Sentry.Scrubber.scrub(keys: ["password", "api_key"])
  |> Map.drop(["internal_notes"])
end

Scrubbing a %Plug.Conn{}

scrub/1 redacts a conn by applying, to each field listed in the @scrubbable_conn_fields attribute, that field's strategy. A strategy is either:

  • a configurable scrubber (:cookie_scrubber, :header_scrubber, :body_scrubber) — resolved per process via put_conn_scrubber/1 (typically from Sentry.PlugContext.call/2), falling back to the SDK default scrub(conn, field) clause when none is registered, or
  • a fixed tag — :clear replaces the field with %{}, :params scrubs the field as a params-shaped map, :query_string redacts sensitive params from a raw query string, and :private_allow_list keeps only the registered allow-listed keys of the field (see default_private_allow_list/0 and the :private_allow_list option of put_conn_scrubber/1), dropping everything else.

By default scrub/1 redacts cookies, req_headers, params, and body_params (the configurable fields — body_params shares the :body_scrubber with params, so it honors the same registered scrubber and is emptied when body_scrubber is nil), clears req_cookies and assigns to %{}, scrubs query_params as a params-shaped map, and reduces private to its allow-listed keys (default_private_allow_list/0). assigns is cleared wholesale because auth libraries (Guardian, Pow, Coherence) routinely store decoded tokens, full user structs, and session data there, where no key-based heuristic redacts safely. private keeps only the allow-listed framework metadata and drops everything else (notably :plug_session).

The defaults can be overridden per call with scrub(conn, overrides), where overrides is a field: strategy keyword list merged over the attribute — for example scrub(conn, assigns: :clear). The request URL is not a conn field, so callers fetch the registered :url_scrubber with get/1 and apply it to the conn.

Summary

Types

A per-field scrubber identifying how to redact a particular %Plug.Conn{} field.

Options accepted by the scrubbing functions in this module.

t()

A resolved set of per-field scrubbers for a %Plug.Conn{}.

Functions

Returns the default list of sensitive header keys.

Returns the default list of sensitive parameter keys.

Returns the default list of %Plug.Conn{} :private keys retained by the :private_allow_list scrubbing strategy.

Drops sensitive keys from a flat map.

Returns the current process's resolved scrubber function for the given field.

Builds a resolved t/0 set of per-field scrubbers from the given options.

Registers the current process's per-field scrubbers for %Plug.Conn{}.

Scrubs a %Plug.Conn{} or a plain map.

Scrubs a value with the given options, dispatching on the value's type.

Scrubs an application/x-www-form-urlencoded query string, replacing the value of any sensitive parameter with the placeholder.

Scrubs the query string portion of a URL, replacing the value of any sensitive query parameter with the placeholder. URLs without a query string are returned unchanged.

The placeholder string used to replace scrubbed values.

Types

Link to this type

conn_scrubber_opts()

View Source (since 13.1.0)
@type conn_scrubber_opts() :: [
  body_scrubber: field_scrubber(),
  header_scrubber: field_scrubber(),
  cookie_scrubber: field_scrubber(),
  url_scrubber: field_scrubber(),
  private_allow_list: [atom()]
]

Options accepted by put_conn_scrubber/1.

Each *_scrubber key, when omitted, falls back to the field's default scrubber — the matching scrub(conn, field) clause of scrub/2. :private_allow_list defaults to default_private_allow_list/0.

Link to this type

field_scrubber()

View Source (since 13.1.0)
@type field_scrubber() :: (Plug.Conn.t() -> term()) | {module(), atom()} | nil

A per-field scrubber identifying how to redact a particular %Plug.Conn{} field.

  • a 1-arity function — invoked as fun.(conn)
  • {module, function} — invoked as apply(module, function, [conn])
  • nil — disables the scrubber; map-shaped fields are replaced with %{}, and :url falls back to the request URL unchanged
Link to this type

option()

View Source (since 13.1.0)
@type option() :: {:keys, [String.t()]}

Options accepted by the scrubbing functions in this module.

@type t() :: %Sentry.Scrubber{
  body_scrubber: (Plug.Conn.t() -> term()),
  cookie_scrubber: (Plug.Conn.t() -> term()),
  header_scrubber: (Plug.Conn.t() -> term()),
  private_allow_list: [atom()],
  url_scrubber: (Plug.Conn.t() -> String.t())
}

A resolved set of per-field scrubbers for a %Plug.Conn{}.

Each scrubber field holds a 1-arity function that takes the conn and returns the scrubbed value for the corresponding field. private_allow_list holds the keys retained by the :private_allow_list strategy. Built by put_conn_scrubber/1 from conn_scrubber_opts/0 and stored in the process dictionary.

Functions

Link to this function

default_header_keys()

View Source (since 13.1.0)
@spec default_header_keys() :: [String.t()]

Returns the default list of sensitive header keys.

Link to this function

default_param_keys()

View Source (since 13.1.0)
@spec default_param_keys() :: [String.t()]

Returns the default list of sensitive parameter keys.

Link to this function

default_private_allow_list()

View Source (since 13.2.0)
@spec default_private_allow_list() :: [atom()]

Returns the default list of %Plug.Conn{} :private keys retained by the :private_allow_list scrubbing strategy.

These are Phoenix's routing/render metadata keys, kept because they are high-signal, non-sensitive breadcrumbs for triaging errors. This is the default for the scrubber: [conn_private_allow_list: ...] configuration option.

Link to this function

drop_keys(map, opts \\ [])

View Source (since 13.1.0)
@spec drop_keys(map(), [option()]) :: map()

Drops sensitive keys from a flat map.

This is the strategy used for HTTP headers, where the sensitive value should not appear in the payload at all.

Options

@spec get(atom()) :: (Plug.Conn.t() -> term())

Returns the current process's resolved scrubber function for the given field.

key is one of [:body_scrubber, :header_scrubber, :cookie_scrubber, :url_scrubber]. Returns the scrubber registered via put_conn_scrubber/1, or the field's default if none was registered. The returned function takes a %Plug.Conn{} and returns the scrubbed value, so callers apply it as Sentry.Scrubber.get(:url_scrubber).(conn).

Link to this function

new(opts \\ [])

View Source (since 13.2.0)
@spec new(conn_scrubber_opts()) :: t()

Builds a resolved t/0 set of per-field scrubbers from the given options.

Accepts the same :body_scrubber, :header_scrubber, :cookie_scrubber, and :url_scrubber keys as put_conn_scrubber/1. Each missing key falls back to the field's default scrubber (the matching scrub(conn, field) clause). Called with no arguments, new/0 returns the all-defaults scrubber.

Unlike put_conn_scrubber/1, this only constructs the struct — it does not register it for the current process.

Link to this function

put_conn_scrubber(opts)

View Source (since 13.2.0)
@spec put_conn_scrubber(conn_scrubber_opts()) :: :ok

Registers the current process's per-field scrubbers for %Plug.Conn{}.

Accepts the same :body_scrubber, :header_scrubber, :cookie_scrubber, and :url_scrubber keys that Sentry.PlugContext takes as plug options, resolves each missing key to the field's default scrubber (the {__MODULE__, :scrub, [field]} MFA, i.e. the matching scrub(conn, field) clause), and stores the resolved scrubbers in the process dictionary.

The registration lives for the lifetime of the calling process — typically the request process when registered from Sentry.PlugContext.call/2. Used by other parts of the SDK (notably Sentry.PlugCapture) so all conn scrubbing honors the same configuration the user passed to plug Sentry.PlugContext.

Returns :ok.

Link to this function

scrub(conn)

View Source (since 13.2.0)
@spec scrub(Plug.Conn.t()) :: Plug.Conn.t()
@spec scrub(map()) :: map()
@spec scrub(term()) :: term()

Scrubs a %Plug.Conn{} or a plain map.

Given a %Plug.Conn{}, scrubs each field listed in @scrubbable_conn_fields according to its strategy — see the "Scrubbing a %Plug.Conn{}" section in the module docs and scrub/2 for the per-field defaults and how to override them per call. The request URL is not a conn field; callers scrub it separately by applying the :url_scrubber from get/1 (whose default is scrub(conn, :url)).

Given a plain map, recursively scrubs it with the default sensitive keys — equivalent to scrub(map, []). Any other struct is converted to a map and scrubbed the same way, so a sensitive field can't slip through unredacted — for example when the struct is inspected into stacktrace frame vars. See scrub/2.

Link to this function

scrub(map, opts)

View Source (since 13.1.0)
@spec scrub(map(), [option()]) :: map()
@spec scrub(list(), [option()]) :: list()
@spec scrub(term(), [option()]) :: term()
@spec scrub(
  Plug.Conn.t(),
  keyword()
) :: Plug.Conn.t()
@spec scrub(Plug.Conn.t(), :body | :headers | :cookies | :url) :: term()

Scrubs a value with the given options, dispatching on the value's type.

Scrubbing a map, list, or leaf value — scrub(value, opts)

Recursively scrubs a map: any value whose key is in the configured sensitive key list is replaced with the placeholder, and the remaining values are scrubbed in turn. Lists are scrubbed element-wise, structs are scrubbed as maps, and credit-card-shaped binaries are replaced with the placeholder. Any other leaf value is returned unchanged.

Accepts the same :keys option as the other scrubbing functions:

Scrubbing a single %Plug.Conn{} field — scrub(conn, field)

Extracts the given field from the conn and applies the SDK's default redaction for it. Each clause is what the field's default scrubber captures as a {__MODULE__, :scrub, [field]} MFA, and what scrub/1 (conn fields) and get/1 (URL) fall back to when no custom scrubber is registered:

  • :body — scrubs conn.params via scrub/2; non-map params (such as %Plug.Conn.Unfetched{}) pass through unchanged.
  • :headers — drops sensitive conn.req_headers case-insensitively, preserving the list-of-tuples shape.
  • :cookies — drops all cookies, returning %{}.
  • :url — scrubs sensitive query parameters from the request URL via scrub_url/1. To disable URL scrubbing, register a :url_scrubber of nil (or a custom one); see Sentry.PlugContext.

Because these clauses are the defaults (not the registered scrubbers), a custom :body_scrubber can safely compose on the default behavior without recursing:

defmodule MyScrubber do
  def scrub_params(conn) do
    conn
    |> Sentry.Scrubber.scrub(:body)
    |> Map.drop(["my_secret_field"])
  end
end

Scrubbing a whole %Plug.Conn{} with overrides — scrub(conn, overrides)

Behaves like scrub/1 but merges the field: strategy keyword overrides over the @scrubbable_conn_fields defaults, so a caller can scrub additional fields or change a field's strategy for that call. Strategies are a configurable scrubber struct-key, :clear (replace with %{}), or :params (params-shaped scrub of that field):

Sentry.Scrubber.scrub(conn, assigns: :clear, query_params: :params)
Link to this function

scrub_query_string(query, opts \\ [])

View Source (since 13.1.0)
@spec scrub_query_string(String.t(), [option()]) :: String.t()

Scrubs an application/x-www-form-urlencoded query string, replacing the value of any sensitive parameter with the placeholder.

Options

See scrub/2.

Link to this function

scrub_url(url, opts \\ [])

View Source (since 13.1.0)
@spec scrub_url(String.t(), [option()]) :: String.t()

Scrubs the query string portion of a URL, replacing the value of any sensitive query parameter with the placeholder. URLs without a query string are returned unchanged.

Options

See scrub/2.

Link to this function

scrubbed_value()

View Source (since 13.1.0)
@spec scrubbed_value() :: String.t()

The placeholder string used to replace scrubbed values.