Skip to content

How to keep personal data out of your logs

Updated 7 November 2026 · 6 min read

Logs are one of the most common places personal data ends up by accident. A developer adds console.log(user) to debug a signup, the line ships, and from then on every new user’s email address is copied into the log pipeline, the error tracker and the backups.

Nobody meant to collect it. It still counts.

Why it is a GDPR problem

Several parts of the GDPR apply at once.

  • Art. 5(1)(c), data minimisation. You should only process the personal data you need. A debugging log rarely needs an email address.
  • Art. 5(1)(e), storage limitation. Logs are often kept longer than the data in your database, and they are copied to more places.
  • Art. 32, security of processing. More people and tools can usually read logs than can read the production database.
  • Art. 17, the right to erasure. When someone asks you to delete their data, you have to find it. Data spread across log files, a log service and backups is hard to find and harder to delete.

SOC 2 (CC6.1) and ISO 27001 (A.8.11, data masking) ask for the same thing from the security side: sensitive data should be masked where people and tools don’t need it.

The patterns that cause it

Most cases come from a few habits.

// 1. Logging a field directly
logger.info(`signup ${user.email}`);

// 2. Logging a whole object
console.log("created user", user);

// 3. Logging a request body or headers
logger.debug({ body: req.body, headers: req.headers });

// 4. Logging an error that carries the data
logger.error(`payment failed for ${card.number}`, err);

The first is easy to spot. The second and third are worse, because the object may gain new personal fields later and nobody looks at the log line again. Headers often hold session tokens and cookies.

How to fix it

Mask the field

Keep enough to debug, drop the rest.

const mask = (email: string) => email.replace(/^(.).*(@.*)$/, "$1***$2");

logger.info(`signup ${mask(user.email)}`); // signup j***@example.com

Log an ID instead of the person

An internal ID lets you find the record when you need it, and the log alone tells a reader nothing about the person.

logger.info("signup", { userId: user.id });

Redact in one place

Most logging libraries can strip fields before anything is written. With pino, for example:

import pino from "pino";

const logger = pino({
  redact: ["email", "password", "token", "*.email", "req.headers.authorization", "req.headers.cookie"],
});

In Python’s standard logging module, a filter on the handler does the same job. Central redaction catches the cases a reviewer misses, but it only knows the field names you list, so keep the list next to your data model.

Turn off body logging in production

Request and response logging is useful while building. In production it copies every form a user submits into your logs. Keep it off, or log only the path and status.

Check what is already there

Fixing the code stops new data from arriving. What was logged before stays until it expires.

  1. Find out how long each log store keeps data, and shorten it where you can.
  2. Search existing logs for email patterns, and delete or let expire what you find.
  3. Write the retention period into your records of processing, so the answer is ready when someone asks.

What Lintsure checks

The personal data written to logs rule looks for log calls (console.log, logger.*, logging.*, print) that include fields such as email, phone, password, passport or card number. It ignores those words when they only appear in the message text, so console.error("email failed", err) is not flagged, while `${user.email}` is.

Related rules look for the same data leaving through other doors: analytics and tracking tools and URLs.

Lintsure finds the line and suggests the change. Through a coding agent, nothing is edited until you approve it.

Check your own code

Lintsure runs these checks on your machine and never uploads your code.

npx lintsure scan

This guide is our own reading of public texts, written for software teams. It is not legal advice and it doesn't cover your whole obligation, only the parts code can show. Ask a qualified person before any audit or decision. Disclaimer