Masking a sandbox replaces PII in tables and fields, but debug logs capture whatever the runtime actually processed, and that includes real customer data if a log was generated before masking ran, or if a system pulls production data through an integration mid-session. Salesforce debug logs are a separate storage layer from your object data. Most masking tools never touch them.

This matters more than it sounds like it should. Admins spend weeks validating that Account, Contact, and Case records are clean, then hand a sandbox to a developer who turns on debug logging to troubleshoot a trigger. Within minutes, that log contains an unmasked email address, a phone number, maybe a national ID that got pulled in through a callout before the masking job ever ran.

Why debug logs bypass masking entirely

A masking job operates on persisted records. It runs after a sandbox refresh, scans target objects and fields, and overwrites values according to your masking rules. Debug logs are generated on demand, by trace flags, and they capture the state of execution at the moment code runs, not the state of the database after a masking pass.

If someone enables a trace flag on a user or a class before masking completes, the log captures live values mid-transition. If someone enables it after masking, but a batch job or integration re-populates a field from an external, unmasked source, the log captures that too. Either way, the log file sits in a completely different part of the platform than the records your masking tool scanned.

Debug logs also capture more than field values. They log SOQL query results, exception messages, and variable dumps from Apex. A poorly written trigger that logs "Contact created: " + con.Email__c will happily print a real email address straight into a log file, regardless of what the underlying record looks like an hour later.

What actually shows up in a debug log

Debug logs are verbose by design. At DEBUG or FINEST levels, Salesforce logs variable assignments, SOQL statements with bind variables, and the full text of exceptions, including stack traces that sometimes embed record data. Developers debugging integration failures routinely log entire request and response bodies.

Consider a common pattern: a callout to an external billing system fails, and the catch block logs the request payload for troubleshooting. That payload might include a customer's full name, billing address, and card-holder details if the integration wasn't built with logging hygiene in mind. None of that data lives in a Salesforce field your masking rules target. It lives in a log entry that expires after a set retention window, but sits fully readable until it does.

Here's the part that catches teams off guard: log visibility isn't limited to the person who set the trace flag. Anyone with the right permission, View All Data or the Debug Logs permission specifically, can open that log and read it. In a sandbox shared across a QA team, a support contractor, and two outsourced developers, that's a wide surface for something that was supposed to be masked.

Event Monitoring and log files: a second blind spot

Event Monitoring compounds the problem. Login history, API usage logs, and Lightning event logs capture record IDs, user actions, and sometimes field-level data depending on the event type. These logs are designed for security monitoring, not for privacy protection, and they weren't built with masking in mind.

API event logs in particular can include query parameters and response metadata that reference real values, especially in orgs where integration users pull data through REST calls tied to production credentials mistakenly pointed at a sandbox. I've seen this happen more than once: a middleware platform configured against a full-copy sandbox, still authenticated with a production-scoped connected app, logging every field it touches.

Data Loader exports have a documented blind spot for similar reasons, and the same logic applies here: any tool or log that captures data outside the object model itself needs its own review, because a masking policy scoped only to fields and records leaves the surrounding telemetry untouched.

Who can see these logs and why that matters for GDPR

Under GDPR, a masked sandbox is supposed to reduce your processing footprint for personal data. If debug logs inside that same sandbox still contain unmasked names, emails, or identifiers, you haven't actually reduced anything. You've just relocated the exposure from an object record to a log file, and log files are frequently less access-controlled than the records they came from.

Debug logs default to a 24-hour retention in most orgs, which sounds reassuring until you account for how many people can view a log within that window: any admin, any user with the Debug Logs permission, and any developer actively troubleshooting. That's not a small audience, and a 24-hour window is plenty of time for a screenshot, a copy-paste into a ticket, or an export to a local machine.

An auditor reviewing your sandbox masking controls will ask about this if they're any good. Saying "our fields are masked" doesn't answer the question "where else could this data have been written." Log retention and trace flag governance are part of that answer whether or not your masking vendor mentions them.

Building a debug log policy that doesn't undo your masking work

The fix isn't complicated, but it does require treating logs as part of your masking scope rather than an afterthought. Start with trace flag discipline: restrict who can enable debug logging in masked sandboxes, and require that flags get set only after a masking job has fully completed, never mid-refresh.

Second, tighten log-level verbosity. Most troubleshooting doesn't need FINEST-level SOQL bind variable logging. Setting Apex Code and System logging to WARN or ERROR for routine debugging, and reserving FINEST for isolated, time-boxed sessions, cuts the volume of captured data significantly without slowing anyone down.

Third, audit the Debug Logs permission itself. It's often granted broadly to developer profiles by default and rarely revisited. Restricting it to a named list of users who actually need it, and pairing that with a shorter retention window where your Salesforce edition allows it, closes most of the exposure window.

ControlWhat it preventsEffort to implement
Restrict Debug Logs permissionBroad internal visibility into log contentsLow
Enforce trace flags post-masking onlyLive data captured mid-refreshLow
Lower default log verbosityField values and payloads in logged exceptionsMedium
Audit integration user credentials in logsProduction-scoped API calls exposing real dataMedium
Review Event Monitoring log accessField-level data in API and Lightning event logsHigh

Where this fits in a broader masking strategy

None of this replaces field-level masking. It supplements it. A masking tool that overwrites Account and Contact data correctly is still doing the core job right; the debug log gap is a separate control, not a failure of the masking engine itself.

I'd argue this is the single most overlooked corner of Salesforce sandbox governance, precisely because it doesn't live in the data model at all. Teams audit objects, fields, and permission sets obsessively, then leave debug logging wide open because nobody thinks of it as a data store. It is one, and it needs the same scrutiny as any other place PII can land.

Treat trace flags, log retention, and the Debug Logs permission as part of your masking checklist, not a separate security conversation. The masking job protects the database. Your log policy protects everything that runs on top of it.

Frequently Asked Questions

Do Salesforce debug logs get masked when I run a data masking tool?

No. Masking tools operate on persisted object records, while debug logs are generated separately by trace flags and capture runtime execution data. A masking job can fully clean your Account and Contact records while an active debug log still contains unmasked field values from that same session.

Can a debug log contain real customer PII even after a sandbox refresh?

Yes, if a trace flag is enabled before masking completes, or if a callout pulls unmasked data from an external system after the refresh. The log captures whatever the code actually processed at execution time, independent of what the underlying records look like afterward.

Who can view debug logs in a Salesforce sandbox?

Anyone assigned the Debug Logs permission or View All Data, which is often granted broadly to developer and admin profiles by default. In a shared sandbox with contractors or outsourced developers, that can mean a wider audience than the team expects.

How long do Salesforce debug logs stay accessible?

Debug logs typically expire after 24 hours by default, though this varies by log type and org configuration. That window is still long enough for the data to be copied, exported, or pasted into a ticketing system before it disappears.

What's the quickest fix for the debug log masking gap?

Restrict the Debug Logs permission to a short list of named users, require trace flags be enabled only after masking jobs finish, and lower default log verbosity so exceptions and SOQL results stop capturing full field values. These three changes close most of the exposure without adding new tooling.