👉🏼 Click here to Join I ❤️ .NET WhatsApp Channel to get 🔔 notified about new articles and other updates.
Improve Data Security by Redacting Logs in .NET

Improve Data Security by Redacting Logs in .NET

Author - Abdul Rahman (Content Writer)

Security

1 Articles

Improve

Table of Contents

  1. What we gonna do?
  2. Why we gonna do?
  3. How we gonna do?
  4. Summary

What we gonna do?

Ever thought your logs were safe, only to discover sensitive data like social security numbers or emails hiding in plain sight? Logging in .NET isn't just about writing messages—it's about protecting your users and your business. In this article, we'll break down the critical considerations for secure, compliant logging in C# applications.

Why we gonna do?

Here's the thing: logging everything is tempting, but it can quickly turn into a compliance nightmare. Accidentally capturing Personally Identifiable Information (PII) in logs exposes you to risks—think GDPR fines, angry users, and sleepless nights.

Why should you care? Because even with authorization checks and admin-only endpoints, sensitive data can slip through if you're not careful. Passing entire objects to loggers or serializers might seem convenient, but it's a recipe for disaster if those objects contain private or restricted information.

That's why .NET developers need to be intentional about what gets logged, how it's classified, and how it's protected. Logging isn't just a technical concern—it's a business-critical responsibility.

How we gonna do?

Let's get practical. Here's how you can log responsibly and avoid common pitfalls:

Create a Simple Console Application. After creating a new Console Application, Install Microsoft.Extensions.Hosting Nuget package.

The initial setup should look like below


using System.Text.Json;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

Console.WriteLine("Log Redaction Demo");

var builder = Host.CreateApplicationBuilder(args);

builder.Services.AddLogging(options =>
{
  options.AddJsonConsole(o => o.JsonWriterOptions = new JsonWriterOptions { Indented = true });
});

var host = builder.Build();

var customer = new Customer
{
  Name = "Abdul Rahman",
  Email = "abdul.rahman@example.com",
  PhoneNumber = "9876543210",
  Address = "Dubai Bus Stand, Dubai Kuruku Santhu, Dubai",
  AadharNumber = "0123-4567-8910"
};

var logger = host.Services.GetRequiredService<ILogger<;Program>>();

logger.LogInformation("This is a log message with sensitive data: {customer}", customer);

await host.RunAsync();

Console.ReadLine();

public sealed class Customer
{
  public string Name { get; set; } = string.Empty;
  public string Email { get; set; } = string.Empty;
  public string PhoneNumber { get; set; } = string.Empty;
  public string Address { get; set; } = string.Empty;
  public string AadharNumber { get; set; } = string.Empty;
}

Now when you run the app, you should see the below logs.


------------------------------------------------------------------------------
You may only use the Microsoft Visual Studio .NET/C/C++ Debugger (vsdbg) with
Visual Studio Code, Visual Studio or Visual Studio for Mac software to help you
develop and test your applications.
------------------------------------------------------------------------------
Log Redaction Demo
{
  "EventId": 0,
  "LogLevel": "Information",
  "Category": "Program",
  "Message": "This is a log message with sensitive data: Customer",
  "State": {
    "Message": "This is a log message with sensitive data: Customer",
    "customer": "Customer",
    "{OriginalFormat}": "This is a log message with sensitive data: {customer}"
  }
}

Nothing seems to be wrong in the above log. Now lets install Microsoft.Extensions.Telemetry Nuget package and create a static logger class which will source generate a specific logger for Customer.


public static partial class Log
{
  [LoggerMessage(LogLevel.Information, "Customer {Customer}")]
  public static partial void LogCustomer(this ILogger logger, [LogProperties] Customer customer);
}

Now lets Log the same customer object using above logger.


logger.LogCustomer(customer);

Now the Log contains all details including sensitive PII information.


------------------------------------------------------------------------------
You may only use the Microsoft Visual Studio .NET/C/C++ Debugger (vsdbg) with
Visual Studio Code, Visual Studio or Visual Studio for Mac software to help you
develop and test your applications.
------------------------------------------------------------------------------
Log Redaction Demo
{
  "EventId": 956896052,
  "LogLevel": "Information",
  "Category": "Program",
  "Message": "Customer Customer",
  "State": {
    "Message": "customer.AadharNumber=0123-4567-8910,customer.Address=Dubai Bus Stand, Dubai Kuruku Santhu, Dubai,customer.PhoneNumber=9876543210,customer.Email=abdul.rahman@example.com,customer.Name=Abdul Rahman,Customer=Customer,{OriginalFormat}=Customer {Customer}",
    "customer.AadharNumber": "0123-4567-8910",
    "customer.Address": "Dubai Bus Stand, Dubai Kuruku Santhu, Dubai",
    "customer.PhoneNumber": "9876543210",
    "customer.Email": "abdul.rahman@example.com",
    "customer.Name": "Abdul Rahman",
    "Customer": "Customer",
    "{OriginalFormat}": "Customer {Customer}"
  }
}

Now lets work on to make sure only necessary information is logged. lets Now install Microsoft.Extensions.Compliance.Redaction and Microsoft.Extensions.Compliance.Abstractions Nuget packages.

Now lets Define what type of data were are working with. lets Define a class TaxonomyClassifications That give use an instance of type of data we are working. lets also create a attribute for each type of data.


using Microsoft.Extensions.Compliance.Classification;

public static class TaxonomyClassifications
{
    /// <summary>
    /// Anyone can see the information
    /// </summary>
    public static DataClassification PublicInformation => new("PublicTaxonomyClassification", nameof(PublicInformation));

    /// <summary>
    /// Only visible to user themselves
    /// </summary>
    public static DataClassification PrivateInformation => new("PrivateTaxonomyClassification", nameof(PrivateInformation));

    /// <summary>
    /// Only for internal use or employees
    /// </summary>
    public static DataClassification InternalInformation => new("InternalTaxonomyClassification", nameof(InternalInformation));

    /// <summary>
    /// Sensitive PII, never log or share
    /// </summary>
    public static DataClassification RedactedInformation => new("RedactedTaxonomyClassification", nameof(RedactedInformation));
}

public sealed class PrivateInformationAttribute() : DataClassificationAttribute(TaxonomyClassifications.PrivateInformation);
public sealed class PublicInformationAttribute() : DataClassificationAttribute(TaxonomyClassifications.PublicInformation);
public sealed class InternalInformationAttribute() : DataClassificationAttribute(TaxonomyClassifications.InternalInformation);
public sealed class RedactedInformationAttribute() : DataClassificationAttribute(TaxonomyClassifications.RedactedInformation);

Now lets add the attributes to the Customer class properties. This will help us classify the data and redact sensitive information.


public sealed class Customer
{
  public string Name { get; set; } = string.Empty;
  public string Email { get; set; } = string.Empty;
  public string PhoneNumber { get; set; } = string.Empty;
  public string Address { get; set; } = string.Empty;
  [RedactedInformation] // This field will be redacted in logs
  public string AadharNumber { get; set; } = string.Empty;
}

Now if were run the logs should look like


------------------------------------------------------------------------------
You may only use the Microsoft Visual Studio .NET/C/C++ Debugger (vsdbg) with
Visual Studio Code, Visual Studio or Visual Studio for Mac software to help you
develop and test your applications.
------------------------------------------------------------------------------
Log Redaction Demo
{
  "EventId": 956896052,
  "LogLevel": "Information",
  "Category": "Program",
  "Message": "Customer Customer",
  "State": {
    "Message": "customer.Address=Dubai Bus Stand, Dubai Kuruku Santhu, Dubai,customer.PhoneNumber=9876543210,customer.Email=abdul.rahman@example.com,customer.Name=Abdul Rahman,Customer=Customer,{OriginalFormat}=Customer {Customer},customer.AadharNumber=\u003Comitted\u003E ([RedactedTaxonomyClassification:RedactedInformation])",
    "customer.Address": "Dubai Bus Stand, Dubai Kuruku Santhu, Dubai",
    "customer.PhoneNumber": "9876543210",
    "customer.Email": "abdul.rahman@example.com",
    "customer.Name": "Abdul Rahman",
    "Customer": "Customer",
    "{OriginalFormat}": "Customer {Customer}"
  }
}

Since the source generated logger is not aware of How to handle redaction the Log hashing TaxonomyClassifications attribute present. But this still leaves use in a better position. Now lets improve this By doing EnableRedaction in logging configuration.


builder.Services.AddLogging(options =>
{
    options.AddJsonConsole(o => o.JsonWriterOptions = new JsonWriterOptions { Indented = true });
    options.EnableRedaction();
});

This again leaves us with all data getting displayed in logs.


------------------------------------------------------------------------------
You may only use the Microsoft Visual Studio .NET/C/C++ Debugger (vsdbg) with
Visual Studio Code, Visual Studio or Visual Studio for Mac software to help you
develop and test your applications.
------------------------------------------------------------------------------
Log Redaction Demo
{
  "EventId": 956896052,
  "LogLevel": "Information",
  "Category": "Program",
  "Message": "Customer Customer",
  "State": {
    "Message": "Microsoft.Extensions.Logging.ExtendedLogger\u002BModernTagJoiner",
    "customer.AadharNumber": "0123-4567-8910:customer.AadharNumber",
    "customer.Address": "Dubai Bus Stand, Dubai Kuruku Santhu, Dubai",
    "customer.PhoneNumber": "9876543210",
    "customer.Email": "abdul.rahman@example.com",
    "customer.Name": "Abdul Rahman",
    "Customer": "Customer",
    "{OriginalFormat}": "Customer {Customer}"
  }
}

lets Now enable support for redaction those erase data while logging.


using Microsoft.Extensions.Compliance.Redaction;
builder.Services.AddRedaction(options =>
{
    options.SetRedactor<ErasingRedactor>([TaxonomyClassifications.RedactedInformation]);
});

Now the log gets erased. Note that this works out of box with source generated loggers. if you are using different sink or non source generated logging, you need to take a different approach.


------------------------------------------------------------------------------
You may only use the Microsoft Visual Studio .NET/C/C++ Debugger (vsdbg) with
Visual Studio Code, Visual Studio or Visual Studio for Mac software to help you
develop and test your applications.
------------------------------------------------------------------------------
Log Redaction Demo
{
  "EventId": 956896052,
  "LogLevel": "Information",
  "Category": "Program",
  "Message": "Customer Customer",
  "State": {
    "Message": "Microsoft.Extensions.Logging.ExtendedLogger\u002BModernTagJoiner",
    "customer.AadharNumber": "",
    "customer.Address": "Dubai Bus Stand, Dubai Kuruku Santhu, Dubai",
    "customer.PhoneNumber": "9876543210",
    "customer.Email": "abdul.rahman@example.com",
    "customer.Name": "Abdul Rahman",
    "Customer": "Customer",
    "{OriginalFormat}": "Customer {Customer}"
  }
}

Now you can see the logs getting erased. we can also bring our own custom redactors those do custom manipulation and display custom text.


public class RedactedRedactor : Redactor
{
    public override int GetRedactedLength(ReadOnlySpan<char> input)
    {
        return "**[REDACTED]**".Length;
    }

    public override int Redact(ReadOnlySpan<char> source, Span<char> destination)
    {
        "**[REDACTED]**".CopyTo(destination);

        return destination.Length;
    }
}

// in program.cs
builder.Services.AddRedaction(options =>
{
    options.SetRedactor<RedactedRedactor>([TaxonomyClassifications.RedactedInformation]);
});

Now running the app gives the below logs in much better format.


------------------------------------------------------------------------------
You may only use the Microsoft Visual Studio .NET/C/C++ Debugger (vsdbg) with
Visual Studio Code, Visual Studio or Visual Studio for Mac software to help you
develop and test your applications.
------------------------------------------------------------------------------
Log Redaction Demo
{
  "EventId": 956896052,
  "LogLevel": "Information",
  "Category": "Program",
  "Message": "Customer Customer",
  "State": {
    "Message": "Microsoft.Extensions.Logging.ExtendedLogger\u002BModernTagJoiner",
    "customer.AadharNumber": "**[REDACTED]**",
    "customer.Address": "Dubai Bus Stand, Dubai Kuruku Santhu, Dubai",
    "customer.PhoneNumber": "9876543210",
    "customer.Email": "abdul.rahman@example.com",
    "customer.Name": "Abdul Rahman",
    "Customer": "Customer",
    "{OriginalFormat}": "Customer {Customer}"
  }
}

Finally always review the logs. Don't assume your logger is doing the right thing. Regularly inspect your logs to ensure no sensitive data is leaking. Consider custom redactors for extra control—hashing, encrypting, or replacing values as needed.

Summary

Logging in .NET is more than just writing messages—it's about protecting your users, your business, and your reputation. By classifying data, enabling redaction, and securing audit logs, you can avoid compliance headaches and keep sensitive information out of the wrong hands.

👉🏼 Click here to Join I ❤️ .NET WhatsApp Channel to get 🔔 notified about new articles and other updates.
  • Security
  • Logging
  • PII
  • Compliance
  • Redaction
  • Non-Repudiation
  • Security