csharp.lang.best-practice.structured-logging.structured-logging
semgrep
Author
unknown
Download Count*
License
String interpolation in log message obscures the distinction between variables and the log message. Use structured logging instead, where the variables are passed as additional arguments and the interpolation is performed by the logging library. This reduces the possibility of log injection and makes it easier to search through logs.
Run Locally
Run in CI
Defintion
rules:
- id: structured-logging
patterns:
- pattern-either:
- pattern: $LOG.Debug($"...")
- pattern: $LOG.Error($"...")
- pattern: $LOG.Fatal($"...")
- pattern: $LOG.Information($"...")
- pattern: $LOG.Verbose($"...")
- pattern: $LOG.Warning($"...")
- pattern: $LOG.LogCritical($"...")
- pattern: $LOG.LogDebug($"...")
- pattern: $LOG.LogError($"...")
- pattern: $LOG.LogInformation($"...")
- pattern: $LOG.LogTrace($"...")
- pattern: $LOG.LogWarning($"...")
- pattern: $LOG.Info($"...")
- pattern: $LOG.Trace($"...")
- pattern: $LOG.Warn($"...")
- metavariable-regex:
metavariable: $LOG
regex: .*(log|LOG|Log)
message: String interpolation in log message obscures the distinction between
variables and the log message. Use structured logging instead, where the
variables are passed as additional arguments and the interpolation is
performed by the logging library. This reduces the possibility of log
injection and makes it easier to search through logs.
languages:
- csharp
severity: INFO
metadata:
cwe:
- "CWE-117: Improper Output Neutralization for Logs"
owasp:
- A09:2021 - Security Logging and Monitoring Failures
technology:
- .net
- serilog
- nlog
confidence: LOW
references:
- https://github.com/NLog/NLog/wiki/How-to-use-structured-logging
- https://softwareengineering.stackexchange.com/questions/312197/benefits-of-structured-logging-vs-basic-logging
category: best-practice
subcategory:
- audit
likelihood: LOW
impact: LOW
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
vulnerability_class:
- Improper Validation
Examples
structured-logging.cs
using Microsoft.Extensions.Logging;
using Serilog;
using NLog;
class Program
{
public static void SerilogSample()
{
using var serilog = new LoggerConfiguration().WriteTo.Console().CreateLogger();
var position = new { Latitude = 25, Longitude = 134 };
var elapsedMs = 34;
// ok: structured-logging
serilog.Information("Processed {@Position} in {Elapsed:000} ms.", position, elapsedMs);
// ruleid: structured-logging
serilog.Information($"Processed {position} in {elapsedMs:000} ms.");
}
public static void MicrosoftSample()
{
var loggerFactory = LoggerFactory.Create(builder => {
builder.AddConsole();
}
);
var logger = loggerFactory.CreateLogger<Program>();
var position = new { Latitude = 25, Longitude = 134 };
var elapsedMs = 34;
// ok: structured-logging
logger.LogInformation("Processed {@Position} in {Elapsed:000} ms.", position, elapsedMs);
// ruleid: structured-logging
logger.LogInformation($"Processed {position} in {elapsedMs:000} ms.");
}
public static void NLogSample()
{
var logger = NLog.LogManager.Setup().LoadConfiguration(builder => {
builder.ForLogger().WriteToConsole();
}).GetCurrentClassLogger();
var position = new { Latitude = 25, Longitude = 134 };
var elapsedMs = 34;
// ok: structured-logging
logger.Info("Processed {@Position} in {Elapsed:000} ms.", position, elapsedMs);
// ruleid: structured-logging
logger.Info($"Processed {position} in {elapsedMs:000} ms.");
// try with different name
var _LOG = logger;
// ruleid: structured-logging
_LOG.Info($"Processed {position} in {elapsedMs:000} ms.");
}
public static void NotLogging()
{
// System.Web.TraceContext.Warn does not support structured logging
var traceContext = new FakeTraceContext();
// ok: structured-logging
traceContext.Warn($"hello world");
}
public static void Main()
{
SerilogSample();
MicrosoftSample();
NLogSample();
NotLogging();
}
}
class FakeTraceContext
{
public void Warn(string foo) { }
}
Short Link: https://sg.run/nwNb