using MarketAlly.AIPlugin;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace MarketAlly.AIPlugin.Security.Plugins
{
///
/// Validates configuration files for security best practices and sensitive data exposure
///
[AIPlugin("SecureConfiguration", "Validates configuration files for security best practices and sensitive data exposure")]
public class SecureConfigurationPlugin : IAIPlugin
{
[AIParameter("Full path to the configuration file or directory", required: true)]
public string ConfigPath { get; set; }
[AIParameter("Check for exposed secrets in config files", required: false)]
public bool CheckSecrets { get; set; } = true;
[AIParameter("Validate HTTPS/TLS configurations", required: false)]
public bool CheckTls { get; set; } = true;
[AIParameter("Check database connection security", required: false)]
public bool CheckDatabase { get; set; } = true;
[AIParameter("Validate CORS settings", required: false)]
public bool CheckCors { get; set; } = true;
[AIParameter("Check environment-specific configurations", required: false)]
public bool CheckEnvironments { get; set; } = true;
public IReadOnlyDictionary SupportedParameters => new Dictionary
{
["configPath"] = typeof(string),
["checkSecrets"] = typeof(bool),
["checkTls"] = typeof(bool),
["checkDatabase"] = typeof(bool),
["checkCors"] = typeof(bool),
["checkEnvironments"] = typeof(bool)
};
// Configuration security patterns
private static readonly Dictionary ConfigPatterns = new()
{
// Exposed Secrets
["password_in_config"] = (new Regex(@"(password|pwd|pass|secret|key|token)\s*[=:]\s*['""][^'""]{3,}['""]", RegexOptions.IgnoreCase),
"Secret", "High", "Password or secret in configuration file"),
["connection_string_password"] = (new Regex(@"password\s*=\s*[^;]{3,}", RegexOptions.IgnoreCase),
"Secret", "High", "Database password in connection string"),
["api_key_exposed"] = (new Regex(@"(api.?key|apikey|clientsecret)\s*[=:]\s*['""][^'""]{10,}['""]", RegexOptions.IgnoreCase),
"Secret", "Critical", "API key or client secret exposed in configuration"),
["jwt_secret_exposed"] = (new Regex(@"(jwt|token).*(secret|key)\s*[=:]\s*['""][^'""]{1,}['""]", RegexOptions.IgnoreCase),
"Secret", "Critical", "JWT secret exposed in configuration"),
["encryption_key_exposed"] = (new Regex(@"(encryption|cipher).*(key|secret)\s*[=:]\s*['""][^'""]{1,}['""]", RegexOptions.IgnoreCase),
"Secret", "Critical", "Encryption key exposed in configuration"),
// TLS/HTTPS Issues
["ssl_disabled"] = (new Regex(@"(ssl|https|tls)\s*[=:]\s*(false|disabled|no)", RegexOptions.IgnoreCase),
"TLS", "High", "SSL/TLS disabled in configuration"),
["weak_tls_version"] = (new Regex(@"(tls|ssl).*(version|protocol)\s*[=:]\s*['""]?(1\.0|1\.1|ssl)['""]?", RegexOptions.IgnoreCase),
"TLS", "High", "Weak TLS version configured (TLS 1.0/1.1 or SSL)"),
["insecure_ciphers"] = (new Regex(@"(cipher|encryption).*(rc4|des|md5|sha1)", RegexOptions.IgnoreCase),
"TLS", "Medium", "Weak cipher suites configured"),
["certificate_validation_disabled"] = (new Regex(@"(certificate|cert).*(validation|verify|check)\s*[=:]\s*(false|disabled|no)", RegexOptions.IgnoreCase),
"TLS", "High", "Certificate validation disabled"),
// Database Security
["integrated_security_disabled"] = (new Regex(@"integrated.?security\s*=\s*(false|no)", RegexOptions.IgnoreCase),
"Database", "Medium", "Integrated security disabled for database connection"),
["sql_server_trust_cert"] = (new Regex(@"trustservercertificate\s*=\s*true", RegexOptions.IgnoreCase),
"Database", "Medium", "SQL Server certificate trust enabled (potential MITM risk)"),
["database_timeout_too_long"] = (new Regex(@"(timeout|commandtimeout)\s*=\s*([5-9]\d{2,}|\d{4,})", RegexOptions.IgnoreCase),
"Database", "Low", "Very long database timeout configured"),
["database_no_encryption"] = (new Regex(@"encrypt\s*=\s*(false|no)", RegexOptions.IgnoreCase),
"Database", "Medium", "Database connection encryption disabled"),
// CORS Issues
["cors_allow_all_origins"] = (new Regex(@"(allowedorigins|origins)\s*.*\*", RegexOptions.IgnoreCase),
"CORS", "High", "CORS allows all origins (*)"),
["cors_allow_credentials_with_wildcard"] = (new Regex(@"(allowcredentials|credentials)\s*[=:]\s*true.*\*", RegexOptions.IgnoreCase),
"CORS", "High", "CORS allows credentials with wildcard origin"),
["cors_unsafe_headers"] = (new Regex(@"(allowedheaders|headers).*\*", RegexOptions.IgnoreCase),
"CORS", "Medium", "CORS allows all headers (*)"),
["cors_unsafe_methods"] = (new Regex(@"(allowedmethods|methods).*(delete|put|patch)", RegexOptions.IgnoreCase),
"CORS", "Low", "CORS allows potentially unsafe HTTP methods"),
// General Security Settings
["debug_mode_enabled"] = (new Regex(@"(debug|development)\s*[=:]\s*true", RegexOptions.IgnoreCase),
"General", "Medium", "Debug mode enabled"),
["detailed_errors_enabled"] = (new Regex(@"(detailederrors|customerrors)\s*[=:]\s*(on|true|detailed)", RegexOptions.IgnoreCase),
"General", "Medium", "Detailed error information enabled"),
["insecure_cookies"] = (new Regex(@"(httponly|secure)\s*[=:]\s*(false|no)", RegexOptions.IgnoreCase),
"General", "Medium", "Insecure cookie settings"),
["weak_session_timeout"] = (new Regex(@"(session|timeout)\s*[=:]\s*['""]?\d{1,2}['""]?", RegexOptions.IgnoreCase),
"General", "Low", "Very short session timeout"),
// Environment-Specific Issues
["prod_using_dev_settings"] = (new Regex(@"(environment|env)\s*[=:]\s*['""]?(development|dev)['""]?", RegexOptions.IgnoreCase),
"Environment", "High", "Production environment using development settings"),
["hardcoded_environment"] = (new Regex(@"(server|host|endpoint)\s*[=:]\s*['""]localhost['""]", RegexOptions.IgnoreCase),
"Environment", "Medium", "Hardcoded localhost/development server"),
["missing_environment_config"] = (new Regex(@"\{\{.*\}\}|\$\{.*\}", RegexOptions.IgnoreCase),
"Environment", "Low", "Environment variable placeholder found"),
// Logging Security
["sensitive_data_logging"] = (new Regex(@"(log|logging).*(password|secret|key|token)", RegexOptions.IgnoreCase),
"Logging", "High", "Sensitive data may be logged"),
["excessive_logging"] = (new Regex(@"(loglevel|level)\s*[=:]\s*['""]?(debug|trace|verbose)['""]?", RegexOptions.IgnoreCase),
"Logging", "Low", "Excessive logging level in production"),
["log_injection_risk"] = (new Regex(@"log.*user.*input", RegexOptions.IgnoreCase),
"Logging", "Medium", "Potential log injection from user input")
};
// Positive configuration patterns (good practices)
private static readonly Dictionary GoodConfigPatterns = new()
{
["environment_variables"] = new Regex(@"\$\{[^}]+\}|%[^%]+%", RegexOptions.IgnoreCase),
["https_enforced"] = new Regex(@"(https|ssl|tls)\s*[=:]\s*(true|enabled|yes)", RegexOptions.IgnoreCase),
["secure_cookies"] = new Regex(@"(httponly|secure)\s*[=:]\s*(true|yes)", RegexOptions.IgnoreCase),
["strong_tls"] = new Regex(@"(tls|ssl).*(1\.2|1\.3)", RegexOptions.IgnoreCase),
["security_headers"] = new Regex(@"(hsts|csp|x-frame-options|x-content-type-options)", RegexOptions.IgnoreCase),
["encrypted_connections"] = new Regex(@"encrypt\s*=\s*true", RegexOptions.IgnoreCase),
["certificate_validation"] = new Regex(@"(certificate|cert).*(validation|verify)\s*[=:]\s*(true|enabled)", RegexOptions.IgnoreCase)
};
public async Task ExecuteAsync(IReadOnlyDictionary parameters)
{
try
{
// Extract parameters
string configPath = parameters["configPath"].ToString();
bool checkSecrets = parameters.TryGetValue("checkSecrets", out var secretsObj) ? Convert.ToBoolean(secretsObj) : true;
bool checkTls = parameters.TryGetValue("checkTls", out var tlsObj) ? Convert.ToBoolean(tlsObj) : true;
bool checkDatabase = parameters.TryGetValue("checkDatabase", out var dbObj) ? Convert.ToBoolean(dbObj) : true;
bool checkCors = parameters.TryGetValue("checkCors", out var corsObj) ? Convert.ToBoolean(corsObj) : true;
bool checkEnvironments = parameters.TryGetValue("checkEnvironments", out var envObj) ? Convert.ToBoolean(envObj) : true;
// Validate path exists
if (!File.Exists(configPath) && !Directory.Exists(configPath))
{
return new AIPluginResult(
new FileNotFoundException($"Configuration path not found: {configPath}"),
"Configuration path not found"
);
}
// Find configuration files to analyze
var configFiles = GetConfigurationFiles(configPath);
if (!configFiles.Any())
{
return new AIPluginResult(
new FileNotFoundException($"No configuration files found in: {configPath}"),
"No configuration files found"
);
}
var results = new SecureConfigurationResults
{
ConfigPath = configPath,
FilesAnalyzed = configFiles.Count
};
// Analyze each configuration file
foreach (var configFile in configFiles)
{
await AnalyzeConfigurationFile(configFile, results, checkSecrets, checkTls, checkDatabase, checkCors, checkEnvironments);
}
// Calculate security rating
results.SecurityRating = CalculateSecurityRating(results);
// Generate configuration recommendations
results.ConfigurationRecommendations = GenerateConfigurationRecommendations(results);
return new AIPluginResult(results,
$"Configuration security analysis completed. Found {results.GetTotalIssues()} security issues.");
}
catch (Exception ex)
{
return new AIPluginResult(ex, $"Configuration security analysis failed: {ex.Message}");
}
}
///
/// Finds configuration files to analyze
///
private List GetConfigurationFiles(string path)
{
var configFiles = new List();
if (File.Exists(path))
{
if (IsConfigurationFile(path))
{
configFiles.Add(path);
}
}
else if (Directory.Exists(path))
{
// Look for common configuration file patterns
var patterns = new[]
{
"*.json", "*.config", "*.xml", "*.yml", "*.yaml",
"*.ini", "*.properties", "*.conf", "*.cfg", "*.env"
};
foreach (var pattern in patterns)
{
configFiles.AddRange(Directory.GetFiles(path, pattern, SearchOption.AllDirectories));
}
// Filter to actual configuration files
configFiles = configFiles.Where(IsConfigurationFile).ToList();
}
// Exclude common non-config directories
var excludedDirs = new[] { "node_modules", "bin", "obj", ".git", ".vs", "packages", "target", "build" };
configFiles = configFiles.Where(f => !excludedDirs.Any(dir => f.Contains($"{Path.DirectorySeparatorChar}{dir}{Path.DirectorySeparatorChar}"))).ToList();
return configFiles.Take(20).ToList(); // Limit for performance
}
///
/// Checks if a file is a configuration file
///
private bool IsConfigurationFile(string filePath)
{
var fileName = Path.GetFileName(filePath).ToLower();
var configNames = new[]
{
"appsettings", "web.config", "app.config", "config", "settings",
"environment", ".env", "database", "connection", "cors", "security"
};
return configNames.Any(name => fileName.Contains(name)) ||
fileName.EndsWith(".json") ||
fileName.EndsWith(".config") ||
fileName.EndsWith(".xml") ||
fileName.EndsWith(".yml") ||
fileName.EndsWith(".yaml") ||
fileName.EndsWith(".ini") ||
fileName.EndsWith(".properties");
}
///
/// Analyzes a single configuration file
///
private async Task AnalyzeConfigurationFile(string configFile, SecureConfigurationResults results,
bool checkSecrets, bool checkTls, bool checkDatabase, bool checkCors, bool checkEnvironments)
{
try
{
var content = await File.ReadAllTextAsync(configFile);
var fileName = Path.GetFileName(configFile);
var extension = Path.GetExtension(configFile).ToLower();
// Parse configuration based on file type
var configData = ParseConfigurationFile(content, extension);
// Perform security checks
if (checkSecrets)
{
await AnalyzeSecretsExposure(configFile, content, configData, results);
}
if (checkTls)
{
await AnalyzeTlsConfiguration(configFile, content, configData, results);
}
if (checkDatabase)
{
await AnalyzeDatabaseSecurity(configFile, content, configData, results);
}
if (checkCors)
{
await AnalyzeCorsConfiguration(configFile, content, configData, results);
}
if (checkEnvironments)
{
await AnalyzeEnvironmentConfiguration(configFile, content, configData, results);
}
// Check for good practices
await AnalyzeGoodPractices(configFile, content, results);
}
catch (Exception ex)
{
results.AnalysisErrors.Add($"Error analyzing {configFile}: {ex.Message}");
}
}
///
/// Parses configuration file content based on format
///
private Dictionary ParseConfigurationFile(string content, string extension)
{
var configData = new Dictionary();
try
{
switch (extension)
{
case ".json":
if (content.Trim().StartsWith("{"))
{
var jsonDoc = JsonDocument.Parse(content);
configData = JsonElementToDictionary(jsonDoc.RootElement);
}
break;
case ".xml":
case ".config":
var xmlDoc = XDocument.Parse(content);
configData = XmlToDictionary(xmlDoc);
break;
case ".yml":
case ".yaml":
// Simple YAML parsing (key: value pairs)
configData = ParseSimpleYaml(content);
break;
case ".ini":
case ".properties":
configData = ParseKeyValueFile(content);
break;
}
}
catch
{
// If parsing fails, fall back to regex analysis on raw content
}
return configData;
}
///
/// Converts JsonElement to Dictionary
///
private Dictionary JsonElementToDictionary(JsonElement element)
{
var dict = new Dictionary();
if (element.ValueKind == JsonValueKind.Object)
{
foreach (var property in element.EnumerateObject())
{
dict[property.Name] = property.Value.ValueKind == JsonValueKind.Object
? JsonElementToDictionary(property.Value)
: property.Value.ToString();
}
}
return dict;
}
///
/// Converts XML to Dictionary (simplified)
///
private Dictionary XmlToDictionary(XDocument doc)
{
var dict = new Dictionary();
foreach (var element in doc.Descendants())
{
if (!element.HasElements)
{
dict[element.Name.LocalName] = element.Value;
}
}
return dict;
}
///
/// Parses simple YAML (key: value pairs)
///
private Dictionary ParseSimpleYaml(string content)
{
var dict = new Dictionary();
var lines = content.Split('\n');
foreach (var line in lines)
{
var trimmed = line.Trim();
if (trimmed.Contains(':') && !trimmed.StartsWith('#'))
{
var parts = trimmed.Split(':', 2);
if (parts.Length == 2)
{
dict[parts[0].Trim()] = parts[1].Trim();
}
}
}
return dict;
}
///
/// Parses key=value format files
///
private Dictionary ParseKeyValueFile(string content)
{
var dict = new Dictionary();
var lines = content.Split('\n');
foreach (var line in lines)
{
var trimmed = line.Trim();
if (trimmed.Contains('=') && !trimmed.StartsWith('#') && !trimmed.StartsWith(';'))
{
var parts = trimmed.Split('=', 2);
if (parts.Length == 2)
{
dict[parts[0].Trim()] = parts[1].Trim();
}
}
}
return dict;
}
///
/// Analyzes configuration for exposed secrets
///
private async Task AnalyzeSecretsExposure(string filePath, string content, Dictionary configData, SecureConfigurationResults results)
{
var secretPatterns = ConfigPatterns.Where(p => p.Value.Type == "Secret").ToList();
foreach (var pattern in secretPatterns)
{
var matches = pattern.Value.Pattern.Matches(content);
foreach (Match match in matches)
{
// Additional validation for false positives
if (!IsLikelySecret(match.Value))
continue;
results.ExposedSecrets.Add(new ConfigurationIssue
{
Type = "Exposed Secret",
Severity = pattern.Value.Severity,
Description = pattern.Value.Description,
File = filePath,
LineNumber = GetLineNumber(content, match.Index),
ConfigKey = ExtractConfigKey(content, match.Index),
Value = MaskSensitiveValue(match.Value),
Recommendation = GetSecretsRecommendation(pattern.Key)
});
}
}
}
///
/// Analyzes TLS/HTTPS configuration
///
private async Task AnalyzeTlsConfiguration(string filePath, string content, Dictionary configData, SecureConfigurationResults results)
{
var tlsPatterns = ConfigPatterns.Where(p => p.Value.Type == "TLS").ToList();
foreach (var pattern in tlsPatterns)
{
var matches = pattern.Value.Pattern.Matches(content);
foreach (Match match in matches)
{
results.SecurityIssues.Add(new ConfigurationIssue
{
Type = "TLS/HTTPS Security",
Severity = pattern.Value.Severity,
Description = pattern.Value.Description,
File = filePath,
LineNumber = GetLineNumber(content, match.Index),
ConfigKey = ExtractConfigKey(content, match.Index),
Value = match.Value,
Recommendation = GetTlsRecommendation(pattern.Key)
});
}
}
}
///
/// Analyzes database security configuration
///
private async Task AnalyzeDatabaseSecurity(string filePath, string content, Dictionary configData, SecureConfigurationResults results)
{
var dbPatterns = ConfigPatterns.Where(p => p.Value.Type == "Database").ToList();
foreach (var pattern in dbPatterns)
{
var matches = pattern.Value.Pattern.Matches(content);
foreach (Match match in matches)
{
results.SecurityIssues.Add(new ConfigurationIssue
{
Type = "Database Security",
Severity = pattern.Value.Severity,
Description = pattern.Value.Description,
File = filePath,
LineNumber = GetLineNumber(content, match.Index),
ConfigKey = ExtractConfigKey(content, match.Index),
Value = MaskSensitiveValue(match.Value),
Recommendation = GetDatabaseRecommendation(pattern.Key)
});
}
}
}
///
/// Analyzes CORS configuration
///
private async Task AnalyzeCorsConfiguration(string filePath, string content, Dictionary configData, SecureConfigurationResults results)
{
var corsPatterns = ConfigPatterns.Where(p => p.Value.Type == "CORS").ToList();
foreach (var pattern in corsPatterns)
{
var matches = pattern.Value.Pattern.Matches(content);
foreach (Match match in matches)
{
results.SecurityIssues.Add(new ConfigurationIssue
{
Type = "CORS Security",
Severity = pattern.Value.Severity,
Description = pattern.Value.Description,
File = filePath,
LineNumber = GetLineNumber(content, match.Index),
ConfigKey = ExtractConfigKey(content, match.Index),
Value = match.Value,
Recommendation = GetCorsRecommendation(pattern.Key)
});
}
}
}
///
/// Analyzes environment-specific configuration
///
private async Task AnalyzeEnvironmentConfiguration(string filePath, string content, Dictionary configData, SecureConfigurationResults results)
{
var envPatterns = ConfigPatterns.Where(p => p.Value.Type == "Environment" || p.Value.Type == "General" || p.Value.Type == "Logging").ToList();
foreach (var pattern in envPatterns)
{
var matches = pattern.Value.Pattern.Matches(content);
foreach (Match match in matches)
{
var severity = pattern.Value.Severity;
// Adjust severity for environment-specific issues
if (pattern.Value.Type == "Environment" && IsProductionConfig(filePath))
{
severity = severity == "Medium" ? "High" : severity;
}
results.EnvironmentIssues.Add(new ConfigurationIssue
{
Type = pattern.Value.Type,
Severity = severity,
Description = pattern.Value.Description,
File = filePath,
LineNumber = GetLineNumber(content, match.Index),
ConfigKey = ExtractConfigKey(content, match.Index),
Value = match.Value,
Recommendation = GetEnvironmentRecommendation(pattern.Key)
});
}
}
}
///
/// Analyzes good security practices in configuration
///
private async Task AnalyzeGoodPractices(string filePath, string content, SecureConfigurationResults results)
{
foreach (var pattern in GoodConfigPatterns)
{
if (pattern.Value.IsMatch(content))
{
var practiceDescription = GetGoodPracticeDescription(pattern.Key);
if (!results.GoodPractices.Contains(practiceDescription))
{
results.GoodPractices.Add(practiceDescription);
}
}
}
}
///
/// Checks if a match is likely a real secret
///
private bool IsLikelySecret(string value)
{
// Filter out common non-secrets
var nonSecrets = new[] { "password", "secret", "key", "token", "example", "placeholder", "your_", "xxx", "***", "localhost", "127.0.0.1" };
var lowerValue = value.ToLower();
if (nonSecrets.Any(ns => lowerValue.Contains(ns)))
return false;
// Check for reasonable length and complexity
var cleanValue = value.Replace("\"", "").Replace("'", "").Trim();
return cleanValue.Length >= 8 && cleanValue.Any(char.IsLetterOrDigit);
}
///
/// Checks if configuration file is for production environment
///
private bool IsProductionConfig(string filePath)
{
var fileName = Path.GetFileName(filePath).ToLower();
return fileName.Contains("prod") || fileName.Contains("production") || fileName.Contains("release");
}
///
/// Extracts configuration key from context
///
private string ExtractConfigKey(string content, int index)
{
var lines = content.Split('\n');
var lineNumber = GetLineNumber(content, index) - 1;
if (lineNumber >= 0 && lineNumber < lines.Length)
{
var line = lines[lineNumber];
var colonIndex = line.IndexOf(':');
var equalsIndex = line.IndexOf('=');
if (colonIndex > 0 && (equalsIndex < 0 || colonIndex < equalsIndex))
{
return line.Substring(0, colonIndex).Trim().Trim('"', '\'');
}
else if (equalsIndex > 0)
{
return line.Substring(0, equalsIndex).Trim().Trim('"', '\'');
}
}
return "unknown";
}
///
/// Masks sensitive values for display
///
private string MaskSensitiveValue(string value)
{
if (value.Length <= 4)
return "***";
return value.Substring(0, 2) + "***" + value.Substring(value.Length - 2);
}
///
/// Gets line number for character index
///
private int GetLineNumber(string content, int index)
{
return content.Take(index).Count(c => c == '\n') + 1;
}
///
/// Gets secrets-specific recommendations
///
private string GetSecretsRecommendation(string patternKey)
{
return patternKey switch
{
"password_in_config" => "Move passwords to environment variables or secure key management systems like Azure Key Vault or AWS Secrets Manager.",
"connection_string_password" => "Use integrated authentication or move connection strings to secure configuration providers.",
"api_key_exposed" => "Store API keys in environment variables and use secure configuration providers.",
"jwt_secret_exposed" => "Move JWT secrets to environment variables and ensure they are cryptographically strong.",
"encryption_key_exposed" => "Store encryption keys in dedicated key management systems, never in configuration files.",
_ => "Move all secrets to environment variables or dedicated secret management systems."
};
}
///
/// Gets TLS-specific recommendations
///
private string GetTlsRecommendation(string patternKey)
{
return patternKey switch
{
"ssl_disabled" => "Enable HTTPS/TLS for all production environments to protect data in transit.",
"weak_tls_version" => "Use TLS 1.2 or 1.3. Disable older protocols (TLS 1.0/1.1, SSL 2.0/3.0).",
"insecure_ciphers" => "Configure strong cipher suites and disable weak algorithms like RC4, DES, MD5.",
"certificate_validation_disabled" => "Enable certificate validation to prevent man-in-the-middle attacks.",
_ => "Implement strong TLS configuration with modern protocols and cipher suites."
};
}
///
/// Gets database-specific recommendations
///
private string GetDatabaseRecommendation(string patternKey)
{
return patternKey switch
{
"integrated_security_disabled" => "Use integrated security (Windows Authentication) when possible for better security.",
"sql_server_trust_cert" => "Verify server certificates properly instead of blindly trusting them.",
"database_timeout_too_long" => "Use reasonable database timeouts to prevent resource exhaustion.",
"database_no_encryption" => "Enable encryption for database connections, especially over networks.",
_ => "Follow database security best practices including encrypted connections and proper authentication."
};
}
///
/// Gets CORS-specific recommendations
///
private string GetCorsRecommendation(string patternKey)
{
return patternKey switch
{
"cors_allow_all_origins" => "Specify explicit allowed origins instead of using wildcards (*) in production.",
"cors_allow_credentials_with_wildcard" => "Never allow credentials with wildcard origins - specify exact domains.",
"cors_unsafe_headers" => "Specify only required headers instead of allowing all headers (*).",
"cors_unsafe_methods" => "Review if unsafe HTTP methods (DELETE, PUT, PATCH) are necessary for CORS.",
_ => "Configure CORS with specific, minimal permissions based on actual requirements."
};
}
///
/// Gets environment-specific recommendations
///
private string GetEnvironmentRecommendation(string patternKey)
{
return patternKey switch
{
"prod_using_dev_settings" => "Ensure production environments use production-specific configuration, not development settings.",
"debug_mode_enabled" => "Disable debug mode in production to prevent information disclosure.",
"detailed_errors_enabled" => "Disable detailed error messages in production to prevent information leakage.",
"hardcoded_environment" => "Use environment-specific configuration instead of hardcoded development values.",
"sensitive_data_logging" => "Ensure sensitive data is not logged. Use structured logging with data classification.",
"excessive_logging" => "Use appropriate logging levels in production (Info/Warning/Error, not Debug/Trace).",
_ => "Review environment-specific settings and ensure appropriate configuration for each environment."
};
}
///
/// Gets description for good practices
///
private string GetGoodPracticeDescription(string patternKey)
{
return patternKey switch
{
"environment_variables" => "Uses environment variables for configuration",
"https_enforced" => "Enforces HTTPS/TLS encryption",
"secure_cookies" => "Uses secure cookie settings",
"strong_tls" => "Uses modern TLS versions (1.2/1.3)",
"security_headers" => "Implements security headers",
"encrypted_connections" => "Uses encrypted database connections",
"certificate_validation" => "Enables proper certificate validation",
_ => $"Implements {patternKey} security feature"
};
}
///
/// Calculates overall security rating
///
private string CalculateSecurityRating(SecureConfigurationResults results)
{
var totalIssues = results.GetTotalIssues();
var criticalIssues = results.ExposedSecrets.Count(s => s.Severity == "Critical") +
results.SecurityIssues.Count(s => s.Severity == "Critical") +
results.EnvironmentIssues.Count(s => s.Severity == "Critical");
var highIssues = results.ExposedSecrets.Count(s => s.Severity == "High") +
results.SecurityIssues.Count(s => s.Severity == "High") +
results.EnvironmentIssues.Count(s => s.Severity == "High");
if (criticalIssues > 0)
return "Critical Risk";
else if (highIssues >= 3)
return "High Risk";
else if (totalIssues >= 5)
return "Medium Risk";
else if (totalIssues > 0)
return "Low Risk";
else
return "Secure";
}
///
/// Generates configuration recommendations
///
private List GenerateConfigurationRecommendations(SecureConfigurationResults results)
{
var recommendations = new List();
// Critical secrets exposure
var criticalSecrets = results.ExposedSecrets.Where(s => s.Severity == "Critical").ToList();
if (criticalSecrets.Any())
{
recommendations.Add("🚨 **CRITICAL: SECRETS EXPOSED**:");
recommendations.Add($" • {criticalSecrets.Count} critical secrets found in configuration files");
recommendations.Add(" • Immediately move secrets to environment variables or key vaults");
recommendations.Add(" • Rotate any exposed secrets/keys immediately");
recommendations.Add(" • Review commit history for accidentally committed secrets");
}
// High severity issues
var highSecrets = results.ExposedSecrets.Where(s => s.Severity == "High").ToList();
if (highSecrets.Any())
{
recommendations.Add("⚠️ **HIGH PRIORITY: SECRET MANAGEMENT**:");
recommendations.Add($" • {highSecrets.Count} high-risk secrets found");
recommendations.Add(" • Implement proper secret management strategy");
recommendations.Add(" • Use Azure Key Vault, AWS Secrets Manager, or similar services");
}
// TLS/HTTPS issues
var tlsIssues = results.SecurityIssues.Where(i => i.Type.Contains("TLS")).ToList();
if (tlsIssues.Any())
{
recommendations.Add("🔒 **TLS/HTTPS SECURITY**:");
recommendations.Add($" • {tlsIssues.Count} TLS security issues found");
recommendations.Add(" • Enable HTTPS enforcement for all environments");
recommendations.Add(" • Use TLS 1.2 or 1.3, disable older protocols");
recommendations.Add(" • Configure strong cipher suites");
}
// Database security
var dbIssues = results.SecurityIssues.Where(i => i.Type.Contains("Database")).ToList();
if (dbIssues.Any())
{
recommendations.Add("🗄️ **DATABASE SECURITY**:");
recommendations.Add($" • {dbIssues.Count} database security issues found");
recommendations.Add(" • Enable connection encryption");
recommendations.Add(" • Use integrated authentication where possible");
recommendations.Add(" • Move connection strings to secure configuration");
}
// CORS issues
var corsIssues = results.SecurityIssues.Where(i => i.Type.Contains("CORS")).ToList();
if (corsIssues.Any())
{
recommendations.Add("🌐 **CORS CONFIGURATION**:");
recommendations.Add($" • {corsIssues.Count} CORS security issues found");
recommendations.Add(" • Specify explicit allowed origins (avoid wildcards)");
recommendations.Add(" • Review allowed headers and methods");
recommendations.Add(" • Never allow credentials with wildcard origins");
}
// Environment issues
if (results.EnvironmentIssues.Any())
{
recommendations.Add("⚙️ **ENVIRONMENT CONFIGURATION**:");
var envByType = results.EnvironmentIssues.GroupBy(i => i.Type).ToList();
foreach (var group in envByType.Take(3))
{
recommendations.Add($" • {group.Key}: {group.Count()} issues");
}
recommendations.Add(" • Ensure production uses production-specific settings");
recommendations.Add(" • Disable debug mode and detailed errors in production");
}
// General best practices
recommendations.Add("📋 **CONFIGURATION BEST PRACTICES**:");
recommendations.Add(" • Use environment variables for all sensitive values");
recommendations.Add(" • Implement configuration validation on startup");
recommendations.Add(" • Use different configuration files for each environment");
recommendations.Add(" • Enable security headers (HSTS, CSP, X-Frame-Options)");
recommendations.Add(" • Implement proper logging without sensitive data");
recommendations.Add(" • Regular security configuration reviews");
// Positive reinforcement
if (results.GoodPractices.Any())
{
recommendations.Add("✅ **GOOD PRACTICES FOUND**:");
foreach (var practice in results.GoodPractices.Take(5))
{
recommendations.Add($" • {practice}");
}
}
// Overall security rating recommendations
switch (results.SecurityRating)
{
case "Critical Risk":
recommendations.Add("🚨 **IMMEDIATE ACTION REQUIRED**: Critical security vulnerabilities found");
recommendations.Add(" • Stop deployment until critical issues are resolved");
recommendations.Add(" • Conduct emergency security review");
break;
case "High Risk":
recommendations.Add("⚠️ **HIGH PRIORITY**: Significant security improvements needed");
recommendations.Add(" • Address high-severity issues before next deployment");
break;
case "Medium Risk":
recommendations.Add("👍 **GOOD**: Address remaining issues to improve security posture");
break;
case "Low Risk":
recommendations.Add("🌟 **EXCELLENT**: Minor improvements needed");
break;
case "Secure":
recommendations.Add("🏆 **OUTSTANDING**: Configuration follows security best practices!");
recommendations.Add(" • Continue regular security reviews");
break;
}
return recommendations;
}
}
///
/// Results of secure configuration analysis
///
public class SecureConfigurationResults
{
public string ConfigPath { get; set; }
public int FilesAnalyzed { get; set; }
public List ExposedSecrets { get; set; } = new List();
public List SecurityIssues { get; set; } = new List();
public List EnvironmentIssues { get; set; } = new List();
public List GoodPractices { get; set; } = new List();
public List ConfigurationRecommendations { get; set; } = new List();
public List AnalysisErrors { get; set; } = new List();
public string SecurityRating { get; set; }
public int GetTotalIssues() => ExposedSecrets.Count + SecurityIssues.Count + EnvironmentIssues.Count;
}
///
/// Represents a configuration security issue
///
public class ConfigurationIssue
{
public string Type { get; set; }
public string Severity { get; set; }
public string Description { get; set; }
public string File { get; set; }
public int LineNumber { get; set; }
public string ConfigKey { get; set; }
public string Value { get; set; }
public string Recommendation { get; set; }
}
}