Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion Web/Services/EmailService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,21 @@
private readonly EmailAccountConfig _emailAccountConfig;
private readonly ILogger<EmailService> _logger;

private static string MaskEmail(string email)
{
if (string.IsNullOrWhiteSpace(email)) return string.Empty;

var atIndex = email.IndexOf('@');
if (atIndex <= 0 || atIndex == email.Length - 1) return "***";

var localPart = email.Substring(0, atIndex);
var domainPart = email.Substring(atIndex + 1);

if (localPart.Length <= 1)
return "*@" + domainPart;

return localPart[0] + new string('*', Math.Max(1, localPart.Length - 1)) + "@" + domainPart;
}
Comment on lines +14 to +28
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MaskEmail preserves the full domain (and local-part length), which can still be considered private information (e.g., corporate domains) and may still match email-detection rules in code scanning. Consider masking the domain as well (e.g., keep only the TLD/first char) or logging a non-reversible identifier (hash) instead of any recognizable email form.

Copilot uses AI. Check for mistakes.

public EmailService(ILogger<EmailService> logger, IOptions<EmailAccountConfig> options)
{
Expand All @@ -21,7 +36,8 @@
public async Task<MessageSentEventArgs> SendEmailAsync(string subject, string body, string toName, string toAddress)
{
var sanitizedToAddress = toAddress.Replace(Environment.NewLine, "").Replace("\n", "").Replace("\r", "");
_logger.LogDebug("Sending email, subject: {Subject}, recipient: {ToAddress}", subject, sanitizedToAddress);
var maskedToAddress = MaskEmail(sanitizedToAddress);
_logger.LogDebug("Sending email, subject: {Subject}, recipient: {ToAddress}", subject, maskedToAddress);

Check warning

Code scanning / CodeQL

Exposure of private information Medium

Private data returned by
access to parameter email
is written to an external location.
Private data returned by
access to parameter email
is written to an external location.
Private data returned by
access to parameter email
is written to an external location.
Private data returned by
access to parameter email
is written to an external location.
Private data returned by
access to parameter email
is written to an external location.
Private data returned by
access to parameter email
is written to an external location.
Private data returned by
access to parameter email
is written to an external location.
Private data returned by
access to parameter email
is written to an external location.
Private data returned by
access to parameter email
is written to an external location.
Private data returned by
access to parameter email
is written to an external location.
Private data returned by
access to parameter email
is written to an external location.
Private data returned by
call to method MaskEmail
is written to an external location.
body += $"<br><p>This message was automatically sent by {BlogLink}, no need to reply.</p>";
return await EmailUtils.SendEmailAsync(_emailAccountConfig, subject, body, toName, toAddress);
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sanitizedToAddress is computed but the actual send still uses the original toAddress. Since toAddress originates from user input in some flows (e.g., link exchange) and may contain unexpected control characters, consider sending using the sanitized value (or performing strict validation and rejecting invalid addresses) to avoid header-injection style issues or unexpected exceptions in MailboxAddress parsing.

Suggested change
return await EmailUtils.SendEmailAsync(_emailAccountConfig, subject, body, toName, toAddress);
return await EmailUtils.SendEmailAsync(_emailAccountConfig, subject, body, toName, sanitizedToAddress);

Copilot uses AI. Check for mistakes.
}
Expand Down
Loading