Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/codacy-rules-ai.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ rules:
$CLIENT.GenerateContentAsync(model: "$MODEL", ...)
- metavariable-regex:
metavariable: $MODEL
regex: "<!-- MODEL_REGEX -->"
regex: <!-- MODEL_ALLOW_LIST -->
metadata:
category: security
subcategory: ai
description: Detects usage of insecure/unauthorized LLM models in C# codebases
technology:
- csharp
impact: MEDIUM
confidence: MEDIUM
confidence: LOW
likelihood: MEDIUM
86 changes: 85 additions & 1 deletion docs/codacy-rules-i18n.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,90 @@ rules:
technology:
- java
impact: MEDIUM
confidence: HIGH
confidence: LOW
likelihood: HIGH

- id: codacy.js.i18n.no-hardcoded-alert-concat
severity: WARNING
languages:
- js
- ts
pattern-either:
# Direct hardcoded alert strings
- pattern: alert("...")
- pattern: window.alert("...")
# String concatenation in alerts
- pattern: alert("..." + ...)
- pattern: alert(... + "...")
- pattern: window.alert("..." + ...)
- pattern: window.alert(... + "...")
pattern-not: alert(t(...))
message: >-
Avoid hardcoded or concatenated strings in alerts. Use an i18n translation function (e.g., t("key")) with interpolation.
metadata:
category: codestyle
subcategory: i18n
description: Flags hardcoded and concatenated strings in alert dialogs to enforce localization
technology:
- javascript
- typescript
impact: MEDIUM
confidence: LOW
likelihood: HIGH

- id: codacy.js.i18n.no-hardcoded-locale-date
severity: WARNING
languages:
- js
- ts
pattern-regex: "\\.(toLocale(Date|Time)?String)\\(\"[^\"]+\""
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This regex pattern may have unintended matches. The pattern "\\.(toLocale(Date|Time)?String)\\(\"[^\"]+\"" will only match cases where the locale string is immediately after the opening parenthesis with no whitespace. It won't match cases like .toLocaleDateString( "en-US") or .toLocaleDateString(options, "en-US"). Consider using a more flexible pattern that accounts for optional whitespace and multiple parameters.

Suggested change
pattern-regex: "\\.(toLocale(Date|Time)?String)\\(\"[^\"]+\""
pattern-regex: "\\.(toLocale(Date|Time)?String)\\([^)]*\"[^\"]+\""

Copilot uses AI. Check for mistakes.
message: Avoid hardcoded locale strings in date/time formatting.
metadata:
category: codestyle
subcategory: i18n
description: Flags explicit locale strings in date/time formatting which can break localization
technology:
- javascript
- typescript
impact: MEDIUM
confidence: LOW
likelihood: HIGH

- id: codacy.js.i18n.no-hardcoded-number-format
severity: WARNING
languages:
- js
- ts
pattern-regex: "\\.toFixed\\([^)]*\\)"
message: >-
Avoid using toFixed for user-visible number formatting. Use locale-aware formatting or translation helpers.
metadata:
category: codestyle
subcategory: i18n
description: Flags toFixed used for UI number formatting; recommends locale-aware alternatives
technology:
- javascript
- typescript
impact: MEDIUM
confidence: LOW
likelihood: HIGH

- id: codacy.js.i18n.no-raw-jsx-text
severity: WARNING
languages:
- js
- ts
pattern-regex: "<(h1|h2|h3|h4|h5|h6|p|span|div|td|th)[^>]*>[^<{]*[A-Za-z][^<{]*</\\1>"
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This regex pattern is overly broad and will produce many false positives. The pattern <(h1|h2|h3|h4|h5|h6|p|span|div|td|th)[^>]*>[^<{]*[A-Za-z][^<{]*</\\1> will flag any element containing a single letter, including legitimate cases like variable names (e.g., <span>{x}</span>), single-letter abbreviations, or code examples. The pattern also doesn't account for numbers or punctuation-only content that might be acceptable. Consider making this pattern more specific to catch meaningful text content (e.g., multiple words) rather than any alphabetic character.

Suggested change
pattern-regex: "<(h1|h2|h3|h4|h5|h6|p|span|div|td|th)[^>]*>[^<{]*[A-Za-z][^<{]*</\\1>"
pattern-regex: "<(h1|h2|h3|h4|h5|h6|p|span|div|td|th)[^>]*>[^<{]*[A-Za-z]{2,}[^<{]*\\s+[A-Za-z]{2,}[^<{]*</\\1>"

Copilot uses AI. Check for mistakes.
message: >-
Avoid raw text in JSX for user-facing content. Use i18n translation functions (e.g., t("key")) with interpolation.
metadata:
category: codestyle
subcategory: i18n
description: Flags raw text nodes in JSX elements to enforce localization of UI strings
technology:
- javascript
- typescript
impact: MEDIUM
confidence: LOW
likelihood: MEDIUM

2 changes: 1 addition & 1 deletion docs/multiple-tests/ai/patterns.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<module name="root">
<module name="codacy.csharp.ai.insecure-llm-model-usage">
<property name="modelRegex" value="^(gemini-2.5-flash|gpt-3\\.5-turbo|old-llama-model)$" />
<property name="modelAllowList" value="gemini-2.5-flash,gpt-3.5-turbo,old-llama-model" />
</module>
</module>
2 changes: 1 addition & 1 deletion docs/multiple-tests/ai/results.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<checkstyle version="1.5">
<file name="cs/GeminiExample.cs">
<error source="codacy.csharp.ai.insecure-llm-model-usage" line="9"
message="Usage of Insecure LLM Model: gemini-2.5-flash"
message="Usage of Insecure LLM Model: deepseek-v3.2"
severity="error" />
</file>
</checkstyle>
Expand Down
3 changes: 3 additions & 0 deletions docs/multiple-tests/ai/src/cs/GeminiExample.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assignment to response2 is useless, since its value is never read.

Suggested change
var response2 = await client.Models.GenerateContentAsync(
await client.Models.GenerateContentAsync(

Copilot uses AI. Check for mistakes.
model: "gemini-2.5-flash", contents: "Explain how AI works in a few words"
);
Console.WriteLine(response.Candidates[0].Content.Parts[0].Text);
Expand Down
3 changes: 3 additions & 0 deletions docs/multiple-tests/i18n/patterns.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<module name="root">
<module name="codacy.java.i18n.enforce-localized-output" />
<module name="codacy.js.i18n.no-hardcoded-alert-concat" />
<module name="codacy.js.i18n.no-hardcoded-locale-date" />
<module name="codacy.js.i18n.no-hardcoded-number-format" />
</module>
16 changes: 16 additions & 0 deletions docs/multiple-tests/i18n/results.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,21 @@
message="Use localized messages instead of hardcoded strings."
severity="warning" />
</file>
<file name="OrderList.js">
<error source="codacy.js.i18n.no-hardcoded-alert-concat" line="19"
message="Avoid hardcoded or concatenated strings in alerts."
severity="warning" />
</file>
<file name="Orderlist.jsx">
<error source="codacy.js.i18n.no-hardcoded-alert-concat" line="15"
message="Avoid hardcoded or concatenated strings in alerts."
severity="warning" />
<error source="codacy.js.i18n.no-hardcoded-locale-date" line="46"
message="Avoid hardcoded locale strings in date/time formatting."
severity="warning" />
<error source="codacy.js.i18n.no-hardcoded-number-format" line="52"
message="Avoid using toFixed for user-visible number formatting."
severity="warning" />
</file>
</checkstyle>

31 changes: 29 additions & 2 deletions internal/tool/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,17 +167,23 @@ 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
if value == nil {
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
}
}
}
Expand All @@ -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)$"
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The example in this comment is misleading. It shows the output format for the include=true case (^(...)$), but when this function is actually called on line 184, it's always called with include=false, which produces a different pattern: ^(?!(...)$).* (a negative lookahead). Update the example to show the actual pattern generated for the include=false case, or include both examples to clarify the difference.

Suggested change
// Example: "gemini-2.5-flash,gpt-3.5-turbo,old-llama-model" -> "^(gemini-2\\.5-flash|gpt-3\\.5-turbo|old-llama-model)$"
// Examples:
// convertListToRegex("gemini-2.5-flash,gpt-3.5-turbo,old-llama-model", true) -> "^(gemini-2\\.5-flash|gpt-3\\.5-turbo|old-llama-model)$"
// convertListToRegex("gemini-2.5-flash,gpt-3.5-turbo,old-llama-model", false) -> "^(?!(gemini-2\\.5-flash|gpt-3\\.5-turbo|old-llama-model)$).*"

Copilot uses AI. Check for mistakes.
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, ".", "\\.")
Comment on lines +206 to +207
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The regex escaping in this function is incomplete and could cause incorrect pattern matching. Currently, only dots are escaped, but regex has many other special characters that need escaping (e.g., +, *, ?, [, ], (, ), {, }, ^, $, |, ). For example, if a model name contains "gpt-4+" or "model[v2]", these would be interpreted as regex operators rather than literal characters. Use a proper regex escaping function like regexp.QuoteMeta() to escape all special characters.

Suggested change
// Escape dots for regex
item = strings.ReplaceAll(item, ".", "\\.")
// Escape all regex metacharacters
item = regexp.QuoteMeta(item)

Copilot uses AI. Check for mistakes.
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, "|"))
}
Comment on lines +200 to +217
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new convertListToRegex function lacks test coverage. Given that this function performs critical regex pattern generation with special character escaping and complex logic for allow/deny lists, it should have comprehensive unit tests covering edge cases such as: empty lists, lists with special regex characters, single-item lists, and both include=true and include=false branches.

Copilot uses AI. Check for mistakes.

// formatParameterName converts UPPER_CASE to camelCase
func formatParameterName(name string) string {
parts := strings.Split(strings.ToLower(name), "_")
Expand Down