Redaction Library Limitations with Complex Types
- Dominant language
- C#
- Stars
- 3.2k
- Forks
- 894
- Avg merge
- 1d 12h
- Merged PRs (30d)
- 23
Description
We’ve been integrating the .NET Redaction library to help mask sensitive identifiers in logs (e.g., IP addresses, user IDs), following both the official documentation and recent blog guidance. While the redaction works well in simple scenarios, we’ve encountered significant challenges with more complex data types and real-world logging patterns. Below is a summary of the issues:
---
### 🔴 **Issue 1: Redaction Does Not Work with Complex Types (e.g., `IPAddress`) in Log Properties**
When trying to redact an `IPAddress` field using `[IpAddress]`, the following logging methods do **not** result in redacted or even logged output:
```csharp
[LoggerMessage(
Level = LogLevel.Warning,
Message = "Missing IP Region.")]
internal static partial void MissingIPRegion(
this ILogger logger,
[IpAddress] string clientIP); // IP is not printed
[LoggerMessage(
Level = LogLevel.Warning,
Message = "Missing IP Region.")]
internal static partial void MissingIPRegion(
this ILogger logger,
[IpAddress] IPAddress clientIP); // IP is not printed
```
However, the redaction **does work** when the IP address is **directly referenced** in the message:
```csharp
[LoggerMessage(
Level = LogLevel.Warning,
Message = "Missing IP Region: {ClientIP}")]
internal static partial void MissingIPRegion(
this ILogger logger,
[IpAddress] string clientIP); // ✅ Redacted and printed
```
This indicates that redaction is only effective for complex types when they are explicitly included in the logger message. However, in our environment, logging values directly in the message string is **not permitted**.
The only workaround we’ve found is manually redacting and passing in a string:
```csharp
var ipRedactor = redactorProvider.GetRedactor(PicassoDataClassifications.IpAddress);
var redactedIP = ipRedactor.Redact(userContext.Caller.ClientIP.ToString());
logger.MissingIPRegion(redactedIP); // ✅ Works
```
This adds complexity and reduces the benefit of the Redaction library.
---
### 🔴 **Issue 2: \[LogProperties] Does Not Log Subclass Properties in Inherited Types**
We use inheritance for user identity types (e.g., `MicrosoftConsumerIdentity : MicrosoftIdentity : UserIdentity`), but when passing an instance of a derived type to a `[LogProperties]` parameter, only the **base class** fields are logged:
```csharp
[LoggerMessage(
Level = LogLevel.Warning,
Message = "Merge users failed for authenticated user.")]
internal static partial void MergeUsers(
this ILogger logger,
[LogProperties] UserIdentity sourceIdentity);
```
In this scenario, subclass fields like `Oid`, `Puid`, and `Anid` (which are annotated with redaction attributes like `[UserOid]`) are omitted from the log output.
We believe this is due to `[LogProperties]` only traversing the base class, not reflecting over subclass properties—even when the actual instance is of a derived type.
---
### 🙏 **Feature Requests / Suggestions**
1. **Improve `Redactor` support for complex types** such as `IPAddress` when not explicitly included in the log properties.
2. **Ensure `[LogProperties]` supports logging subclass-specific fields**, especially for scenarios where the log parameter is abstract or base class type.
3. Provide clear guidance in documentation around these limitations and recommended practices in restricted logging environments (e.g., where structured logging is enforced and message interpolation is not allowed).
Could you please consider the above suggestions or provide feedback/suggestions about how we can better integrate .Net Redaction library in our service? Really appreciate your help and guidance!
Contributor guide
Assessment
This issue has not been assessed yet.