Skip to content

Commit

Permalink
Merge pull request #404 from StefanMaron/development
Browse files Browse the repository at this point in the history
New rule0034 Use SecretText type
  • Loading branch information
Arthurvdv authored Dec 7, 2023
2 parents c43d3fa + 9ea8a77 commit b34a478
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 1 deletion.
77 changes: 77 additions & 0 deletions Design/Rule0043SecretText.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using System.Collections.Immutable;
using Microsoft.Dynamics.Nav.CodeAnalysis;
using Microsoft.Dynamics.Nav.CodeAnalysis.Diagnostics;
using Microsoft.Dynamics.Nav.CodeAnalysis.Symbols;

namespace BusinessCentral.LinterCop.Design
{
[DiagnosticAnalyzer]
public class Rule0043SecretText : DiagnosticAnalyzer
{
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create<DiagnosticDescriptor>(DiagnosticDescriptors.Rule0043SecretText);

private static readonly string authorization = "Authorization";
private static readonly List<string> buildInMethodNames = new List<string>
{
"add",
"getvalues",
"tryaddwithoutvalidation"
};

public override void Initialize(AnalysisContext context) => context.RegisterOperationAction(new Action<OperationAnalysisContext>(this.AnalyzeHttpObjects), OperationKind.InvocationExpression);

private void AnalyzeHttpObjects(OperationAnalysisContext ctx)
{
if (!VersionChecker.IsSupported(ctx.ContainingSymbol, VersionCompatibility.Fall2023OrGreater)) return;

if (ctx.ContainingSymbol.GetContainingObjectTypeSymbol().IsObsoletePending || ctx.ContainingSymbol.GetContainingObjectTypeSymbol().IsObsoleteRemoved) return;
if (ctx.ContainingSymbol.IsObsoletePending || ctx.ContainingSymbol.IsObsoleteRemoved) return;

IInvocationExpression operation = (IInvocationExpression)ctx.Operation;

// We need at least two arguments
if (operation.Arguments.Count() < 2) return;

switch (operation.TargetMethod.MethodKind)
{
case MethodKind.BuiltInMethod:
if (!buildInMethodNames.Contains(operation.TargetMethod.Name.ToLowerInvariant())) return;

// We need to verify that the method is called from a HttpHeaders or HttpClient object
if (!ctx.Operation.DescendantsAndSelf().Where(x => x.GetSymbol() != null)
.Where(x => x.Type.GetNavTypeKindSafe() == NavTypeKind.HttpHeaders || x.Type.GetNavTypeKindSafe() == NavTypeKind.HttpClient)
.Any()) return;
break;
case MethodKind.Method:
if (operation.TargetMethod.ContainingType.GetNavTypeKindSafe() != NavTypeKind.Codeunit) return;
ICodeunitTypeSymbol codeunitTypeSymbol = (ICodeunitTypeSymbol)operation.TargetMethod.GetContainingObjectTypeSymbol();
if (!SemanticFacts.IsSameName(((INamespaceSymbol)codeunitTypeSymbol.ContainingSymbol).QualifiedName, "System.RestClient")) return;
if (!SemanticFacts.IsSameName(codeunitTypeSymbol.Name, "Rest Client")) return;
if (!SemanticFacts.IsSameName(operation.TargetMethod.Name, "SetDefaultRequestHeader")) return;
break;
default:
return;
}

if (!IsAuthorizationArgument(operation.Arguments[0])) return;

if (operation.Arguments[1].Parameter.OriginalDefinition.GetTypeSymbol().GetNavTypeKindSafe() != NavTypeKind.SecretText)
ctx.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.Rule0043SecretText, ctx.Operation.Syntax.GetLocation()));
}

private static bool IsAuthorizationArgument(IArgument argument)
{
switch (argument.Syntax.Kind)
{
case SyntaxKind.LiteralExpression:
return SemanticFacts.IsSameName(argument.Value.ConstantValue.Value.ToString(), authorization);
case SyntaxKind.IdentifierName:
IOperation operand = ((IConversionExpression)argument.Value).Operand;
ILabelTypeSymbol label = (ILabelTypeSymbol)operand.GetSymbol().OriginalDefinition.GetTypeSymbol();
return SemanticFacts.IsSameName(label.GetLabelText(), authorization);
default:
return false;
}
}
}
}
5 changes: 5 additions & 0 deletions LinterCop.ruleset.json
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,11 @@
"id": "LC0042",
"action": "Warning",
"justification": "AutoCalcFields should only be used for FlowFields or Blob fields."
},
{
"id": "LC0043",
"action": "Info",
"justification": "Use SecretText type to protect credentials and sensitive textual values from being revealed."
}
]
}
1 change: 1 addition & 0 deletions LinterCopAnalyzers.Generated.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,6 @@ public static class DiagnosticDescriptors
public static readonly DiagnosticDescriptor Rule0040ExplicitlySetRunTrigger = new DiagnosticDescriptor(LinterCopAnalyzers.AnalyzerPrefix + "0040", (LocalizableString)new LocalizableResourceString("Rule0040ExplicitlySetRunTriggerTitle", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), (LocalizableString)new LocalizableResourceString("Rule0040ExplicitlySetRunTriggerFormat", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "Design", DiagnosticSeverity.Info, true, (LocalizableString)new LocalizableResourceString("Rule0040ExplicitlySetRunTriggerDescription", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0040");
public static readonly DiagnosticDescriptor Rule0041EmptyCaptionLocked = new DiagnosticDescriptor(LinterCopAnalyzers.AnalyzerPrefix + "0041", (LocalizableString)new LocalizableResourceString("Rule0041EmptyCaptionLockedTitle", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), (LocalizableString)new LocalizableResourceString("Rule0041EmptyCaptionLockedFormat", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "Design", DiagnosticSeverity.Info, true, (LocalizableString)new LocalizableResourceString("Rule0041EmptyCaptionLockedDescription", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0041");
public static readonly DiagnosticDescriptor Rule0042AutoCalcFieldsOnNormalFields = new DiagnosticDescriptor(LinterCopAnalyzers.AnalyzerPrefix + "0042", (LocalizableString)new LocalizableResourceString("Rule0042AutoCalcFieldsOnNormalFieldsTitle", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), (LocalizableString)new LocalizableResourceString("Rule0042AutoCalcFieldsOnNormalFieldsFormat", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "Design", DiagnosticSeverity.Warning, true, (LocalizableString)new LocalizableResourceString("Rule0042AutoCalcFieldsOnNormalFieldsDescription", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0042");
public static readonly DiagnosticDescriptor Rule0043SecretText = new DiagnosticDescriptor(LinterCopAnalyzers.AnalyzerPrefix + "0043", (LocalizableString)new LocalizableResourceString("Rule0043SecretTextTitle", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), (LocalizableString)new LocalizableResourceString("Rule0043SecretTextFormat", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "Design", DiagnosticSeverity.Info, true, (LocalizableString)new LocalizableResourceString("Rule0043SecretTextDescription", LinterCopAnalyzers.ResourceManager, typeof(LinterCopAnalyzers)), "https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0043");
}
}
9 changes: 9 additions & 0 deletions LinterCopAnalyzers.resx
Original file line number Diff line number Diff line change
Expand Up @@ -483,4 +483,13 @@
<data name="Rule0042AutoCalcFieldsOnNormalFieldsDescription" xml:space="preserve">
<value>The SetAutoCalcFields method should only be used with FlowFields or fields of type Blob. The field {0} is not a FlowField or of type Blob.</value>
</data>
<data name="Rule0043SecretTextTitle" xml:space="preserve">
<value>Use SecretText type to protect credentials and sensitive textual values from being revealed.</value>
</data>
<data name="Rule0043SecretTextFormat" xml:space="preserve">
<value>Use SecretText type to protect credentials and sensitive textual values from being revealed.</value>
</data>
<data name="Rule0043SecretTextDescription" xml:space="preserve">
<value>Use SecretText type to protect credentials and sensitive textual values from being revealed.</value>
</data>
</root>
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ Further note that you should have BcContainerHelper version 2.0.16 (or newer) in
|[LC0040](https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0040)|Explicitly set the `RunTrigger` parameter on build-in methods.|Info|
|[LC0041](https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0041)|Empty Captions should be `Locked`.|Info|
|[LC0042](https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0042)|`AutoCalcFields` should only be used for FlowFields or Blob fields.|Warning|

|[LC0043](https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0043)|Use `SecretText` type to protect credentials and sensitive textual values from being revealed.|Info|

## Configuration

Expand Down

0 comments on commit b34a478

Please sign in to comment.