private void AnalyzeNeverSetProperties(OperationAnalysisContext context, IPropertySymbol property, Location location) { if (property.MatchPropertyDerivedByName(_xmlTypes.XmlDocument, SecurityMemberNames.InnerXml)) { DiagnosticDescriptor rule = RuleDoNotUseInsecureDtdProcessing; context.ReportDiagnostic( Diagnostic.Create( rule, location, SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.DoNotUseSetInnerXmlMessage) ) ) ); } else if (property.MatchPropertyDerivedByName(_xmlTypes.DataViewManager, SecurityMemberNames.DataViewSettingCollectionString)) { DiagnosticDescriptor rule = RuleDoNotUseInsecureDtdProcessing; context.ReportDiagnostic( Diagnostic.Create( rule, location, SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.ReviewDtdProcessingPropertiesMessage) ) ) ); } }
private void AnalyzeXmlResolverPropertyAssignmentForXmlDocument(OperationAnalysisContext context, ISymbol assignedSymbol, IAssignmentExpression expression) { bool isSecureResolver = false; IConversionExpression conv = expression.Value as IConversionExpression; if (SecurityDiagnosticHelpers.IsXmlSecureResolverType(conv.Operand.Type, _xmlTypes)) { isSecureResolver = true; } else if (conv != null && SecurityDiagnosticHelpers.IsExpressionEqualsNull(conv.Operand)) { isSecureResolver = true; } else // Assigning XmlDocument's XmlResolver to an insecure value { Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDtdProcessing, context.Operation.Syntax.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlDocumentWithNoSecureResolverMessage) ) ); context.ReportDiagnostic(diag); } if (_xmlDocumentEnvironments.ContainsKey(assignedSymbol)) { XmlDocumentEnvironment xmlDocumentEnv = _xmlDocumentEnvironments[assignedSymbol]; xmlDocumentEnv.IsXmlResolverSet = true; xmlDocumentEnv.IsSecureResolver = isSecureResolver; } }
public override void Initialize(AnalysisContext analysisContext) { // TODO: Make analyzer thread-safe. //analysisContext.EnableConcurrentExecution(); // Security analyzer - analyze and report diagnostics in generated code. analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); analysisContext.RegisterCompilationStartAction( (context) => { Compilation compilation = context.Compilation; var xmlTypes = new CompilationSecurityTypes(compilation); if (ReferencesAnyTargetType(xmlTypes)) { Version version = SecurityDiagnosticHelpers.GetDotNetFrameworkVersion(compilation); // bail if we are not analyzing project targeting .NET Framework // TODO: should we throw an exception to notify user? if (version != null) { SymbolAndNodeAnalyzer analyzer = GetAnalyzer(context, xmlTypes, version); context.RegisterSymbolAction(analyzer.AnalyzeSymbol, SymbolKind.NamedType); } } }); }
public void AnalyzeCodeBlockEnd(CodeBlockAnalysisContext context) { foreach (KeyValuePair <ISymbol, XmlDocumentEnvironment> p in _xmlDocumentEnvironments) { XmlDocumentEnvironment env = p.Value; if (!(env.IsXmlResolverSet | env.IsSecureResolver)) { Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDTDProcessing, env.XmlDocumentDefinition.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlDocumentWithNoSecureResolverMessage), env.EnclosingConstructSymbol.Name)); context.ReportDiagnostic(diag); } } foreach (KeyValuePair <ISymbol, XmlTextReaderEnvironment> p in _xmlTextReaderEnvironments) { XmlTextReaderEnvironment env = p.Value; if (!(env.IsXmlResolverSet | env.IsSecureResolver) || !(env.IsDtdProcessingSet | env.IsDtdProcessingDisabled)) { Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDTDProcessing, env.XmlTextReaderDefinition.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlTextReaderConstructedWithNoSecureResolutionMessage), env.EnclosingConstructSymbol.Name)); context.ReportDiagnostic(diag); } } }
private void AnalyzeObjectCreationInternal(OperationAnalysisContext context, ISymbol variable, IOperation value) { IObjectCreationExpression objCreation = value as IObjectCreationExpression; if (objCreation == null) { return; } if (_objectCreationOperationsAnalyzed.Contains(objCreation)) { return; } else { _objectCreationOperationsAnalyzed.Add(objCreation); } if (SecurityDiagnosticHelpers.IsXmlDocumentCtorDerived(objCreation.Constructor, _xmlTypes)) { AnalyzeObjectCreationForXmlDocument(context, variable, objCreation); } else if (SecurityDiagnosticHelpers.IsXmlTextReaderCtorDerived(objCreation.Constructor, _xmlTypes)) { AnalyzeObjectCreationForXmlTextReader(context, variable, objCreation); } else if (SecurityDiagnosticHelpers.IsXmlReaderSettingsCtor(objCreation.Constructor, _xmlTypes)) { AnalyzeObjectCreationForXmlReaderSettings(variable, objCreation); } else { AnalyzeMethodOverloads(context, objCreation.Constructor, objCreation); } }
public override void Initialize(AnalysisContext analysisContext) { // TODO: Make analyzer thread-safe //analysisContext.EnableConcurrentExecution(); // Security analyzer - analyze and report diagnostics in generated code. analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); analysisContext.RegisterCompilationStartAction( (context) => { Compilation compilation = context.Compilation; var xmlTypes = new CompilationSecurityTypes(compilation); if (ReferencesAnyTargetType(xmlTypes)) { Version version = SecurityDiagnosticHelpers.GetDotNetFrameworkVersion(compilation); if (version != null) { context.RegisterOperationBlockStartAction( (c) => { RegisterAnalyzer(c, xmlTypes, version); }); } } }); }
private void AnalyzeNodeForXmlDocumentDerivedTypeConstructorDecl(SyntaxNodeAnalysisContext context) { SyntaxNode node = context.Node; SemanticModel model = context.SemanticModel; IMethodSymbol methodSymbol = SyntaxNodeHelper.GetDeclaredSymbol(node, model) as IMethodSymbol; if (methodSymbol == null || methodSymbol.MethodKind != MethodKind.Constructor || !((methodSymbol.ContainingType != _xmlTypes.XmlDocument) && methodSymbol.ContainingType.DerivesFrom(_xmlTypes.XmlDocument, baseTypesOnly: true))) { return; } bool hasSetSecureXmlResolver = false; IEnumerable <SyntaxNode> assignments = _syntaxNodeHelper.GetDescendantAssignmentExpressionNodes(node); foreach (SyntaxNode a in assignments) { bool isTargetProperty; // this is intended to be an assignment, not a bug if (hasSetSecureXmlResolver = IsAssigningIntendedValueToPropertyDerivedFromType(a, model, (s) => { return(SecurityDiagnosticHelpers.IsXmlDocumentXmlResolverProperty(s, _xmlTypes)); }, (n) => { return(SyntaxNodeHelper.NodeHasConstantValueNull(n, model) || SecurityDiagnosticHelpers.IsXmlSecureResolverType(model.GetTypeInfo(n).Type, _xmlTypes)); }, out isTargetProperty)) { break; } } if (!hasSetSecureXmlResolver) { DiagnosticDescriptor rule = RuleDoNotUseInsecureDtdProcessingInApiDesign; context.ReportDiagnostic( CreateDiagnostic( methodSymbol.Locations, rule, SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlDocumentDerivedClassConstructorNoSecureXmlResolverMessage), SecurityDiagnosticHelpers.GetNonEmptyParentName(node, model) ) ) ); } }
private static DiagnosticDescriptor CreateDiagnosticDescriptor(LocalizableResourceString messageFormat, LocalizableResourceString description, string helpLink = null) { return(new DiagnosticDescriptor(RuleId, SecurityDiagnosticHelpers.GetLocalizableResourceString(nameof(DesktopAnalyzersResources.InsecureXsltScriptProcessingMessage)), messageFormat, DiagnosticCategory.Security, DiagnosticSeverity.Warning, isEnabledByDefault: true, description: description, helpLinkUri: helpLink, customTags: WellKnownDiagnosticTags.Telemetry)); }
// Trying to find every "this.XmlResolver = [Insecure Resolve];" in methods of types derived from XmlDocment and generate a warning for each private void AnalyzeNodeForXmlDocumentDerivedTypeMethodDecl(SyntaxNodeAnalysisContext context) { SyntaxNode node = context.Node; SemanticModel model = context.SemanticModel; IMethodSymbol methodSymbol = SyntaxNodeHelper.GetDeclaredSymbol(node, model) as IMethodSymbol; if (methodSymbol == null || // skip constructors since we report on the absence of secure assignment in AnalyzeNodeForXmlDocumentDerivedTypeConstructorDecl methodSymbol.MethodKind == MethodKind.Constructor || !((methodSymbol.ContainingType != _xmlTypes.XmlDocument) && methodSymbol.ContainingType.DerivesFrom(_xmlTypes.XmlDocument, baseTypesOnly: true))) { return; } var assignments = this._syntaxNodeHelper.GetDescendantAssignmentExpressionNodes(node); foreach (var assignment in assignments) { bool isTargetProperty; // this is intended to be an assignment, not a bug if (IsAssigningIntendedValueToPropertyDerivedFromType(assignment, model, (s) => { return(SecurityDiagnosticHelpers.IsXmlDocumentXmlResolverProperty(s, this._xmlTypes)); }, (n) => { return(!(SyntaxNodeHelper.NodeHasConstantValueNull(n, model) || SecurityDiagnosticHelpers.IsXmlSecureResolverType(model.GetTypeInfo(n).Type, this._xmlTypes))); }, out isTargetProperty) ) { var rule = RuleDoNotUseInsecureDtdProcessingInApiDesign; context.ReportDiagnostic( CreateDiagnostic( assignment.GetLocation(), rule, SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlDocumentDerivedClassSetInsecureXmlResolverInMethodMessage), methodSymbol.Name ) ) ); } } }
private void AnalyzeObjectCreationForXmlReaderSettings(ISymbol variable, IObjectCreationExpression objCreation) { XmlReaderSettingsEnvironment xmlReaderSettingsEnv = new XmlReaderSettingsEnvironment(_isFrameworkSecure); if (variable != null) { _xmlReaderSettingsEnvironments[variable] = xmlReaderSettingsEnv; } xmlReaderSettingsEnv.XmlReaderSettingsDefinition = objCreation.Syntax; foreach (ISymbolInitializer init in objCreation.MemberInitializers) { var prop = init as IPropertyInitializer; if (prop != null) { if (SecurityDiagnosticHelpers.IsXmlReaderSettingsXmlResolverProperty( prop.InitializedProperty, _xmlTypes) ) { IConversionExpression operation = prop.Value as IConversionExpression; if (operation == null) { return; } if (SecurityDiagnosticHelpers.IsXmlSecureResolverType(operation.Operand.Type, _xmlTypes)) { xmlReaderSettingsEnv.IsSecureResolver = true; } else if (SecurityDiagnosticHelpers.IsExpressionEqualsNull(operation.Operand)) { xmlReaderSettingsEnv.IsSecureResolver = true; } } else if (SecurityDiagnosticHelpers.IsXmlReaderSettingsDtdProcessingProperty(prop.InitializedProperty, _xmlTypes)) { xmlReaderSettingsEnv.IsDtdProcessingDisabled = !SecurityDiagnosticHelpers.IsExpressionEqualsDtdProcessingParse(prop.Value); } else if (SecurityDiagnosticHelpers.IsXmlReaderSettingsMaxCharactersFromEntitiesProperty(prop.InitializedProperty, _xmlTypes)) { xmlReaderSettingsEnv.IsMaxCharactersFromEntitiesLimited = !SecurityDiagnosticHelpers.IsExpressionEqualsIntZero(prop.Value); } } } }
private void AnalyzeNodeForDtdProcessingProperties(SyntaxNodeAnalysisContext context) { SyntaxNode node = context.Node; SemanticModel semanticModel = context.SemanticModel; SyntaxNode lhs = _syntaxNodeHelper.GetAssignmentLeftNode(node); if (lhs == null) { return; } IPropertySymbol property = SyntaxNodeHelper.GetCalleePropertySymbol(lhs, semanticModel); if (property == null) { return; } if (property.MatchPropertyDerivedByName(_xmlTypes.XmlDocument, SecurityMemberNames.InnerXml)) //FxCop CA3058 { DiagnosticDescriptor rule = RuleDoNotUseInsecureDTDProcessing; context.ReportDiagnostic( Diagnostic.Create( rule, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.DoNotUseSetInnerXmlMessage), SecurityDiagnosticHelpers.GetNonEmptyParentName(node, semanticModel) ) ) ); } else if (property.MatchPropertyDerivedByName(_xmlTypes.DataViewManager, SecurityMemberNames.DataViewSettingCollectionString)) //FxCop CA3065 { DiagnosticDescriptor rule = RuleDoNotUseInsecureDTDProcessing; context.ReportDiagnostic( Diagnostic.Create( rule, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.ReviewDtdProcessingPropertiesMessage), SecurityDiagnosticHelpers.GetNonEmptyParentName(node, semanticModel) ) ) ); } }
private void AnalyzeXmlTextReaderProperties(OperationAnalysisContext context, ISymbol assignedSymbol, IAssignmentExpression expression, bool isXmlTextReaderXmlResolverProperty, bool isXmlTextReaderDtdProcessingProperty) { XmlTextReaderEnvironment env; if (!_xmlTextReaderEnvironments.TryGetValue(assignedSymbol, out env)) { env = new XmlTextReaderEnvironment(_isFrameworkSecure); } if (isXmlTextReaderXmlResolverProperty) { env.IsXmlResolverSet = true; } else { env.IsDtdProcessingSet = true; } IConversionExpression conv = expression.Value as IConversionExpression; if (isXmlTextReaderXmlResolverProperty && conv != null && SecurityDiagnosticHelpers.IsXmlSecureResolverType(conv.Operand.Type, _xmlTypes)) { env.IsSecureResolver = true; } else if (isXmlTextReaderXmlResolverProperty && conv != null && SecurityDiagnosticHelpers.IsExpressionEqualsNull(conv.Operand)) { env.IsSecureResolver = true; } else if (isXmlTextReaderDtdProcessingProperty && conv == null && !SecurityDiagnosticHelpers.IsExpressionEqualsDtdProcessingParse(expression.Value)) { env.IsDtdProcessingDisabled = !SecurityDiagnosticHelpers.IsExpressionEqualsDtdProcessingParse(expression.Value); } else { // Generate a warning whenever the XmlResolver or DtdProcessing property is set to an insecure value Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDtdProcessing, expression.Syntax.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlTextReaderSetInsecureResolutionMessage) ) ); context.ReportDiagnostic(diag); } }
private void AnalyzeObjectCreationForXmlTextReader(OperationAnalysisContext context, ISymbol variable, IObjectCreationExpression objCreation) { if (variable == null || !_xmlTextReaderEnvironments.TryGetValue(variable, out XmlTextReaderEnvironment env)) { env = new XmlTextReaderEnvironment(_isFrameworkSecure) { XmlTextReaderDefinition = objCreation.Syntax }; } if (objCreation.Constructor.ContainingType != _xmlTypes.XmlTextReader) { env.IsDtdProcessingDisabled = true; env.IsSecureResolver = true; } foreach (ISymbolInitializer init in objCreation.MemberInitializers) { if (init is IPropertyInitializer prop) { if (prop.Value is IConversionExpression operation && SecurityDiagnosticHelpers.IsXmlTextReaderXmlResolverPropertyDerived(prop.InitializedProperty, _xmlTypes)) { env.IsXmlResolverSet = true; if (SecurityDiagnosticHelpers.IsXmlSecureResolverType(operation.Operand.Type, _xmlTypes)) { env.IsSecureResolver = true; } else if (SecurityDiagnosticHelpers.IsExpressionEqualsNull(operation.Operand)) { env.IsSecureResolver = true; } else { env.IsSecureResolver = false; } } else if (SecurityDiagnosticHelpers.IsXmlTextReaderDtdProcessingPropertyDerived(prop.InitializedProperty, _xmlTypes)) { env.IsDtdProcessingSet = true; env.IsDtdProcessingDisabled = !SecurityDiagnosticHelpers.IsExpressionEqualsDtdProcessingParse(prop.Value); } } }
public override void Initialize(AnalysisContext analysisContext) { analysisContext.RegisterCompilationStartAction( (context) => { Compilation compilation = context.Compilation; var xmlTypes = new CompilationSecurityTypes(compilation); if (ReferencesAnyTargetType(xmlTypes)) { Version version = SecurityDiagnosticHelpers.GetDotNetFrameworkVersion(compilation); // bail if we are not analyzing project targeting .NET Framework // TODO: should we throw an exception to notify user? if (version != null) { SymbolAndNodeAnalyzer analyzer = GetAnalyzer(context, xmlTypes, version); context.RegisterSymbolAction(analyzer.AnalyzeSymbol, SymbolKind.NamedType); } } }); }
// report warning if no explicit definition of contrsuctor in XmlTextReader derived types private void AnalyzeSymbolForXmlTextReaderDerivedType(SymbolAnalysisContext context) { ISymbol symbol = context.Symbol; if (symbol.Kind != SymbolKind.NamedType) { return; } var typeSymbol = (INamedTypeSymbol)symbol; INamedTypeSymbol xmlTextReaderSym = _xmlTypes.XmlTextReader; if ((typeSymbol != xmlTextReaderSym) && typeSymbol.DerivesFrom(xmlTextReaderSym, baseTypesOnly: true)) { bool explicitlyDeclared = true; if (typeSymbol.Constructors.Length == 1) { IMethodSymbol constructor = typeSymbol.Constructors[0]; explicitlyDeclared = !constructor.IsImplicitlyDeclared; if (!explicitlyDeclared && !_isFrameworkSecure) { DiagnosticDescriptor rule = RuleDoNotUseInsecureDtdProcessingInApiDesign; context.ReportDiagnostic( CreateDiagnostic( typeSymbol.Locations, rule, SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlTextReaderDerivedClassNoConstructorMessage), symbol.Name ) ) ); } } _xmlTextReaderDerivedTypes.AddOrUpdate(typeSymbol, explicitlyDeclared, (k, v) => explicitlyDeclared); } }
public override void Initialize(AnalysisContext analysisContext) { analysisContext.RegisterCompilationStartAction( (context) => { Compilation compilation = context.Compilation; var xmlTypes = new CompilationSecurityTypes(compilation); if (ReferencesAnyTargetType(xmlTypes)) { Version version = SecurityDiagnosticHelpers.GetDotNetFrameworkVersion(compilation); // bail if we are not analyzing project targeting .NET Framework // TODO: should we throw an exception to notify user? if (version != null) { context.RegisterCodeBlockStartAction <TLanguageKindEnum>( (c) => { RegisterAnalyzer(c, xmlTypes, version); }); } } }); }
public override void Initialize(AnalysisContext analysisContext) { analysisContext.RegisterCompilationStartAction( (context) => { Compilation compilation = context.Compilation; var xmlTypes = new CompilationSecurityTypes(compilation); if (ReferencesAnyTargetType(xmlTypes)) { Version version = SecurityDiagnosticHelpers.GetDotNetFrameworkVersion(compilation); if (version != null) { context.RegisterOperationBlockStartAction( (c) => { RegisterAnalyzer(c, xmlTypes, version); }); } } }); }
private void AnalyzeNodeForXmlTextReaderDerivedTypeMethodDecl(SyntaxNodeAnalysisContext context) { SyntaxNode node = context.Node; SemanticModel model = context.SemanticModel; IMethodSymbol methodSymbol = SyntaxNodeHelper.GetDeclaredSymbol(node, model) as IMethodSymbol; if (methodSymbol == null || !((methodSymbol.ContainingType != _xmlTypes.XmlTextReader) && methodSymbol.ContainingType.DerivesFrom(_xmlTypes.XmlTextReader, baseTypesOnly: true))) { return; } // If the default value are not secure, the AnalyzeNodeForXmlTextReaderDerivedTypeConstructorDecl would be skipped, // therefoer we need to check constructor for any insecure settings. // Otherwise, we skip checking constructors if (_isFrameworkSecure && methodSymbol.MethodKind == MethodKind.Constructor) { return; } bool hasSetXmlResolver = false; bool hasSetInsecureXmlResolver = true; bool isDtdProcessingSet = false; bool isDtdProcessingEnabled = true; List <Location> locs = null; Location insecureXmlResolverAssignLoc = null; Location issecureDtdProcessingLoc = null; IEnumerable <SyntaxNode> assignments = _syntaxNodeHelper.GetDescendantAssignmentExpressionNodes(node); foreach (SyntaxNode assignment in assignments) { bool ret; bool isTargetProperty; ret = IsAssigningIntendedValueToPropertyDerivedFromType(assignment, model, (s) => { return(SecurityDiagnosticHelpers.IsXmlTextReaderXmlResolverProperty(s, _xmlTypes)); }, (n) => { return(!(SyntaxNodeHelper.NodeHasConstantValueNull(n, model) || SecurityDiagnosticHelpers.IsXmlSecureResolverType(model.GetTypeInfo(n).Type, _xmlTypes))); }, out isTargetProperty ); if (isTargetProperty) { hasSetXmlResolver = true; hasSetInsecureXmlResolver &= ret; // use 'AND' to avoid false positives (but imcrease false negative rate) if (ret) { if (locs == null) { locs = new List <Location>(); } locs.Add(assignment.GetLocation()); } continue; } ret = IsAssigningIntendedValueToPropertyDerivedFromType(assignment, model, (s) => { return(SecurityDiagnosticHelpers.IsXmlTextReaderDtdProcessingProperty(s, _xmlTypes)); }, (n) => { return(SyntaxNodeHelper.GetSymbol(n, model).MatchFieldByName(_xmlTypes.DtdProcessing, SecurityMemberNames.Parse)); }, out isTargetProperty); if (isTargetProperty) { isDtdProcessingSet = true; isDtdProcessingEnabled &= ret; // use 'AND' to avoid false positives (but imcrease false negative rate) if (ret) { if (locs == null) { locs = new List <Location>(); } locs.Add(assignment.GetLocation()); } } } // neither XmlResolver nor DtdProcessing is explicitly set if (!(hasSetXmlResolver || isDtdProcessingSet)) { return; } // explicitly set XmlResolver and/or DtdProcessing to secure value else if (!hasSetInsecureXmlResolver || !isDtdProcessingEnabled) { return; } // didn't explicitly set either one of XmlResolver and DtdProcessing to secure value // but explicitly set XmlResolver and/or DtdProcessing to insecure value else { if (insecureXmlResolverAssignLoc != null) { locs.Add(insecureXmlResolverAssignLoc); } if (issecureDtdProcessingLoc != null) { locs.Add(issecureDtdProcessingLoc); } DiagnosticDescriptor rule = RuleDoNotUseInsecureDtdProcessingInApiDesign; // TODO: Only first location is shown in error, maybe we want to report on method instead? // Or on each insecure assignment? context.ReportDiagnostic( CreateDiagnostic( locs, rule, SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlTextReaderDerivedClassSetInsecureSettingsInMethodMessage), methodSymbol.Name ) ) ); } }
private void AnalyzeNodeForDtdProcessingOverloads(SyntaxNodeAnalysisContext context) { SyntaxNode node = context.Node; SemanticModel model = context.SemanticModel; IMethodSymbol method = _syntaxNodeHelper.GetCalleeMethodSymbol(node, model); if (method == null) { return; } CompilationSecurityTypes xmlTypes = _xmlTypes; if (method.MatchMethodDerivedByName(xmlTypes.XmlDocument, SecurityMemberNames.Load) || //FxCop CA3056 method.MatchMethodDerivedByName(xmlTypes.XmlDocument, SecurityMemberNames.LoadXml) || //FxCop CA3057 method.MatchMethodDerivedByName(xmlTypes.XPathDocument, WellKnownMemberNames.InstanceConstructorName) || //FxCop CA3059 method.MatchMethodDerivedByName(xmlTypes.XmlSchema, SecurityMemberNames.Read) || //FxCop CA3060 method.MatchMethodDerivedByName(xmlTypes.DataSet, SecurityMemberNames.ReadXml) || //FxCop CA3063 method.MatchMethodDerivedByName(xmlTypes.DataSet, SecurityMemberNames.ReadXmlSchema) || //FxCop CA3064 method.MatchMethodDerivedByName(xmlTypes.XmlSerializer, SecurityMemberNames.Deserialize) || //FxCop CA3070 method.MatchMethodDerivedByName(xmlTypes.DataTable, SecurityMemberNames.ReadXml) || //FxCop CA3071 method.MatchMethodDerivedByName(xmlTypes.DataTable, SecurityMemberNames.ReadXmlSchema)) //FxCop CA3072 { if (SecurityDiagnosticHelpers.HasXmlReaderParameter(method, xmlTypes) < 0) { DiagnosticDescriptor rule = RuleDoNotUseInsecureDTDProcessing; context.ReportDiagnostic( Diagnostic.Create( rule, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.DoNotUseDtdProcessingOverloadsMessage), SecurityDiagnosticHelpers.GetNonEmptyParentName(node, model), method.Name) ) ); } } // We assume the design of derived type are secure, per Rule CA9003 else if (method.MatchMethodByName(xmlTypes.XmlDocument, WellKnownMemberNames.InstanceConstructorName)) { if (IsObjectConstructionForTemporaryObject(node)) // REVIEW: may be hard to check { bool isXmlDocumentSecureResolver = false; foreach (SyntaxNode arg in _syntaxNodeHelper.GetObjectInitializerExpressionNodes(node)) { SyntaxNode argLhs = _syntaxNodeHelper.GetAssignmentLeftNode(arg); SyntaxNode argRhs = _syntaxNodeHelper.GetAssignmentRightNode(arg); if (SecurityDiagnosticHelpers.IsXmlDocumentXmlResolverProperty(SyntaxNodeHelper.GetSymbol(argLhs, model), xmlTypes)) { if (!(SyntaxNodeHelper.NodeHasConstantValueNull(argRhs, model) || SecurityDiagnosticHelpers.IsXmlSecureResolverType(model.GetTypeInfo(argRhs).Type, xmlTypes))) { // if XmlResolver property is explicitly set to an insecure value in initializer list, // a warning would be generated when handling assignment of XmlDocument.XmlResolver // AnalyzeNodeForXmlDocument method, so we ignore it here. return; } else { isXmlDocumentSecureResolver = true; } } } if (!isXmlDocumentSecureResolver) { Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDTDProcessing, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlDocumentWithNoSecureResolverMessage), _syntaxNodeHelper.GetEnclosingConstructSymbol(node, model).Name) ); context.ReportDiagnostic(diag); } } } // We assume the design of derived type are secure, per Rule CA9003 else if (method.MatchMethodByName(xmlTypes.XmlTextReader, WellKnownMemberNames.InstanceConstructorName)) { if (IsObjectConstructionForTemporaryObject(node)) // REVIEW: may be hard to check { bool isXmlTextReaderSecureResolver, isXmlTextReaderDtdProcessingDisabled; isXmlTextReaderSecureResolver = isXmlTextReaderDtdProcessingDisabled = false; foreach (SyntaxNode arg in _syntaxNodeHelper.GetObjectInitializerExpressionNodes(node)) { SyntaxNode argLhs = _syntaxNodeHelper.GetAssignmentLeftNode(arg); SyntaxNode argRhs = _syntaxNodeHelper.GetAssignmentRightNode(arg); ISymbol symArgLhs = SyntaxNodeHelper.GetSymbol(argLhs, model); if (SecurityDiagnosticHelpers.IsXmlTextReaderXmlResolverProperty(symArgLhs, xmlTypes)) { if (!(SyntaxNodeHelper.NodeHasConstantValueNull(argRhs, model) || SecurityDiagnosticHelpers.IsXmlSecureResolverType(model.GetTypeInfo(argRhs).Type, xmlTypes))) { // Generate a warning whenever the XmlTextReader.XmlResolver property is set to an insecure value Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDTDProcessing, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlTextReaderSetInsecureResolutionMessage), _syntaxNodeHelper.GetEnclosingConstructSymbol(node, model).Name ) ); context.ReportDiagnostic(diag); return; } else { isXmlTextReaderSecureResolver = true; } } else if (SecurityDiagnosticHelpers.IsXmlTextReaderDtdProcessingProperty(symArgLhs, xmlTypes)) { if (SyntaxNodeHelper.GetSymbol(argRhs, model).MatchFieldByName(xmlTypes.DtdProcessing, SecurityMemberNames.Parse)) { // Generate a warning whenever the XmlTextReader.DtdProcessing property is set to DtdProcessing.Parse Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDTDProcessing, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlTextReaderSetInsecureResolutionMessage), _syntaxNodeHelper.GetEnclosingConstructSymbol(node, model).Name ) ); context.ReportDiagnostic(diag); return; } else { isXmlTextReaderDtdProcessingDisabled = true; } } } if (!isXmlTextReaderSecureResolver || !isXmlTextReaderDtdProcessingDisabled) { Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDTDProcessing, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlTextReaderConstructedWithNoSecureResolutionMessage), SecurityDiagnosticHelpers.GetNonEmptyParentName(node, model) ) ); context.ReportDiagnostic(diag); } } } else if (method.MatchMethodDerivedByName(xmlTypes.XmlReader, SecurityMemberNames.Create)) { int xmlReaderSettingsIndex = SecurityDiagnosticHelpers.HasXmlReaderSettingsParameter(method, xmlTypes); if (xmlReaderSettingsIndex < 0) //FxCop CA3053:XmlReaderCreateWrongOverload { DiagnosticDescriptor rule = RuleDoNotUseInsecureDTDProcessing; context.ReportDiagnostic( Diagnostic.Create( rule, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlReaderCreateWrongOverloadMessage), SecurityDiagnosticHelpers.GetNonEmptyParentName(node, model) ) ) ); } else { SyntaxNode settingsNode = _syntaxNodeHelper.GetInvocationArgumentExpressionNodes(node).ElementAt(xmlReaderSettingsIndex); ISymbol settingsSymbol = SyntaxNodeHelper.GetSymbol(settingsNode, model); XmlReaderSettingsEnvironment env = null; if (!_xmlReaderSettingsEnvironments.TryGetValue(settingsSymbol, out env)) { // symbol for settings is not found => passed in without any change => assume insecure Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDTDProcessing, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlReaderCreateInsecureInputMessage), SecurityDiagnosticHelpers.GetNonEmptyParentName(node, model) ) ); context.ReportDiagnostic(diag); } else if (!env.IsDtdProcessingDisabled && !(env.IsSecureResolver & env.IsMaxCharactersFromEntitiesLimited)) { Diagnostic diag; if (env.IsConstructedInCodeBlock) { diag = Diagnostic.Create( RuleDoNotUseInsecureDTDProcessing, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlReaderCreateInsecureConstructedMessage) ) ); } else { diag = Diagnostic.Create( RuleDoNotUseInsecureDTDProcessing, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlReaderCreateInsecureInputMessage) ) ); } context.ReportDiagnostic(diag); } } } }
private void AnalyzeNodeForXmlTextReaderDerivedTypeConstructorDecl(SyntaxNodeAnalysisContext context) { SyntaxNode node = context.Node; SemanticModel model = context.SemanticModel; IMethodSymbol methodSymbol = SyntaxNodeHelper.GetDeclaredSymbol(node, model) as IMethodSymbol; if (methodSymbol == null || methodSymbol.MethodKind != MethodKind.Constructor || !((methodSymbol.ContainingType != _xmlTypes.XmlTextReader) && methodSymbol.ContainingType.DerivesFrom(_xmlTypes.XmlTextReader, baseTypesOnly: true))) { return; } bool hasSetSecureXmlResolver = false; bool isDtdProcessingDisabled = false; IEnumerable <SyntaxNode> assignments = _syntaxNodeHelper.GetDescendantAssignmentExpressionNodes(node); foreach (SyntaxNode assignment in assignments) { bool isTargetProperty = false; hasSetSecureXmlResolver = hasSetSecureXmlResolver || IsAssigningIntendedValueToPropertyDerivedFromType(assignment, model, (s) => { return(SecurityDiagnosticHelpers.IsXmlTextReaderXmlResolverProperty(s, _xmlTypes)); }, (n) => { return(SyntaxNodeHelper.NodeHasConstantValueNull(n, model) || SecurityDiagnosticHelpers.IsXmlSecureResolverType(model.GetTypeInfo(n).Type, _xmlTypes)); }, out isTargetProperty); if (isTargetProperty) { continue; } isDtdProcessingDisabled = isDtdProcessingDisabled || IsAssigningIntendedValueToPropertyDerivedFromType(assignment, model, (s) => { return(SecurityDiagnosticHelpers.IsXmlTextReaderDtdProcessingProperty(s, _xmlTypes)); }, (n) => { return(!SyntaxNodeHelper.GetSymbol(n, model).MatchFieldByName(_xmlTypes.DtdProcessing, SecurityMemberNames.Parse)); }, out isTargetProperty); if (hasSetSecureXmlResolver && isDtdProcessingDisabled) { return; } } DiagnosticDescriptor rule = RuleDoNotUseInsecureDtdProcessingInApiDesign; context.ReportDiagnostic( CreateDiagnostic( methodSymbol.Locations, rule, SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlTextReaderDerivedClassConstructorNoSecureSettingsMessage), SecurityDiagnosticHelpers.GetNonEmptyParentName(node, model) ) ) ); }
private void AnalyzeMethodOverloads(OperationAnalysisContext context, IMethodSymbol method, IHasArgumentsExpression expression) { if (method.MatchMethodDerivedByName(_xmlTypes.XmlDocument, SecurityMemberNames.Load) || //FxCop CA3056 method.MatchMethodDerivedByName(_xmlTypes.XmlDocument, SecurityMemberNames.LoadXml) || //FxCop CA3057 method.MatchMethodDerivedByName(_xmlTypes.XPathDocument, WellKnownMemberNames.InstanceConstructorName) || //FxCop CA3059 method.MatchMethodDerivedByName(_xmlTypes.XmlSchema, SecurityMemberNames.Read) || //FxCop CA3060 method.MatchMethodDerivedByName(_xmlTypes.DataSet, SecurityMemberNames.ReadXml) || //FxCop CA3063 method.MatchMethodDerivedByName(_xmlTypes.DataSet, SecurityMemberNames.ReadXmlSchema) || //FxCop CA3064 method.MatchMethodDerivedByName(_xmlTypes.XmlSerializer, SecurityMemberNames.Deserialize) || //FxCop CA3070 method.MatchMethodDerivedByName(_xmlTypes.DataTable, SecurityMemberNames.ReadXml) || //FxCop CA3071 method.MatchMethodDerivedByName(_xmlTypes.DataTable, SecurityMemberNames.ReadXmlSchema)) //FxCop CA3072 { if (SecurityDiagnosticHelpers.HasXmlReaderParameter(method, _xmlTypes) < 0) { DiagnosticDescriptor rule = RuleDoNotUseInsecureDtdProcessing; context.ReportDiagnostic( Diagnostic.Create( rule, expression.Syntax.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.DoNotUseDtdProcessingOverloadsMessage), method.Name ) ) ); } } else if (method.MatchMethodDerivedByName(_xmlTypes.XmlReader, SecurityMemberNames.Create)) { int xmlReaderSettingsIndex = SecurityDiagnosticHelpers.GetXmlReaderSettingsParameterIndex(method, _xmlTypes); if (xmlReaderSettingsIndex < 0) { DiagnosticDescriptor rule = RuleDoNotUseInsecureDtdProcessing; Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDtdProcessing, expression.Syntax.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlReaderCreateWrongOverloadMessage) ) ); context.ReportDiagnostic(diag); } else { SemanticModel model = context.Compilation.GetSemanticModel(context.Operation.Syntax.SyntaxTree); IArgument arg = expression.ArgumentsInParameterOrder[xmlReaderSettingsIndex]; ISymbol settingsSymbol = arg.Value.Syntax.GetDeclaredOrReferencedSymbol(model); if (settingsSymbol == null) { return; } XmlReaderSettingsEnvironment env; if (!_xmlReaderSettingsEnvironments.TryGetValue(settingsSymbol, out env)) { // symbol for settings is not found => passed in without any change => assume insecure Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDtdProcessing, expression.Syntax.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlReaderCreateInsecureInputMessage) ) ); context.ReportDiagnostic(diag); } else if (!env.IsDtdProcessingDisabled && !(env.IsSecureResolver && env.IsMaxCharactersFromEntitiesLimited)) { Diagnostic diag; if (env.IsConstructedInCodeBlock) { diag = Diagnostic.Create( RuleDoNotUseInsecureDtdProcessing, expression.Syntax.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlReaderCreateInsecureConstructedMessage) ) ); } else { diag = Diagnostic.Create( RuleDoNotUseInsecureDtdProcessing, expression.Syntax.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlReaderCreateInsecureInputMessage) ) ); } context.ReportDiagnostic(diag); } } } }
private void AnalyzeNodeForXmlDocument(SyntaxNodeAnalysisContext context) { SyntaxNode node = context.Node; SemanticModel model = context.SemanticModel; node = _syntaxNodeHelper.GetVariableDeclaratorOfAFieldDeclarationNode(node) ?? node; SyntaxNode lhs = _syntaxNodeHelper.GetAssignmentLeftNode(node); SyntaxNode rhs = _syntaxNodeHelper.GetAssignmentRightNode(node); if (lhs == null || rhs == null) { return; } ISymbol lhsSymbol = SyntaxNodeHelper.GetSymbol(lhs, model); if (lhsSymbol == null) { return; } CompilationSecurityTypes xmlTypes = _xmlTypes; IMethodSymbol rhsMethodSymbol = _syntaxNodeHelper.GetCalleeMethodSymbol(rhs, model); if (SecurityDiagnosticHelpers.IsXmlDocumentCtorDerived(rhsMethodSymbol, xmlTypes)) { XmlDocumentEnvironment env = new XmlDocumentEnvironment(); if (rhsMethodSymbol.ContainingType != xmlTypes.XmlDocument) { env.IsSecureResolver = true; } foreach (SyntaxNode arg in _syntaxNodeHelper.GetObjectInitializerExpressionNodes(rhs)) { SyntaxNode argLhs = _syntaxNodeHelper.GetAssignmentLeftNode(arg); SyntaxNode argRhs = _syntaxNodeHelper.GetAssignmentRightNode(arg); if (SecurityDiagnosticHelpers.IsXmlDocumentXmlResolverPropertyDerived(SyntaxNodeHelper.GetSymbol(argLhs, model), xmlTypes)) { env.IsXmlResolverSet = true; if (SyntaxNodeHelper.NodeHasConstantValueNull(argRhs, model) || SecurityDiagnosticHelpers.IsXmlSecureResolverType(model.GetTypeInfo(argRhs).Type, xmlTypes)) { env.IsSecureResolver = true; } break; } } // if XmlResolver property is explicitly set to an insecure value in initializer list, // a warning would be generated when handling assignment of XmlDocument.XmlResolver in the // else-if clause below, so we ignore it here. // Only keep track of XmlDocument constructed here when if is not explicitly set to insecure value. if (!env.IsXmlResolverSet | env.IsSecureResolver) { env.XmlDocumentDefinition = node; env.EnclosingConstructSymbol = _syntaxNodeHelper.GetEnclosingConstructSymbol(node, model); _xmlDocumentEnvironments[lhsSymbol] = env; } } else if (SecurityDiagnosticHelpers.IsXmlDocumentXmlResolverPropertyDerived(lhsSymbol, xmlTypes)) { SyntaxNode lhsExpressionNode = _syntaxNodeHelper.GetMemberAccessExpressionNode(lhs) ?? lhs; if (lhsExpressionNode == null) { return; } ISymbol lhsExpressionSymbol = SyntaxNodeHelper.GetSymbol(lhsExpressionNode, model); if (lhsExpressionSymbol == null) { return; } XmlDocumentEnvironment env = null; _xmlDocumentEnvironments.TryGetValue(lhsExpressionSymbol, out env); ITypeSymbol rhsType = model.GetTypeInfo(rhs).Type; // if XmlDocument was constructed in the same code block with default values. if (env != null) { env.IsXmlResolverSet = true; } if (SyntaxNodeHelper.NodeHasConstantValueNull(rhs, model) || SecurityDiagnosticHelpers.IsXmlSecureResolverType(rhsType, xmlTypes)) { if (env != null) { env.IsSecureResolver = true; } } else { // Generate a warning whenever the XmlResolver property is set to an insecure value Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDTDProcessing, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlDocumentWithNoSecureResolverMessage), _syntaxNodeHelper.GetEnclosingConstructSymbol(node, model).Name ) ); context.ReportDiagnostic(diag); } } }
//Note: False negative if integer is used to set DtdProcessing instead of enumeration private void AnalyzeNodeForXmlTextReader(SyntaxNodeAnalysisContext context) { SyntaxNode node = context.Node; SemanticModel model = context.SemanticModel; node = _syntaxNodeHelper.GetVariableDeclaratorOfAFieldDeclarationNode(node) ?? node; SyntaxNode lhs = _syntaxNodeHelper.GetAssignmentLeftNode(node); SyntaxNode rhs = _syntaxNodeHelper.GetAssignmentRightNode(node); if (lhs == null || rhs == null) { return; } ISymbol lhsSymbol = SyntaxNodeHelper.GetSymbol(lhs, model); if (lhsSymbol == null) { return; } CompilationSecurityTypes xmlTypes = _xmlTypes; IMethodSymbol rhsMethodSymbol = _syntaxNodeHelper.GetCalleeMethodSymbol(rhs, model); if (SecurityDiagnosticHelpers.IsXmlTextReaderCtorDerived(rhsMethodSymbol, xmlTypes)) { XmlTextReaderEnvironment env = null; if (!_xmlTextReaderEnvironments.TryGetValue(lhsSymbol, out env)) { env = new XmlTextReaderEnvironment(_isFrameworkSecure); } if (rhsMethodSymbol.ContainingType != xmlTypes.XmlTextReader) { env.IsDtdProcessingDisabled = true; env.IsSecureResolver = true; } foreach (SyntaxNode arg in _syntaxNodeHelper.GetObjectInitializerExpressionNodes(rhs)) { SyntaxNode argLhs = _syntaxNodeHelper.GetAssignmentLeftNode(arg); SyntaxNode argRhs = _syntaxNodeHelper.GetAssignmentRightNode(arg); if (SecurityDiagnosticHelpers.IsXmlTextReaderXmlResolverPropertyDerived(SyntaxNodeHelper.GetSymbol(argLhs, model), xmlTypes)) { env.IsXmlResolverSet = true; env.IsSecureResolver = SyntaxNodeHelper.NodeHasConstantValueNull(argRhs, model) || SecurityDiagnosticHelpers.IsXmlSecureResolverType(model.GetTypeInfo(argRhs).Type, xmlTypes); } else if (SecurityDiagnosticHelpers.IsXmlTextReaderDtdProcessingPropertyDerived(SyntaxNodeHelper.GetSymbol(argLhs, model), xmlTypes)) { env.IsDtdProcessingSet = true; env.IsDtdProcessingDisabled = !SyntaxNodeHelper.GetSymbol(argRhs, model).MatchFieldByName(xmlTypes.DtdProcessing, SecurityMemberNames.Parse); } } // if the XmlResolver or Dtdprocessing property is explicitly set when created, and is to an insecure value, generate a warning if ((env.IsXmlResolverSet & !env.IsSecureResolver) || (env.IsDtdProcessingSet & !env.IsDtdProcessingDisabled)) { Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDTDProcessing, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlTextReaderSetInsecureResolutionMessage), _syntaxNodeHelper.GetEnclosingConstructSymbol(node, model).Name ) ); context.ReportDiagnostic(diag); } // if the XmlResolver or Dtdprocessing property is not explicitly set when constructed for XmlTextReader type, add env to the dictionary. else if (!(env.IsDtdProcessingSet & env.IsXmlResolverSet) && (rhsMethodSymbol.ContainingType == xmlTypes.XmlTextReader)) { env.XmlTextReaderDefinition = node; env.EnclosingConstructSymbol = _syntaxNodeHelper.GetEnclosingConstructSymbol(node, model); _xmlTextReaderEnvironments[lhsSymbol] = env; } } else if (lhsSymbol.Kind == SymbolKind.Property) { bool isXmlTextReaderXmlResolverProperty = SecurityDiagnosticHelpers.IsXmlTextReaderXmlResolverPropertyDerived(lhsSymbol, xmlTypes); bool isXmlTextReaderDtdProcessingProperty = !isXmlTextReaderXmlResolverProperty && SecurityDiagnosticHelpers.IsXmlTextReaderDtdProcessingPropertyDerived(lhsSymbol, xmlTypes); if (isXmlTextReaderXmlResolverProperty | isXmlTextReaderDtdProcessingProperty) { // unlike XmlDocument, we already generate a warning for this scenario: // var doc = new XmlTextReader(path){XmlResolver = new XmlUrlResolver()}; // therefore we only need to check property setting in the form of: // xmlTextReaderObject.XmlResolver = new XmlUrlResolver(); SyntaxNode lhsExpressionNode = _syntaxNodeHelper.GetMemberAccessExpressionNode(lhs); if (lhsExpressionNode == null) { return; } ISymbol lhsExpressionSymbol = SyntaxNodeHelper.GetSymbol(lhsExpressionNode, model); if (lhsExpressionSymbol == null) { return; } XmlTextReaderEnvironment env = null; _xmlTextReaderEnvironments.TryGetValue(lhsExpressionSymbol, out env); ITypeSymbol rhsType = model.GetTypeInfo(rhs).Type; // if the XmlTextReader object was constructed with default values if (env != null) { if (isXmlTextReaderXmlResolverProperty) { env.IsXmlResolverSet = true; } else { env.IsDtdProcessingSet = true; } } if (isXmlTextReaderXmlResolverProperty && (SyntaxNodeHelper.NodeHasConstantValueNull(rhs, model) || SecurityDiagnosticHelpers.IsXmlSecureResolverType(rhsType, xmlTypes))) { if (env != null) { env.IsSecureResolver = true; } } else if (isXmlTextReaderDtdProcessingProperty && !SyntaxNodeHelper.GetSymbol(rhs, model).MatchFieldByName(xmlTypes.DtdProcessing, SecurityMemberNames.Parse)) { if (env != null) { env.IsDtdProcessingDisabled = true; } } else { // Generate a warning whenever the XmlResolver or DtdProcessing property is set to an insecure value Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDTDProcessing, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlTextReaderSetInsecureResolutionMessage), _syntaxNodeHelper.GetEnclosingConstructSymbol(node, model).Name ) ); context.ReportDiagnostic(diag); } } } }
private void AnalyzeObjectCreationForXmlDocument(OperationAnalysisContext context, ISymbol variable, IObjectCreationExpression objCreation) { XmlDocumentEnvironment xmlDocumentEnvironment; if (variable == null || !_xmlDocumentEnvironments.ContainsKey(variable)) { xmlDocumentEnvironment = new XmlDocumentEnvironment { IsSecureResolver = false, IsXmlResolverSet = false }; } else { xmlDocumentEnvironment = _xmlDocumentEnvironments[variable]; } xmlDocumentEnvironment.XmlDocumentDefinition = objCreation.Syntax; SyntaxNode node = objCreation.Syntax; bool isXmlDocumentSecureResolver = false; if (objCreation.Constructor.ContainingType != _xmlTypes.XmlDocument) { isXmlDocumentSecureResolver = true; } foreach (ISymbolInitializer init in objCreation.MemberInitializers) { var prop = init as IPropertyInitializer; if (prop != null) { if (prop.InitializedProperty.MatchPropertyDerivedByName(_xmlTypes.XmlDocument, "XmlResolver")) { IConversionExpression operation = prop.Value as IConversionExpression; if (operation == null) { return; } if (SecurityDiagnosticHelpers.IsXmlSecureResolverType(operation.Operand.Type, _xmlTypes)) { isXmlDocumentSecureResolver = true; } else if (SecurityDiagnosticHelpers.IsExpressionEqualsNull(operation.Operand)) { isXmlDocumentSecureResolver = true; } else // Non secure resolvers { IObjectCreationExpression xmlResolverObjCreated = operation.Operand as IObjectCreationExpression; if (xmlResolverObjCreated != null) { Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDtdProcessing, prop.Syntax.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlDocumentWithNoSecureResolverMessage) ) ); context.ReportDiagnostic(diag); } return; } } else { AnalyzeNeverSetProperties(context, prop.InitializedProperty, prop.Syntax.GetLocation()); } } } xmlDocumentEnvironment.IsSecureResolver = isXmlDocumentSecureResolver; if (variable != null) { _xmlDocumentEnvironments[variable] = xmlDocumentEnvironment; } else if (!xmlDocumentEnvironment.IsSecureResolver) // Insecure temp object { Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDtdProcessing, node.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlDocumentWithNoSecureResolverMessage) ) ); context.ReportDiagnostic(diag); } }
//Note: False negative if integer is used to set DtdProcessing instead of enumeration private void AnalyzeNodeForXmlReaderSettings(SyntaxNodeAnalysisContext context) { SyntaxNode node = context.Node; SemanticModel model = context.SemanticModel; SyntaxNode lhs = _syntaxNodeHelper.GetAssignmentLeftNode(node); SyntaxNode rhs = _syntaxNodeHelper.GetAssignmentRightNode(node); if (lhs == null || rhs == null) { return; } ISymbol lhsSymbol = SyntaxNodeHelper.GetSymbol(lhs, model); if (lhsSymbol == null) { return; } CompilationSecurityTypes xmlTypes = _xmlTypes; IMethodSymbol rhsMethodSymbol = _syntaxNodeHelper.GetCalleeMethodSymbol(rhs, model); if (SecurityDiagnosticHelpers.IsXmlReaderSettingsCtor(rhsMethodSymbol, xmlTypes)) { XmlReaderSettingsEnvironment env = new XmlReaderSettingsEnvironment(_isFrameworkSecure); _xmlReaderSettingsEnvironments[lhsSymbol] = env; env.XmlReaderSettingsDefinition = node; env.EnclosingConstructSymbol = _syntaxNodeHelper.GetEnclosingConstructSymbol(node, model); foreach (SyntaxNode arg in _syntaxNodeHelper.GetObjectInitializerExpressionNodes(rhs)) { SyntaxNode argLhs = _syntaxNodeHelper.GetAssignmentLeftNode(arg); SyntaxNode argRhs = _syntaxNodeHelper.GetAssignmentRightNode(arg); ISymbol argLhsSymbol = SyntaxNodeHelper.GetSymbol(argLhs, model); if (SecurityDiagnosticHelpers.IsXmlReaderSettingsXmlResolverProperty(argLhsSymbol, xmlTypes)) { env.IsSecureResolver = SyntaxNodeHelper.NodeHasConstantValueNull(argRhs, model) || SecurityDiagnosticHelpers.IsXmlSecureResolverType(model.GetTypeInfo(argRhs).Type, xmlTypes); } else if (SecurityDiagnosticHelpers.IsXmlReaderSettingsDtdProcessingProperty(argLhsSymbol, xmlTypes)) { // since the default is always Prohibit, we only need update if it is set to Parse if (SyntaxNodeHelper.GetSymbol(argRhs, model).MatchFieldByName(xmlTypes.DtdProcessing, SecurityMemberNames.Parse)) { env.IsDtdProcessingDisabled = false; } } else if (SecurityDiagnosticHelpers.IsXmlReaderSettingsMaxCharactersFromEntitiesProperty(argLhsSymbol, xmlTypes)) { env.IsMaxCharactersFromEntitiesLimited = !SyntaxNodeHelper.NodeHasConstantValueIntZero(argRhs, model); } } } else if (lhsSymbol.Kind == SymbolKind.Property) { bool isXmlReaderSettingsXmlResolverProperty = SecurityDiagnosticHelpers.IsXmlReaderSettingsXmlResolverProperty(lhsSymbol, xmlTypes); bool isXmlReaderSettingsDtdProcessingProperty = !isXmlReaderSettingsXmlResolverProperty && SecurityDiagnosticHelpers.IsXmlReaderSettingsDtdProcessingProperty(lhsSymbol, xmlTypes); bool isXmlReaderSettingsMaxCharactersFromEntitiesProperty = !(isXmlReaderSettingsXmlResolverProperty | isXmlReaderSettingsDtdProcessingProperty) && SecurityDiagnosticHelpers.IsXmlReaderSettingsMaxCharactersFromEntitiesProperty(lhsSymbol, xmlTypes); if (isXmlReaderSettingsXmlResolverProperty | isXmlReaderSettingsDtdProcessingProperty | isXmlReaderSettingsMaxCharactersFromEntitiesProperty) { SyntaxNode lhsExpressionNode = _syntaxNodeHelper.GetMemberAccessExpressionNode(lhs); if (lhsExpressionNode == null) { return; } ISymbol lhsExpressionSymbol = SyntaxNodeHelper.GetSymbol(lhsExpressionNode, model); if (lhsExpressionSymbol == null) { return; } XmlReaderSettingsEnvironment env = null; if (!_xmlReaderSettingsEnvironments.TryGetValue(lhsExpressionSymbol, out env)) { // env.IsConstructedInCodeBlock is false env = new XmlReaderSettingsEnvironment(); _xmlReaderSettingsEnvironments[lhsExpressionSymbol] = env; } ITypeSymbol rhsType = model.GetTypeInfo(rhs).Type; if (isXmlReaderSettingsXmlResolverProperty) { env.IsSecureResolver = SyntaxNodeHelper.NodeHasConstantValueNull(rhs, model) || SecurityDiagnosticHelpers.IsXmlSecureResolverType(rhsType, xmlTypes); } else if (isXmlReaderSettingsDtdProcessingProperty) { env.IsDtdProcessingDisabled = !SyntaxNodeHelper.GetSymbol(rhs, model).MatchFieldByName(xmlTypes.DtdProcessing, SecurityMemberNames.Parse); } else { env.IsMaxCharactersFromEntitiesLimited = !SyntaxNodeHelper.NodeHasConstantValueIntZero(rhs, model); } } } }
private void AnalyzeNodeForXsltSettings(SyntaxNodeAnalysisContext context) { SyntaxNode node = context.Node; SemanticModel model = context.SemanticModel; SyntaxNode lhs = _syntaxNodeHelper.GetAssignmentLeftNode(node); SyntaxNode rhs = _syntaxNodeHelper.GetAssignmentRightNode(node); if (lhs == null || rhs == null) { return; } ISymbol lhsSymbol = SyntaxNodeHelper.GetSymbol(lhs, model); if (lhsSymbol == null) { return; } IMethodSymbol rhsMethodSymbol = _syntaxNodeHelper.GetCalleeMethodSymbol(rhs, model); IPropertySymbol rhsPropertySymbol = SyntaxNodeHelper.GetCalleePropertySymbol(rhs, model); if (SecurityDiagnosticHelpers.IsXsltSettingsCtor(rhsMethodSymbol, _xmlTypes)) { XsltSettingsEnvironment env = new XsltSettingsEnvironment(); _xsltSettingsEnvironments[lhsSymbol] = env; env.XsltSettingsSymbol = lhsSymbol; env.XsltSettingsDefinitionSymbol = rhsMethodSymbol; env.XsltSettingsDefinition = node; env.EnclosingConstructSymbol = _syntaxNodeHelper.GetEnclosingConstructSymbol(node, model); //default both properties are disbled env.IsDocumentFunctionDisabled = true; env.IsScriptDisabled = true; // XsltSettings Constructor (Boolean, Boolean) if (rhsMethodSymbol.Parameters.Any()) { IEnumerable <SyntaxNode> argumentExpressionNodes = _syntaxNodeHelper.GetObjectCreationArgumentExpressionNodes(rhs); env.IsDocumentFunctionDisabled = SyntaxNodeHelper.NodeHasConstantValueBoolFalse(argumentExpressionNodes.ElementAt(0), model); env.IsScriptDisabled = SyntaxNodeHelper.NodeHasConstantValueBoolFalse(argumentExpressionNodes.ElementAt(1), model); } foreach (SyntaxNode arg in _syntaxNodeHelper.GetObjectInitializerExpressionNodes(rhs)) { SyntaxNode argLhs = _syntaxNodeHelper.GetAssignmentLeftNode(arg); SyntaxNode argRhs = _syntaxNodeHelper.GetAssignmentRightNode(arg); ISymbol argLhsSymbol = SyntaxNodeHelper.GetSymbol(argLhs, model); // anything other than a constant false is treated as true if (SecurityDiagnosticHelpers.IsXsltSettingsEnableDocumentFunctionProperty(argLhsSymbol as IPropertySymbol, _xmlTypes)) { env.IsDocumentFunctionDisabled = SyntaxNodeHelper.NodeHasConstantValueBoolFalse(argRhs, model); } else if (SecurityDiagnosticHelpers.IsXsltSettingsEnableScriptProperty(argLhsSymbol as IPropertySymbol, _xmlTypes)) { env.IsScriptDisabled = SyntaxNodeHelper.NodeHasConstantValueBoolFalse(argRhs, model); } } } else if (SecurityDiagnosticHelpers.IsXsltSettingsDefaultProperty(rhsPropertySymbol, _xmlTypes)) { XsltSettingsEnvironment env = new XsltSettingsEnvironment(); _xsltSettingsEnvironments[lhsSymbol] = env; env.XsltSettingsSymbol = lhsSymbol; env.XsltSettingsDefinitionSymbol = rhsPropertySymbol; env.XsltSettingsDefinition = node; env.EnclosingConstructSymbol = _syntaxNodeHelper.GetEnclosingConstructSymbol(node, model); env.IsDocumentFunctionDisabled = true; env.IsScriptDisabled = true; } else if (SecurityDiagnosticHelpers.IsXsltSettingsTrustedXsltProperty(rhsPropertySymbol, _xmlTypes)) { XsltSettingsEnvironment env = new XsltSettingsEnvironment(); _xsltSettingsEnvironments[lhsSymbol] = env; env.XsltSettingsSymbol = lhsSymbol; env.XsltSettingsDefinitionSymbol = rhsPropertySymbol; env.XsltSettingsDefinition = node; env.EnclosingConstructSymbol = _syntaxNodeHelper.GetEnclosingConstructSymbol(node, model); } else { bool isXlstSettingsEnableDocumentFunctionProperty = SecurityDiagnosticHelpers.IsXsltSettingsEnableDocumentFunctionProperty(lhsSymbol as IPropertySymbol, _xmlTypes); bool isXlstSettingsEnableScriptProperty = SecurityDiagnosticHelpers.IsXsltSettingsEnableScriptProperty(lhsSymbol as IPropertySymbol, _xmlTypes); if (isXlstSettingsEnableDocumentFunctionProperty || isXlstSettingsEnableScriptProperty) { SyntaxNode lhsExpressionNode = _syntaxNodeHelper.GetMemberAccessExpressionNode(lhs); if (lhsExpressionNode == null) { return; } ISymbol lhsExpressionSymbol = SyntaxNodeHelper.GetSymbol(lhsExpressionNode, model); if (lhsExpressionSymbol == null) { return; } XsltSettingsEnvironment env; if (!_xsltSettingsEnvironments.TryGetValue(lhsExpressionSymbol, out env)) { env = new XsltSettingsEnvironment { XsltSettingsSymbol = lhsExpressionSymbol }; _xsltSettingsEnvironments[lhsExpressionSymbol] = env; } ITypeSymbol rhsType = model.GetTypeInfo(rhs).Type; if (isXlstSettingsEnableDocumentFunctionProperty) { env.IsDocumentFunctionDisabled = SyntaxNodeHelper.NodeHasConstantValueBoolFalse(rhs, model); } else if (isXlstSettingsEnableScriptProperty) { env.IsScriptDisabled = SyntaxNodeHelper.NodeHasConstantValueBoolFalse(rhs, model); } } } }
private void AnalyzeAssignment(OperationAnalysisContext context) { IAssignmentExpression expression = context.Operation as IAssignmentExpression; if (expression.Target == null) { return; } SemanticModel model = context.Compilation.GetSemanticModel(expression.Syntax.SyntaxTree); var propRef = expression.Target as IPropertyReferenceExpression; if (propRef == null) // A variable/field assignment { ISymbol symbolAssignedTo = expression.Target.Syntax.GetDeclaredOrReferencedSymbol(model); if (symbolAssignedTo != null) { AnalyzeObjectCreationInternal(context, symbolAssignedTo, expression.Value); } } else // A property assignment { ISymbol assignedSymbol = propRef.Instance.Syntax.GetDeclaredOrReferencedSymbol(model); if (propRef.Property.MatchPropertyByName(_xmlTypes.XmlDocument, "XmlResolver")) { AnalyzeXmlResolverPropertyAssignmentForXmlDocument(context, assignedSymbol, expression); } else { bool isXmlTextReaderXmlResolverProperty = SecurityDiagnosticHelpers.IsXmlTextReaderXmlResolverPropertyDerived(propRef.Property, _xmlTypes); bool isXmlTextReaderDtdProcessingProperty = !isXmlTextReaderXmlResolverProperty && SecurityDiagnosticHelpers.IsXmlTextReaderDtdProcessingPropertyDerived(propRef.Property, _xmlTypes); if (isXmlTextReaderXmlResolverProperty || isXmlTextReaderDtdProcessingProperty) { AnalyzeXmlTextReaderProperties(context, assignedSymbol, expression, isXmlTextReaderXmlResolverProperty, isXmlTextReaderDtdProcessingProperty); } else if (SecurityDiagnosticHelpers.IsXmlReaderSettingsType(propRef.Instance.Type, _xmlTypes)) { XmlReaderSettingsEnvironment env; if (!_xmlReaderSettingsEnvironments.TryGetValue(assignedSymbol, out env)) { env = new XmlReaderSettingsEnvironment(_isFrameworkSecure); _xmlReaderSettingsEnvironments[assignedSymbol] = env; } IConversionExpression conv = expression.Value as IConversionExpression; if (conv != null && SecurityDiagnosticHelpers.IsXmlReaderSettingsXmlResolverProperty( propRef.Property, _xmlTypes) ) { if (SecurityDiagnosticHelpers.IsXmlSecureResolverType(conv.Operand.Type, _xmlTypes)) { env.IsSecureResolver = true; } else if (SecurityDiagnosticHelpers.IsExpressionEqualsNull(conv.Operand)) { env.IsSecureResolver = true; } } else if (SecurityDiagnosticHelpers.IsXmlReaderSettingsDtdProcessingProperty(propRef.Property, _xmlTypes)) { env.IsDtdProcessingDisabled = !SecurityDiagnosticHelpers.IsExpressionEqualsDtdProcessingParse(expression.Value); } else if (SecurityDiagnosticHelpers.IsXmlReaderSettingsMaxCharactersFromEntitiesProperty(propRef.Property, _xmlTypes)) { env.IsMaxCharactersFromEntitiesLimited = !SecurityDiagnosticHelpers.IsExpressionEqualsIntZero(expression.Value); } } else { AnalyzeNeverSetProperties(context, propRef.Property, expression.Syntax.GetLocation()); } } } }
private void AnalyzeNodeForXslCompiledTransformLoad(SyntaxNodeAnalysisContext context) { SyntaxNode node = context.Node; SemanticModel model = context.SemanticModel; IMethodSymbol methodSymbol = _syntaxNodeHelper.GetCalleeMethodSymbol(node, model); if (SecurityDiagnosticHelpers.IsXslCompiledTransformLoad(methodSymbol, _xmlTypes)) { bool isSecureResolver; bool isSecureSettings; bool isSetInBlock; int xmlResolverIndex = SecurityDiagnosticHelpers.GetXmlResolverParameterIndex(methodSymbol, _xmlTypes); int xsltSettingsIndex = SecurityDiagnosticHelpers.GetXsltSettingsParameterIndex(methodSymbol, _xmlTypes); // Overloads with no XmlResolver and XstlSettings specified are secure since they all have folowing behavior: // 1. An XmlUrlResolver with no user credentials is used to process any xsl:import or xsl:include elements. // 2. The document() function is disabled. // 3. Embedded scripts are not supported. if (xmlResolverIndex >= 0 && xsltSettingsIndex >= 0) { IEnumerable <SyntaxNode> argumentExpressionNodes = _syntaxNodeHelper.GetInvocationArgumentExpressionNodes(node); SyntaxNode resolverNode = argumentExpressionNodes.ElementAt(xmlResolverIndex); isSecureResolver = SyntaxNodeHelper.NodeHasConstantValueNull(resolverNode, model) || SecurityDiagnosticHelpers.IsXmlSecureResolverType(model.GetTypeInfo(resolverNode).Type, _xmlTypes); SyntaxNode settingsNode = argumentExpressionNodes.ElementAt(xsltSettingsIndex); ISymbol settingsSymbol = SyntaxNodeHelper.GetSymbol(settingsNode, model); XsltSettingsEnvironment env; // 1. pass null or XsltSettings.Default as XsltSetting : secure if (settingsSymbol == null || SecurityDiagnosticHelpers.IsXsltSettingsDefaultProperty(settingsSymbol as IPropertySymbol, _xmlTypes)) { isSetInBlock = true; isSecureSettings = true; } // 2. XsltSettings.TrustedXslt : insecure else if (SecurityDiagnosticHelpers.IsXsltSettingsTrustedXsltProperty(settingsSymbol as IPropertySymbol, _xmlTypes)) { isSetInBlock = true; isSecureSettings = false; } // 3. check xsltSettingsEnvironments, if IsScriptDisabled && IsDocumentFunctionDisabled then secure, else insecure else if (_xsltSettingsEnvironments.TryGetValue(settingsSymbol, out env)) { isSetInBlock = false; isSecureSettings = env.IsDocumentFunctionDisabled && env.IsScriptDisabled; } //4. symbol for settings is not found => passed in without any change => assume insecure else { isSetInBlock = true; isSecureSettings = false; } if (!isSecureSettings && !isSecureResolver) { LocalizableResourceString message = SecurityDiagnosticHelpers.GetLocalizableResourceString( isSetInBlock ? nameof(DesktopAnalyzersResources.XslCompiledTransformLoadInsecureConstructedMessage) : nameof(DesktopAnalyzersResources.XslCompiledTransformLoadInsecureInputMessage), SecurityDiagnosticHelpers.GetNonEmptyParentName(node, model) ); context.ReportDiagnostic( Diagnostic.Create( RuleDoNotUseInsecureXSLTScriptExecution, node.GetLocation(), message ) ); } } } }
private void AnalyzeObjectCreationForXmlTextReader(OperationAnalysisContext context, ISymbol variable, IObjectCreationExpression objCreation) { XmlTextReaderEnvironment env; if (variable == null || !_xmlTextReaderEnvironments.TryGetValue(variable, out env)) { env = new XmlTextReaderEnvironment(_isFrameworkSecure) { XmlTextReaderDefinition = objCreation.Syntax }; } if (objCreation.Constructor.ContainingType != _xmlTypes.XmlTextReader) { env.IsDtdProcessingDisabled = true; env.IsSecureResolver = true; } foreach (ISymbolInitializer init in objCreation.MemberInitializers) { var prop = init as IPropertyInitializer; if (prop != null) { IConversionExpression operation = prop.Value as IConversionExpression; if (operation != null && SecurityDiagnosticHelpers.IsXmlTextReaderXmlResolverPropertyDerived(prop.InitializedProperty, _xmlTypes)) { env.IsXmlResolverSet = true; if (SecurityDiagnosticHelpers.IsXmlSecureResolverType(operation.Operand.Type, _xmlTypes)) { env.IsSecureResolver = true; } else if (SecurityDiagnosticHelpers.IsExpressionEqualsNull(operation.Operand)) { env.IsSecureResolver = true; } else { env.IsSecureResolver = false; } } else if (SecurityDiagnosticHelpers.IsXmlTextReaderDtdProcessingPropertyDerived(prop.InitializedProperty, _xmlTypes)) { env.IsDtdProcessingSet = true; env.IsDtdProcessingDisabled = !SecurityDiagnosticHelpers.IsExpressionEqualsDtdProcessingParse(prop.Value); } } } // if the XmlResolver or Dtdprocessing property is explicitly set when created, and is to an insecure value, generate a warning if ((env.IsXmlResolverSet && !env.IsSecureResolver) || (env.IsDtdProcessingSet && !env.IsDtdProcessingDisabled)) { Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDtdProcessing, env.XmlTextReaderDefinition.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlTextReaderSetInsecureResolutionMessage) ) ); context.ReportDiagnostic(diag); } // if the XmlResolver or Dtdprocessing property is not explicitly set when constructed for a non-temp XmlTextReader object, add env to the dictionary. else if (variable != null && !(env.IsDtdProcessingSet && env.IsXmlResolverSet)) { _xmlTextReaderEnvironments[variable] = env; } // if the is not set or set to Parse for a temporary object, report right now. else if (variable == null && !(env.IsDtdProcessingSet && env.IsXmlResolverSet && env.IsDtdProcessingDisabled && env.IsSecureResolver)) { Diagnostic diag = Diagnostic.Create( RuleDoNotUseInsecureDtdProcessing, env.XmlTextReaderDefinition.GetLocation(), SecurityDiagnosticHelpers.GetLocalizableResourceString( nameof(DesktopAnalyzersResources.XmlTextReaderConstructedWithNoSecureResolutionMessage) ) ); context.ReportDiagnostic(diag); } }