Repository: microsoft/ApplicationInspector
File: AppInspector.RulesEngine/RulesVerifier.cs (C#)

Code before:
            if (searchPattern.PatternType == PatternType.RegexWord || searchPattern.PatternType == PatternType.Regex)
            {
                try
                {
                    if (string.IsNullOrEmpty(searchPattern.Pattern))
                    {
                        throw new ArgumentException();
                    }
                    
                    RegexOptions regexOpts =
                        Utils.RegexModifierToRegexOptions(searchPattern.Modifiers);
                    
#if NET7_0_OR_GREATER
                    if (_options.EnableNonBacktrackingRegex)
                    {
                        regexOpts |= RegexOptions.NonBacktracking;
                    }
#endif

                    _ = new Regex(searchPattern.Pattern, regexOpts);
                }
                catch (NotSupportedException e)
                {
                    // Regex requires backtracking, try without non-backtracking
                    _logger?.LogWarning(MsgHelp.GetString(MsgHelp.ID.VERIFY_RULES_REGEX_FAIL), rule.Id ?? "", searchPattern.Pattern ?? "", e.Message);
                    errors.Add(MsgHelp.FormatString(MsgHelp.ID.VERIFY_RULES_REGEX_FAIL, rule.Id ?? "", searchPattern.Pattern ?? "", e.Message));

                    _ = new Regex(searchPattern.Pattern, Utils.RegexModifierToRegexOptions(searchPattern.Modifiers));      
                }
                catch (Exception e)
                {
                    _logger?.LogError(MsgHelp.GetString(MsgHelp.ID.VERIFY_RULES_REGEX_FAIL), rule.Id ?? "",
                        searchPattern.Pattern ?? "", e.Message);
                    errors.Add(MsgHelp.FormatString(MsgHelp.ID.VERIFY_RULES_REGEX_FAIL, rule.Id ?? "",
                        searchPattern.Pattern ?? "", e.Message));
                }
            }

            if (searchPattern.JsonPaths is not null)
            {
                foreach (var jsonPath in searchPattern.JsonPaths)
                {
                    try
                    {
                        _ = JsonSelector.Parse(jsonPath);
                    }
                    catch (Exception e)
                    {
                        _logger?.LogError(
                            "The provided JsonPath '{JsonPath}' value was not valid in Rule {Id} : {message}",
                            searchPattern.JsonPaths, rule.Id, e.Message);

Review comment (bug):
Can't add this message to the errors. Any messages in the errors indicate validation failure. The Validation object doesn't currently have a field for informative messages like warnings, Errors are always assumed to be a validation failure.

Code after:

        // App Inspector checks
        var rule = convertedOatRule.AppInspectorRule;
        // Check for null Id
        if (string.IsNullOrEmpty(rule.Id))
        {
            _logger.LogError(MsgHelp.GetString(MsgHelp.ID.VERIFY_RULES_NULLID_FAIL), rule.Name);
            errors.Add(MsgHelp.FormatString(MsgHelp.ID.VERIFY_RULES_NULLID_FAIL, rule.Name));
        }

        //applicability
        if (rule.AppliesTo != null)
        {
            var languages = _options.LanguageSpecs.GetNames();
            // Check for unknown language
            foreach (var lang in rule.AppliesTo)
                if (!string.IsNullOrEmpty(lang))
                {
                    if (!languages.Any(x => x.Equals(lang, StringComparison.CurrentCultureIgnoreCase)))
                    {
                        _logger.LogError(MsgHelp.GetString(MsgHelp.ID.VERIFY_RULES_LANGUAGE_FAIL), rule.Id ?? "", lang);
                        errors.Add(MsgHelp.FormatString(MsgHelp.ID.VERIFY_RULES_LANGUAGE_FAIL, rule.Id ?? "", lang));
                    }
                }
        }

        // Check that regexes for filenames are valid
        foreach (var pattern in (IList<string>?)rule.FileRegexes ?? Array.Empty<string>())
            try
            {
                _ = new Regex(pattern, RegexOptions.Compiled);
            }
            catch (Exception e)
            {
                _logger?.LogError(MsgHelp.GetString(MsgHelp.ID.VERIFY_RULES_REGEX_FAIL), rule.Id ?? "", pattern ?? "",
                    e.Message);
                errors.Add(MsgHelp.FormatString(MsgHelp.ID.VERIFY_RULES_REGEX_FAIL, rule.Id ?? "", pattern ?? "",
                    e.Message));
            }

        //valid search pattern
        foreach (var searchPattern in rule.Patterns ?? Array.Empty<SearchPattern>())
        {
            // Check that pattern regex arguments are valid
            if (searchPattern.PatternType == PatternType.RegexWord || searchPattern.PatternType == PatternType.Regex)
            {
                if (searchPattern.Pattern is null)
                {
                    _logger?.LogError(MsgHelp.GetString(MsgHelp.ID.VERIFY_RULES_REGEX_FAIL_PATTERN_NULL), rule.Id ?? "");
                }
                else