Severity: High
Type: Security hardening
Scope: Notifications
Labels: security, good first issue
Description
EmailService.send (src/notifications/email.service.ts, lines ~98–110) calls transporter.sendMail and, when the JSON transport is used (the dev fallback), it then logs the full message body via this.logger.debug(\Email body preview: ${(info as any).message}`). The (info as any).message` payload includes recipient addresses, subject, and full HTML, which frequently contains donor names, campaign titles, and donation amounts.
Even if intended only for debug level, default NestJS log level can be raised by LOG_LEVEL=debug in non-production environments; once collected by a log shipper (Datadog, Loki, CloudWatch), the body leaves the application boundary.
Recommendation
- In dev mode, log only the subject and recipient, never the HTML body.
- Mask any user-identifying fields (donor name, email) before logging the structured preview line.
- If a body preview is genuinely useful in dev, gate it behind an explicit
EMAIL_PREVIEW=1 env flag and never honour it when NODE_ENV=production.
Severity: High
Type: Security hardening
Scope: Notifications
Labels:
security,good first issueDescription
EmailService.send(src/notifications/email.service.ts, lines ~98–110) callstransporter.sendMailand, when the JSON transport is used (the dev fallback), it then logs the full message body viathis.logger.debug(\Email body preview: ${(info as any).message}`). The(info as any).message` payload includes recipient addresses, subject, and full HTML, which frequently contains donor names, campaign titles, and donation amounts.Even if intended only for
debuglevel, default NestJS log level can be raised byLOG_LEVEL=debugin non-production environments; once collected by a log shipper (Datadog, Loki, CloudWatch), the body leaves the application boundary.Recommendation
EMAIL_PREVIEW=1env flag and never honour it whenNODE_ENV=production.