diff --git a/docs/codacy-rules-ai.yaml b/docs/codacy-rules-ai.yaml
index cccebf7..d58dc0b 100644
--- a/docs/codacy-rules-ai.yaml
+++ b/docs/codacy-rules-ai.yaml
@@ -12,7 +12,7 @@ rules:
$CLIENT.GenerateContentAsync(model: "$MODEL", ...)
- metavariable-regex:
metavariable: $MODEL
- regex: ""
+ regex:
metadata:
category: security
subcategory: ai
@@ -20,5 +20,5 @@ rules:
technology:
- csharp
impact: MEDIUM
- confidence: MEDIUM
+ confidence: LOW
likelihood: MEDIUM
\ No newline at end of file
diff --git a/docs/multiple-tests/ai/patterns.xml b/docs/multiple-tests/ai/patterns.xml
index 6821449..e87962a 100644
--- a/docs/multiple-tests/ai/patterns.xml
+++ b/docs/multiple-tests/ai/patterns.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/docs/multiple-tests/ai/results.xml b/docs/multiple-tests/ai/results.xml
index bd884b1..cf09e18 100644
--- a/docs/multiple-tests/ai/results.xml
+++ b/docs/multiple-tests/ai/results.xml
@@ -2,7 +2,7 @@
diff --git a/docs/multiple-tests/ai/src/cs/GeminiExample.cs b/docs/multiple-tests/ai/src/cs/GeminiExample.cs
index e6324f3..b487990 100644
--- a/docs/multiple-tests/ai/src/cs/GeminiExample.cs
+++ b/docs/multiple-tests/ai/src/cs/GeminiExample.cs
@@ -7,6 +7,9 @@ public static async Task main() {
// The client gets the API key from the environment variable `GEMINI_API_KEY`.
var client = new Client();
var response = await client.Models.GenerateContentAsync(
+ model: "deepseek-v3.2", contents: "Explain how AI works in a few words"
+ );
+ var response2 = await client.Models.GenerateContentAsync(
model: "gemini-2.5-flash", contents: "Explain how AI works in a few words"
);
Console.WriteLine(response.Candidates[0].Content.Parts[0].Text);
diff --git a/internal/tool/configuration.go b/internal/tool/configuration.go
index 2730760..8bb2346 100644
--- a/internal/tool/configuration.go
+++ b/internal/tool/configuration.go
@@ -167,9 +167,9 @@ func replaceParameterPlaceholders(line string, pattern *codacy.Pattern) string {
paramName := matches[1]
// Convert UPPER_CASE to camelCase to match parameter name format
formattedParamName := formatParameterName(paramName)
-
// Find the parameter in the pattern
for _, param := range pattern.Parameters {
+
if param.Name == formattedParamName {
// Use Value if set, otherwise use Default
value := param.Value
@@ -177,7 +177,13 @@ func replaceParameterPlaceholders(line string, pattern *codacy.Pattern) string {
value = param.Default
}
if value != nil {
- return fmt.Sprintf("%v", value)
+ valueStr := fmt.Sprintf("%v", value)
+
+ // If parameter name ends with _ALLOW_LIST, convert comma-separated list to regex pattern
+ if strings.HasSuffix(paramName, "_ALLOW_LIST") {
+ return convertListToRegex(valueStr, false)
+ }
+ return valueStr
}
}
}
@@ -189,6 +195,27 @@ func replaceParameterPlaceholders(line string, pattern *codacy.Pattern) string {
return result
}
+// convertListToRegex converts a comma-separated list into a regex alternation pattern
+// Example: "gemini-2.5-flash,gpt-3.5-turbo,old-llama-model" -> "^(gemini-2\\.5-flash|gpt-3\\.5-turbo|old-llama-model)$"
+func convertListToRegex(list string, include bool) string {
+ // Split by comma and trim spaces
+ items := strings.Split(list, ",")
+ for i, item := range items {
+ // Trim whitespace
+ item = strings.TrimSpace(item)
+ // Escape dots for regex
+ item = strings.ReplaceAll(item, ".", "\\.")
+ items[i] = item
+ }
+
+ // Join with pipe separator and wrap in regex anchors
+ if include {
+ return fmt.Sprintf("^(%s)$", strings.Join(items, "|"))
+ }
+
+ return fmt.Sprintf("^(?!(%s)$).*", strings.Join(items, "|"))
+}
+
// formatParameterName converts UPPER_CASE to camelCase
func formatParameterName(name string) string {
parts := strings.Split(strings.ToLower(name), "_")