# How do I stop passwords, tokens and personal data from ending up in error reports?

Stop it at the source: configure the SDK so sensitive fields are never sent, using its data-collection options and beforeSend and breadcrumb hooks to drop or redact request bodies, headers, URLs, user fields and logged values. Add server-side scrubbing as a safety net, stop logging secrets, and rotate any credential that already leaked, since deleting an event does not un-expose it.

Canonical page: https://bugsly.dev/solutions/sensitive-data-in-error-reports. Last updated 2026-11-13. All solutions: https://bugsly.dev/solutions (list as JSON: https://bugsly.dev/solutions.json).

## Why it happens

Error trackers work because the SDK attaches context to a crash: the request that triggered it, the user, the lines logged just before, sometimes the values of local variables. That same context is where secrets and personal data hide. A login endpoint fails and the form payload includes a password. A third-party API call fails and the URL contains an API key in the query string. A debug log line prints a session token, and the SDK records it as a breadcrumb.

Sentry's own documentation lists where sensitive data typically appears: stack locals (the Python, PHP and Node SDKs pick up variable values), breadcrumbs from log statements, database queries, HTTP query strings and fragments, user context controlled by sendDefaultPii, and transaction names or HTTP spans that contain raw URLs such as /users/1234/details. Request data in the Python integrations includes method, URL, headers, and form or JSON payloads, with raw bodies and multipart uploads excluded.

Defaults have also moved. Recent Sentry SDK documentation describes a newer data-collection option that replaces the single sendDefaultPii switch, and notes that opting in to its defaults is more permissive than sendDefaultPii set to false. Do not assume the default for your SDK version is conservative: check what your version collects, then restrict it deliberately and look at a real event before you trust it.

## How to keep sensitive data out of error reports

1. **Inventory what your SDK sends by looking at a real event.** Trigger an error in staging with realistic input and read the full event JSON: request, headers, cookies, user, breadcrumbs, extra and local variables. Compare it to the leak surfaces in the table below. This step is more reliable than reading defaults from documentation, because defaults differ between SDKs and versions and your code adds its own context.
2. **Restrict collection with SDK options first.** Sentry's React and Python documentation describe the dataCollection (data_collection in Python) option for turning off categories such as user info, and sendDefaultPii as the older switch for user data; if you set both in Python, send_default_pii is ignored (Sentry docs, read 2026-11-13). The Python options also include include_local_variables, which is on by default and attaches local variable values, and max_request_body_size, which can be set to never. Turn off what you do not need rather than scrubbing it afterwards.

```
sentry_sdk.init(
    dsn=...,
    include_local_variables=False,
    max_request_body_size="never",
    data_collection={"user_info": False},
)
```

3. **Redact in beforeSend and beforeBreadcrumb.** Sentry's data-scrubbing guide recommends the beforeSend family of hooks to remove sensitive data before it leaves your environment: beforeSend for errors and messages, beforeSendSpan for spans, beforeSendLog for logs. Use beforeBreadcrumb to filter log-derived breadcrumbs before they attach, and strip or hash query strings that carry tokens. Prefer an allowlist for the fields you keep over a denylist of the ones you remember.

```
Sentry.init({
  beforeSend(event) {
    if (event.user) delete event.user.email;
    if (event.request) { delete event.request.cookies; delete event.request.data; }
    return event;
  },
  beforeBreadcrumb(crumb) {
    if (crumb.category === "console") return null;
    return crumb;
  },
});
```

4. **Identify users by an internal ID, not by email.** Sentry's guide suggests setUser with only an internal id or username if emails are considered confidential, which keeps user-impact counts working without personal details, and hashing contextual values before sending them as tags. Never put a name, email or phone number into a tag, which is searchable and widely visible to your team.

```
Sentry.setUser({ id: user.id });
```

5. **Fix the logging, not just the report.** Sentry's documentation says you should avoid logging confidential information in the first place, because log lines become breadcrumbs. Redact secrets in your logger with a formatter or serializer, never log full request bodies or Authorization headers, and keep tokens out of URLs by sending them in a header. Fixing the log fixes your log store and the tracker.
6. **Add a server-side scrubber as a safety net, then rotate what leaked.** Scrubbing on the tracker side catches what your SDK rules miss, and Sentry's documentation distinguishes SDK-side scrubbing (data is not sent) from server-side scrubbing (data is not stored). Treat it as a backstop. If a password, token or key already reached any tracker or log, assume it is exposed: rotate it, then delete or expire the stored events according to your retention policy. Deleting the event does not make the credential safe again.
7. **Decide retention and who can see events.** Keep only as long as you need to debug. Limit the people who can open issues, because even scrubbed events can contain business data. Re-check after every SDK upgrade, since new integrations can add new fields.

Leak surface to control checklist

| Leak surface | Example | Control |
| --- | --- | --- |
| Request bodies | Password in a login form payload | Disable body capture, or redact in beforeSend |
| Headers and cookies | Authorization, Cookie, session ID | Drop headers and cookies in beforeSend; server-side scrub as backup |
| URLs and query strings | ?token=... or ?api_key=... | Move secrets to headers; strip query strings in hooks; fix transaction names |
| User context | Email, username, IP address | Restrict via dataCollection or sendDefaultPii; send an internal ID only |
| Breadcrumbs from logs | A console.log that printed a token | Remove the log; filter in beforeBreadcrumb |
| Console breadcrumbs | Debug output captured automatically | Return null for console breadcrumbs in beforeBreadcrumb |
| Local variables | A function argument holding a secret | Turn off local variable capture where the SDK has it |
| Tags and extra data | A tag set to an email | Hash values or send internal identifiers only |

Leak surfaces are from Sentry's scrubbing documentation (docs.sentry.io, read 2026-11-13); controls combine its recommendations with the steps above.

## When to use Bugsly

Bugsly accepts the standard Sentry SDKs, so every SDK-side control above works unchanged. On ingest, before any event is stored, Bugsly also scrubs server-side: values of sensitive-looking keys (password, token, auth, secret, api key and similar), credit-card-looking numbers that pass the Luhn check, JWTs, Bearer tokens and well-known provider secret formats are replaced with [Filtered]. You can add your own field names per project, and IP scrubbing is optional. This is a safety net: it matches patterns and key names, so it cannot catch a secret stored under an innocent-looking key. It is not a substitute for not sending data.

If an AI assistant reads your errors over MCP, there is one more difference to know. The hosted MCP server omits user email, IP address, username and extra data from get_issue_events output and caps the output size. The local npm package @bugsly/mcp-server does not apply that redaction, size cap or rate limits, so use the hosted server unless your client cannot call a URL. Bugsly does not claim compliance certifications, so do not rely on a certification here.

## When Bugsly is not the right answer

If a regulation or contract requires error data to stay on your own infrastructure, a hosted service is not the answer, and Bugsly cannot be self-hosted. In that case use a self-hosted tracker or your own log pipeline, with scrubbing applied before data leaves the process. If you are not allowed to send any user data to a third-party processor at all, note that Bugsly's AI analysis uses OpenAI as the processor, so confirm that is acceptable or avoid it for those projects.

## Ask your AI assistant to do it

Connect the Bugsly MCP server (https://bugsly.dev/mcp), then paste:

> Assign to Bugsly: use list_projects to find my project, then list_issues and get_issue_events for the 5 newest unresolved issues. Check each event for anything that looks like a password, token, API key, email address or personal data in the request, URL, breadcrumbs or extra data, and report where it appears and which field name holds it. Do not resolve or ignore anything and do not repeat the secret values in your answer; show me what you found so I can approve the next step.

## Frequently asked questions

### Is server-side scrubbing enough on its own?

No. It matches key names and known patterns, so it can miss a secret under an unexpected key, and the data has already left your system. Use it as a backstop behind SDK-side controls.

### I found a password in an old event. What now?

Rotate the credential first, because anyone who could view the event may have seen it. Then delete or expire the event according to your retention policy and fix the source so it is not sent again.

### Does sendDefaultPii set to false remove everything sensitive?

No. It governs user-related data added by integrations. Query strings, breadcrumbs, logged values and local variables are separate surfaces that need their own controls.

### Are console logs really sent with errors?

In the JavaScript SDK, previously logged statements can be attached as breadcrumbs, per Sentry's documentation. Avoid logging secrets, or filter console breadcrumbs with beforeBreadcrumb.

## Sources

- Sentry docs: Scrubbing sensitive data (JavaScript) (read 2026-11-13): https://docs.sentry.io/platforms/javascript/data-management/sensitive-data/
- Sentry docs: Python SDK options (read 2026-11-13): https://docs.sentry.io/platforms/python/configuration/options/
- Sentry docs: React guide (data collection) (read 2026-11-13): https://docs.sentry.io/platforms/javascript/guides/react/
- Sentry docs: FastAPI (request data) (read 2026-11-13): https://docs.sentry.io/platforms/python/integrations/fastapi/

## Related

- Error tracking best practices: https://bugsly.dev/blog/error-tracking-best-practices
- Bugsly MCP server: https://bugsly.dev/mcp
- Explain any error or stack trace: https://bugsly.dev/tools/explain-error
- Error tracking for AI agents: https://bugsly.dev/agents
