# How Sentry's beforeSend Hook Scrubs PII Before Reports Are Sent in DeskcommCRM

> Learn how DeskcommCRM uses Sentry beforeSend hooks to scrub PII like CPF numbers and emails before sending error reports. Protect sensitive data with this guide.

- Repository: [Rafael Melgaço/DeskcommCRM](https://github.com/melgarafael/DeskcommCRM)
- Tags: how-to-guide
- Published: 2026-09-13

---

**DeskcommCRM's centralized `sentryScrubHooks` module intercepts every error, transaction, span, and breadcrumb through Sentry's `beforeSend` and related hooks to strip CPF numbers, emails, authorization headers, and URL tokens before telemetry leaves the runtime.**

DeskcommCRM implements a comprehensive PII protection layer for Sentry 10 by centralizing all data-scrubbing logic in [`lib/sentry/scrub.ts`](https://github.com/melgarafael/DeskcommCRM/blob/main/lib/sentry/scrub.ts). This TypeScript module exports `sentryScrubHooks`, a collection of functions that attach to every Sentry initialization across Node.js, Edge, and client runtimes, ensuring that personally identifiable information is redacted before any report reaches Sentry's servers.

## Architecture of the PII Scrubbing System

### Centralized Hook Collection

The `sentryScrubHooks` object consolidates four distinct lifecycle hooks into one importable constant. According to the DeskcommCRM source code, these hooks attach to different telemetry types:

- **`beforeSend`**: Processes error events containing exceptions and messages
- **`beforeSendTransaction`**: Handles transaction events for performance monitoring
- **`beforeSendSpan`**: Cleans individual span data within distributed traces
- **`beforeBreadcrumb`**: Sanitizes breadcrumb metadata before attachment to the event stream

All four hooks are defined and exported from a single location to eliminate the "triple-copy bug" of duplicated sanitization logic across runtime-specific configuration files.

Link: [sentryScrubHooks definition, lines 48-88](https://github.com/melgarafael/DeskcommCRM/blob/main/lib/sentry/scrub.ts#L48-L88)

### Header Sanitization Strategy

Sensitive HTTP headers are identified using `isSensitiveHeader()` combined with `scrubHeaders()`. The implementation matches headers against a broad regular expression covering `Authorization`, `Cookie`, `API-Key`, `Token`, and similar patterns, then removes them entirely from the request object before transmission.

Link: [header scrubbing logic, lines 46-55](https://github.com/melgarafael/DeskcommCRM/blob/main/lib/sentry/scrub.ts#L46-L55)

## Step-by-Step PII Scrubbing Process

### 1. Event-Wide URL Redaction

The `scrubEventUrls()` function orchestrates the cleaning of all URL-related fields in an event. It applies `scrubUrl()` to request URLs, transaction names, and trace data to ensure no credential-bearing paths leave the system.

Link: [scrubEventUrls implementation, lines 30-45](https://github.com/melgarafael/DeskcommCRM/blob/main/lib/sentry/scrub.ts#L30-L45)

### 2. Credential Path and Query String Masking

Within `scrubUrl()`, two specific protections operate:

- **Credential Path Redaction**: Webhook and invite URLs containing tokens as the final path segment are masked using the `CREDENTIAL_PATH` regex. For example, `/webhooks/whatsapp/abcd1234` becomes `/webhooks/whatsapp/[TOKEN]`.
- **Query String Value Masking**: Parameter keys are preserved for debugging, but values are replaced with `[REDACTED]`.

Links: [credential path logic, lines 77-89](https://github.com/melgarafael/DeskcommCRM/blob/main/lib/sentry/scrub.ts#L77-L89); [query-string masking, lines 92-95](https://github.com/melgarafael/DeskcommCRM/blob/main/lib/sentry/scrub.ts#L92-L95)

### 3. Message Content Sanitization

Free-form text fields—including exception messages and log entries—are processed by `scrubMessage()`. This function applies regex patterns to detect and replace:

- **CPF numbers** (Brazilian tax IDs)
- **Phone numbers**
- **Email addresses**

Each pattern is substituted with a contextual placeholder like `[CPF]`, `[PHONE]`, or `[EMAIL]`.

Link: [message scrubbing implementation, lines 52-57](https://github.com/melgarafael/DeskcommCRM/blob/main/lib/sentry/scrub.ts#L52-L57)

### 4. OpenTelemetry Attribute Scrubbing

For distributed tracing compatibility, `scrubAttributes()` targets OpenTelemetry-style span attributes such as `url.full` and `http.url`. This ensures that PII embedded in trace metadata is equally protected, preventing leakage through alternative telemetry channels.

Link: [attribute scrubbing, lines 99-115](https://github.com/melgarafael/DeskcommCRM/blob/main/lib/sentry/scrub.ts#L99-L115)

## Cross-Runtime Implementation

The same `sentryScrubHooks` are injected into every Sentry initialization file, eliminating duplicate logic and ensuring consistent PII protection across environments.

### Node.js Server Configuration

```typescript
// lib/sentry/server.config.ts
import * as Sentry from '@sentry/nextjs';
import { sentryScrubHooks } from './scrub';

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  tracesSampleRate: 1.0,
  beforeSend: sentryScrubHooks.beforeSend,
  beforeSendTransaction: sentryScrubHooks.beforeSendTransaction,
  beforeSendSpan: sentryScrubHooks.beforeSendSpan,
  beforeBreadcrumb: sentryScrubHooks.beforeBreadcrumb,
});

```

### Edge Runtime Configuration

```typescript
// lib/sentry/edge.config.ts
import * as Sentry from '@sentry/nextjs';
import { sentryScrubHooks } from './scrub';

export const onError = Sentry.EdgeErrorHandler({
  beforeSend: sentryScrubHooks.beforeSend,
});

```

### Client-Side Configuration

```typescript
// lib/sentry/client.ts
import * as Sentry from '@sentry/nextjs';
import { sentryScrubHooks } from './scrub';

Sentry.init({
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
  beforeSend: sentryScrubHooks.beforeSend,
  beforeSendTransaction: sentryScrubHooks.beforeSendTransaction,
});

```

## Summary

- **Single source of truth**: All scrubbing logic resides in [`lib/sentry/scrub.ts`](https://github.com/melgarafael/DeskcommCRM/blob/main/lib/sentry/scrub.ts), preventing code duplication across server, edge, and client configurations.
- **Four-hook coverage**: Errors (`beforeSend`), transactions (`beforeSendTransaction`), spans (`beforeSendSpan`), and breadcrumbs (`beforeBreadcrumb`) are all sanitized through a unified interface.
- **Comprehensive patterns**: The system removes authorization headers, masks CPF/email/phone patterns, redacts tokens from URL paths, and strips query string values.
- **Runtime agnostic**: Identical hooks protect Node.js, Edge, and browser environments without modification, ensuring LGPD-compliant scrubbing regardless of execution context.

## Frequently Asked Questions

### What is Sentry's beforeSend hook and when does it execute?

The `beforeSend` hook is a Sentry SDK configuration callback that executes synchronously immediately before an error event is transmitted to Sentry's servers. In DeskcommCRM, this hook receives the event object, applies `scrubMessage()` and `scrubEventUrls()`, and returns the sanitized event or `null` to drop the report entirely.

### How does the scrubber handle sensitive HTTP headers?

The `scrubHeaders()` function iterates over request headers and removes any key matching the sensitive header regex, which includes `Authorization`, `Cookie`, `X-API-Key`, and token variants. This operation occurs within `beforeSend` before the event payload leaves the process, ensuring credentials never reach external servers.

### Which types of personally identifiable information does DeskcommCRM remove?

According to the source implementation in [`lib/sentry/scrub.ts`](https://github.com/melgarafael/DeskcommCRM/blob/main/lib/sentry/scrub.ts), the scrubber targets Brazilian CPF numbers, email addresses, phone numbers, bearer tokens in URL paths, and all query string values. It also strips sensitive HTTP headers that might contain session identifiers or API credentials.

### Can I use these hooks in both Node.js and Edge runtimes?

Yes. The `sentryScrubHooks` export is runtime-agnostic and imported into [`sentry.server.config.ts`](https://github.com/melgarafael/DeskcommCRM/blob/main/sentry.server.config.ts) for Node.js, [`sentry.edge.config.ts`](https://github.com/melgarafael/DeskcommCRM/blob/main/sentry.edge.config.ts) for Vercel Edge, and the client instrumentation for browsers. This ensures consistent PII scrubbing regardless of where the code executes.