Menu
Platform
AI
App store purchases
Database
Flags
Jobs and cron
Localization
Monitoring
Notifications
Payments
Queues
Sandboxes
Webhooks
Getting Started
Authentication
KV Store
Deploy & Infrastructure
Reference
Scrubbing
What is removed before an error is stored, and how an environment adds to it
Scrubbing is the line between a useful error report and a stored credential. A
Scrubbing Policy is what is removed from every captured error before it is
stored, and it runs on the way in rather than on the way out: the occurrence
that is written is the occurrence after the rules have been applied, so a
secret that a stack trace carried is not in the record you read back later. The
stack field is scrubbed with the rest of the occurrence.
#The default rules
The defaults always apply, to every occurrence, whatever the environment's policy says:
- Fields named like a password, a secret, a token, a key, a cookie, a session,
an authorization or a card are replaced with
[Filtered]. - Card numbers, bearer tokens, JWTs and Sylphx secret keys are replaced wherever they appear.
- Email addresses are replaced with
[email]unlesskeep_emailsis set.
The first rule reads a name, the second reads a value, and together they catch the two ways a secret reaches a stack trace: carried in a field whose name says what it is, or pasted into one whose name does not.
#An environment's policy adds to them
The environment's Scrubbing Policy adds to the defaults; it cannot remove them. There is no setting that turns the default rules off, which is the reason a policy can be written by whoever owns the application without anyone having to read it as a security review.
| Field | Type | What it is |
|---|---|---|
denied_fields | string[] | More field names to replace with [Filtered] wherever they appear in tags, extra data, request data, or breadcrumb data (case-insensitive, matched as a substring). |
keep_emails | bool | Keep email addresses instead of replacing them with [email]. |
denied_fields is matched case-insensitively and as a substring, so one name
covers every field that contains it — national_insurance covers
national_insurance_number and customerNationalInsurance. Add a name when
the defaults do not know what your domain calls the thing that must not be
stored.
keep_emails exists because an email address is often the identifier you need:
for an application whose users are told their address appears in error reports,
keeping them makes a group readable. It is the one default rule an environment
may switch off, and switching it off is a decision about your users rather than
about the platform.
#One policy per environment
A policy is a singleton, and its name says so:
- Name
- orgs/{org}/projects/{project}/envs/{env}/scrubbing_policies/default
- Id
- scp_<env>
There is one per environment and no call that creates another. meta.etag
fences updates: send the etag you read and the write lands only if nothing has
changed since; a mismatch fails with ETAG_MISMATCH and writes nothing. Two
people editing the policy at once is a conflict rather than a silent overwrite.
#Read it
Reading the policy needs observability:read. It answers with the environment's
own fields — the extra names it filters and the email switch — and the metadata
every resource carries. The default rules are not listed beside them, because
they are not the environment's to state.
sylphx observability scrubbing-policies get orgs/acme/projects/shop/envs/production/scrubbing_policies/scrubbing-policycurl "https://api.sylphx.com/v1/orgs/acme/projects/shop/envs/production/scrubbing_policies/scrubbing-policy" \
-H "Authorization: Bearer $SYLPHX_API_KEY"#Add to it
Writing the policy needs observability:write, and it takes an update_mask:
the fields you name are the fields written, and an unset mask writes every
populated field.
sylphx observability scrubbing-policies update orgs/acme/projects/shop/envs/production/scrubbing_policies/scrubbing-policycurl -X PATCH "https://api.sylphx.com/v1/orgs/acme/projects/shop/envs/production/scrubbing_policies/scrubbing-policy" \
-H "Authorization: Bearer $SYLPHX_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"orgs/acme/projects/shop/envs/production/scrubbing_policies/scrubbing-policy"}'const response = await sylphx.observability.scrubbingPolicies.update({ scrubbingPolicy: { name: 'orgs/acme/projects/shop/envs/production/scrubbing_policies/scrubbing-policy' } })--denied-fields names one more field to filter and repeats for each;
--keep-emails flips the email rule. The
scrubbing_policies commands show both flags.
#Why the floor is the point
A policy that could remove a default rule would be a policy nobody could read at a glance: every reader would have to check what the environment had turned off before deciding whether a report was safe to keep. Making the policy additive is what lets the two questions stay separate — the defaults are the platform's answer to what must never be stored, and the environment's answer is only what else it wants gone.