Improved data security by enforcing provider filtering (#290)

This commit is contained in:
Thorsten Sommer authored and GitHub committed 2025-02-23 15:05:29 +01:00
1 parent bfc9f2ea1d
commit 9bd79bd3a0
22 files changed
+370 -41

No files matched your search

@@ -0,0 +1,7 @@
## Release 1.0
### New Rules
Rule ID | Category | Severity | Notes
-----------|----------|----------|------------------------
MWAIS0001 | Usage | Error | ProviderAccessAnalyzer
@@ -0,0 +1,10 @@
### New Rules
Rule ID | Category | Severity | Notes
---------|----------|----------|-------
### Changed Rules
Rule ID | New Category | New Severity | Old Category | Old Severity | Notes
---------|--------------|--------------|--------------|--------------|-------
@@ -0,0 +1,71 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
namespace SourceCodeRules;
#pragma warning disable RS1038
[DiagnosticAnalyzer(LanguageNames.CSharp)]
#pragma warning restore RS1038
public class ProviderAccessAnalyzer : DiagnosticAnalyzer
{
private const string DIAGNOSTIC_ID = $"{Tools.ID_PREFIX}0001";
private static readonly string TITLE = "Direct access to `Providers` is not allowed";
private static readonly string MESSAGE_FORMAT = "Direct access to `SettingsManager.ConfigurationData.Providers` is not allowed. Instead, use APIs like `SettingsManager.GetPreselectedProvider`, etc.";
private static readonly string DESCRIPTION = MESSAGE_FORMAT;
private const string CATEGORY = "Usage";
private static readonly DiagnosticDescriptor RULE = new(DIAGNOSTIC_ID, TITLE, MESSAGE_FORMAT, CATEGORY, DiagnosticSeverity.Error, isEnabledByDefault: true, description: DESCRIPTION);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(RULE);
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();
context.RegisterSyntaxNodeAction(this.AnalyzeMemberAccess, SyntaxKind.SimpleMemberAccessExpression);
}
private void AnalyzeMemberAccess(SyntaxNodeAnalysisContext context)
{
var memberAccess = (MemberAccessExpressionSyntax)context.Node;
// Prüfen, ob wir eine Kette von Zugriffen haben, die auf "Providers" endet
if (memberAccess.Name.Identifier.Text != "Providers")
return;
// Den kompletten Zugriffspfad aufbauen
var fullPath = this.GetFullMemberAccessPath(memberAccess);
// Prüfen, ob der Pfad unserem verbotenen Muster entspricht
if (fullPath.EndsWith("ConfigurationData.Providers"))
{
var diagnostic = Diagnostic.Create(RULE, memberAccess.GetLocation());
context.ReportDiagnostic(diagnostic);
}
}
private string GetFullMemberAccessPath(ExpressionSyntax expression)
{
var parts = new List<string>();
while (expression is MemberAccessExpressionSyntax memberAccess)
{
parts.Add(memberAccess.Name.Identifier.Text);
expression = memberAccess.Expression;
}
if (expression is IdentifierNameSyntax identifier)
parts.Add(identifier.Identifier.Text);
parts.Reverse();
return string.Join(".", parts);
}
}
@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<IsPackable>false</IsPackable>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<IsRoslynComponent>true</IsRoslynComponent>
<RootNamespace>SourceCodeRules</RootNamespace>
<AssemblyName>SourceCodeRules</AssemblyName>
<Version>1.0.0</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.12.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.12.0" />
</ItemGroup>
</Project>
@@ -0,0 +1,6 @@
namespace SourceCodeRules;
public static class Tools
{
public const string ID_PREFIX = "MWAIS";
}