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), "_")