Skip to content

C#: Fix false positives in cs/log-forging for extension methods#21498

Open
Gregro wants to merge 4 commits intogithub:mainfrom
Gregro:csharp/fix-log-forging-extension-methods
Open

C#: Fix false positives in cs/log-forging for extension methods#21498
Gregro wants to merge 4 commits intogithub:mainfrom
Gregro:csharp/fix-log-forging-extension-methods

Conversation

@Gregro
Copy link

@Gregro Gregro commented Mar 19, 2026

The log forging query previously treated arguments to all extension methods on logger types as direct sinks, bypassing interprocedural analysis. This caused false positives when extension methods sanitize input internally.

Now, arguments to extension methods with source code are excluded from being treated as direct sinks, allowing interprocedural taint tracking through extension method bodies. Framework extension methods (without source code) remain as sinks.

Fixes #15824

@Gregro Gregro marked this pull request as ready for review March 19, 2026 18:29
@Gregro Gregro requested a review from a team as a code owner March 19, 2026 18:29
Copilot AI review requested due to automatic review settings March 19, 2026 18:29
@Gregro Gregro force-pushed the csharp/fix-log-forging-extension-methods branch from 86f9414 to 2539358 Compare March 19, 2026 18:30
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates the C# cs/log-forging dataflow to avoid treating user-defined logger extension methods as sinks, reducing false positives while still flagging framework logging extension methods via Models as Data.

Changes:

  • Refines the log-forging sink definition to focus on direct instance calls on logger types rather than all calls with logger arguments.
  • Adds Models-as-Data sink models for Microsoft.Extensions.Logging.LoggerExtensions logging APIs.
  • Extends CWE-117 test coverage to include safe/unsafe user-defined extension methods and updates expected results + changelog.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.expected Updates expected results to reflect new sink modeling and interprocedural flows through extension methods.
csharp/ql/test/query-tests/Security Features/CWE-117/LogForging.cs Adds user-defined logger extension methods (safe/unsafe) to validate reduced false positives.
csharp/ql/lib/semmle/code/csharp/security/dataflow/LogForgingQuery.qll Adjusts sink definition intended to exclude extension methods from being treated as sinks.
csharp/ql/lib/ext/Microsoft.Extensions.Logging.Sinks.model.yml Introduces explicit sink models for Microsoft.Extensions.Logging.LoggerExtensions APIs.
csharp/ql/lib/change-notes/2026-03-19-fix-log-forging-extension-methods.md Documents the analysis change and new MaD modeling.

Copy link
Contributor

@hvitved hvitved left a comment

Choose a reason for hiding this comment

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

Thanks a lot for your contribution, much appreciated.

* which are analyzed interprocedurally.
*/
private class LogForgingLogMessageSink extends Sink, LogMessageSink { }
private class LogForgingLogMessageSink extends Sink {
Copy link
Contributor

Choose a reason for hiding this comment

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

How about this instead?

private class LogForgingLogMessageSink extends Sink, LogMessageSink {
  LogForgingLogMessageSink() {
    not exists(MethodCall mc, Method m |
      this.getExpr() = mc.getAnArgument() and
      m.fromSource()
    )
  }
}

Then it shouldn't be necessary to add the explicit models.

Copy link
Author

Choose a reason for hiding this comment

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

Good suggestion! I updated to:

private class LogForgingLogMessageSink extends Sink, LogMessageSink {
  LogForgingLogMessageSink() {
    not exists(ExtensionMethodCall mc |
      this.getExpr() = mc.getAnArgument() and
      mc.getTarget().fromSource()
    )
  }
}

Which is your suggestion, but I used ExtensionMethodCall instead of MethodCall because the test case implements its own class ILogger (source code available) and the existing tests fail unless I only exclude extension methods.

@github-actions
Copy link
Contributor

⚠️ The head of this PR and the base branch were compared for differences in the framework coverage reports. The generated reports are available in the artifacts of this workflow run. The differences will be picked up by the nightly job after the PR gets merged.

Click to show differences in coverage

csharp

Generated file changes for csharp

  • Changes to framework-coverage-csharp.rst:
-    Others,"``Amazon.Lambda.APIGatewayEvents``, ``Amazon.Lambda.Core``, ``Dapper``, ``ILCompiler``, ``ILLink.RoslynAnalyzer``, ``ILLink.Shared``, ``ILLink.Tasks``, ``Internal.IL``, ``Internal.Pgo``, ``Internal.TypeSystem``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.AspNetCore.Components``, ``Microsoft.AspNetCore.Http``, ``Microsoft.AspNetCore.Mvc``, ``Microsoft.AspNetCore.WebUtilities``, ``Microsoft.CSharp``, ``Microsoft.Data.SqlClient``, ``Microsoft.Diagnostics.Tools.Pgo``, ``Microsoft.DotNet.Build.Tasks``, ``Microsoft.DotNet.PlatformAbstractions``, ``Microsoft.EntityFrameworkCore``, ``Microsoft.Extensions.Caching.Distributed``, ``Microsoft.Extensions.Caching.Memory``, ``Microsoft.Extensions.Configuration``, ``Microsoft.Extensions.DependencyInjection``, ``Microsoft.Extensions.DependencyModel``, ``Microsoft.Extensions.Diagnostics.Metrics``, ``Microsoft.Extensions.FileProviders``, ``Microsoft.Extensions.FileSystemGlobbing``, ``Microsoft.Extensions.Hosting``, ``Microsoft.Extensions.Http``, ``Microsoft.Extensions.Logging``, ``Microsoft.Extensions.Options``, ``Microsoft.Extensions.Primitives``, ``Microsoft.Interop``, ``Microsoft.JSInterop``, ``Microsoft.NET.Build.Tasks``, ``Microsoft.VisualBasic``, ``Microsoft.Win32``, ``Mono.Linker``, ``MySql.Data.MySqlClient``, ``NHibernate``, ``Newtonsoft.Json``, ``SourceGenerators``, ``Windows.Security.Cryptography.Core``",60,2406,162,4
+    Others,"``Amazon.Lambda.APIGatewayEvents``, ``Amazon.Lambda.Core``, ``Dapper``, ``ILCompiler``, ``ILLink.RoslynAnalyzer``, ``ILLink.Shared``, ``ILLink.Tasks``, ``Internal.IL``, ``Internal.Pgo``, ``Internal.TypeSystem``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.AspNetCore.Components``, ``Microsoft.AspNetCore.Http``, ``Microsoft.AspNetCore.Mvc``, ``Microsoft.AspNetCore.WebUtilities``, ``Microsoft.CSharp``, ``Microsoft.Data.SqlClient``, ``Microsoft.Diagnostics.Tools.Pgo``, ``Microsoft.DotNet.Build.Tasks``, ``Microsoft.DotNet.PlatformAbstractions``, ``Microsoft.EntityFrameworkCore``, ``Microsoft.Extensions.Caching.Distributed``, ``Microsoft.Extensions.Caching.Memory``, ``Microsoft.Extensions.Configuration``, ``Microsoft.Extensions.DependencyInjection``, ``Microsoft.Extensions.DependencyModel``, ``Microsoft.Extensions.Diagnostics.Metrics``, ``Microsoft.Extensions.FileProviders``, ``Microsoft.Extensions.FileSystemGlobbing``, ``Microsoft.Extensions.Hosting``, ``Microsoft.Extensions.Http``, ``Microsoft.Extensions.Logging``, ``Microsoft.Extensions.Options``, ``Microsoft.Extensions.Primitives``, ``Microsoft.Interop``, ``Microsoft.JSInterop``, ``Microsoft.NET.Build.Tasks``, ``Microsoft.VisualBasic``, ``Microsoft.Win32``, ``Mono.Linker``, ``MySql.Data.MySqlClient``, ``NHibernate``, ``Newtonsoft.Json``, ``SourceGenerators``, ``Windows.Security.Cryptography.Core``",60,2406,190,4
-    Totals,,108,14908,415,9
+    Totals,,108,14908,443,9
  • Changes to framework-coverage-csharp.csv:
- Microsoft.Extensions.Logging,,,110,,,,,,,,,,,,,,,,,,,29,81
+ Microsoft.Extensions.Logging,28,,110,,,,,,,,,28,,,,,,,,,,29,81

@Gregro Gregro force-pushed the csharp/fix-log-forging-extension-methods branch from 8804f85 to a59c865 Compare March 21, 2026 20:07
@Gregro Gregro requested a review from hvitved March 21, 2026 20:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

False positive - Log entries created from user input (cs/log-forging)

3 participants