We're sorry but this app doesn't work properly without JavaScript enabled. Please enable it to continue.

This lesson's interactive features are locked, please to keep using them

Sanitizing Logs

Logs are great for observability, but they shouldn't be treated like a vault. They often outlive the requests that produced them, get copied into third-party tools and backups, and are readable by more people than the production database.

Of course, you should always do your best to keep logs private, but you should also avoid putting secrets in logs in the first place.

Secrets in Logs

Imagine an app that logs the working credential from every password-reset request:

// broken: reset credentials are written to the log
logEvent("password_reset_request", {
  accountId: account.id,
  success: true,
  resetToken,
  resetLink,
});

Anyone who can read the log can now take over that account. Yikers.

Log What You Need

Log only what a developer or system administrator will actually need to investigate the system. A login event usually needs the account ID and outcome, not the session credential that proves the user is authenticated:

// fixed: useful context without the session credential
logEvent("login_attempt", {
  accountId: account.id,
  success: true,
});

For a codebase with many structured log calls, centralized redaction is a great idea:

const REDACTED_KEYS = new Set([
  "sessionId",
  "resetToken",
  "resetLink",
  "secret",
  "medicalNotes",
]);

type LogFields = Record<string, unknown>;

function redact(fields: LogFields): LogFields {
  return Object.fromEntries(
    Object.entries(fields).map(([key, value]) => [
      key,
      REDACTED_KEYS.has(key) ? "[REDACTED]" : value,
    ]),
  );
}

function logEvent(eventName: string, fields: LogFields = {}): void {
  appendFileSync(
    logPath,
    `${JSON.stringify({
      timestamp: new Date().toISOString(),
      event: eventName,
      ...redact(fields),
    })}\n`,
  );
}

This exact-key pattern only redacts the top-level fields it knows about. It won't catch apiToken under a different name or inside a nested object. Some structured logging libraries, like Pino, provide tested, more powerful redaction.

Redaction is a backstop, not permission to log everything. Don't even try to log a secret when the event doesn't need it.

Assignment

Bearly Secure's structured logs contain session IDs, reset credentials, TOTP secrets, internal notes, and storage paths. Redact sensitive fields centrally before writing them.

With Bearly Secure still running, run and submit the CLI tests from the project root.