-
Notifications
You must be signed in to change notification settings - Fork 2
Add i18n and ai rules - batch 1 #74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| rules: | ||
| - id: codacy.csharp.ai.insecure-llm-model-usage | ||
| languages: | ||
| - csharp | ||
| message: "Usage of Insecure LLM Model: $MODEL" | ||
| severity: ERROR | ||
| patterns: | ||
| - pattern-either: | ||
| - pattern: | | ||
| $CLIENT.GenerateContentAsync(..., model: "$MODEL", ...) | ||
| - pattern: | | ||
| $CLIENT.GenerateContentAsync(model: "$MODEL", ...) | ||
| - metavariable-regex: | ||
| metavariable: $MODEL | ||
| regex: "<!-- MODEL_REGEX -->" | ||
| metadata: | ||
| category: security | ||
| subcategory: ai | ||
| description: Detects usage of insecure/unauthorized LLM models in C# codebases | ||
| technology: | ||
| - csharp | ||
| impact: MEDIUM | ||
| confidence: MEDIUM | ||
| likelihood: MEDIUM |
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,43 @@ | ||||||||
| rules: | ||||||||
| - id: codacy.java.i18n.enforce-localized-output | ||||||||
| severity: WARNING | ||||||||
| languages: | ||||||||
| - java | ||||||||
| patterns: | ||||||||
| - pattern-either: | ||||||||
| # Detect direct string literals | ||||||||
| - pattern: System.out.println("..."); | ||||||||
| - pattern: System.out.print("..."); | ||||||||
| - pattern: System.err.println("..."); | ||||||||
| - pattern: System.err.print("..."); | ||||||||
| # Detect string concatenation | ||||||||
| - pattern: System.out.println($X + ...); | ||||||||
| - pattern: System.out.print($X + ...); | ||||||||
| - pattern: System.err.println($X + ...); | ||||||||
| - pattern: System.err.print($X + ...); | ||||||||
| # Detect String.format without ResourceBundle | ||||||||
| - pattern: System.out.println(String.format(...)); | ||||||||
| - pattern: System.out.print(String.format(...)); | ||||||||
| - pattern-not: System.out.println($BUNDLE.getString(...)) | ||||||||
| - pattern-not: System.out.print($BUNDLE.getString(...)) | ||||||||
| - pattern-not: System.err.println($BUNDLE.getString(...)) | ||||||||
| - pattern-not: System.err.print($BUNDLE.getString(...)) | ||||||||
| - pattern-not: System.out.println($BUNDLE.getObject(...)) | ||||||||
| - pattern-not: System.out.print($BUNDLE.getObject(...)) | ||||||||
| # Allow println without arguments (blank lines) | ||||||||
| - pattern-not: System.out.println() | ||||||||
| - pattern-not: System.err.println() | ||||||||
| message: >- | ||||||||
| Use localized messages instead of hardcoded strings. | ||||||||
| System.out.println() should use ResourceBundle.getString() or equivalent localization method. | ||||||||
| Example: System.out.println(messages.getString("key")) where messages is of type java.util.ResourceBundle | ||||||||
| metadata: | ||||||||
| category: codestyle | ||||||||
| subcategory: i18n | ||||||||
| description: Enforces use of ResourceBundle for all user-facing output to ensure proper internationalization | ||||||||
| technology: | ||||||||
| - java | ||||||||
| impact: MEDIUM | ||||||||
| confidence: HIGH | ||||||||
| likelihood: HIGH | ||||||||
|
|
||||||||
|
Comment on lines
+42
to
+43
|
||||||||
| likelihood: HIGH | |
| likelihood: HIGH |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +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)$" /> | ||
| </module> | ||
| </module> |
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,9 @@ | ||||||||
| <?xml version="1.0" encoding="utf-8"?> | ||||||||
| <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" | ||||||||
| severity="error" /> | ||||||||
| </file> | ||||||||
| </checkstyle> | ||||||||
|
|
||||||||
|
Comment on lines
+8
to
+9
|
||||||||
| </checkstyle> | |
| </checkstyle> |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,14 @@ | ||||||
| using System.Threading.Tasks; | ||||||
| using Google.GenAI; | ||||||
| using Google.GenAI.Types; | ||||||
|
|
||||||
| public class GenerateContentSimpleText { | ||||||
| public static async Task main() { | ||||||
|
||||||
| public static async Task main() { | |
| public static async Task Main() { |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <module name="root"> | ||
| <module name="codacy.java.i18n.enforce-localized-output" /> | ||
| </module> |
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,33 @@ | ||||||||
| <?xml version="1.0" encoding="utf-8"?> | ||||||||
| <checkstyle version="1.5"> | ||||||||
| <file name="UILayer.java"> | ||||||||
| <error source="codacy.java.i18n.enforce-localized-output" line="12" | ||||||||
| message="Use localized messages instead of hardcoded strings." | ||||||||
| severity="warning" /> | ||||||||
| <error source="codacy.java.i18n.enforce-localized-output" line="22" | ||||||||
| message="Use localized messages instead of hardcoded strings." | ||||||||
| severity="warning" /> | ||||||||
| </file> | ||||||||
| <file name="OrderApp.java"> | ||||||||
| <error source="codacy.java.i18n.enforce-localized-output" line="18" | ||||||||
| message="Use localized messages instead of hardcoded strings." | ||||||||
| severity="warning" /> | ||||||||
| <error source="codacy.java.i18n.enforce-localized-output" line="30" | ||||||||
| message="Use localized messages instead of hardcoded strings." | ||||||||
| severity="warning" /> | ||||||||
| </file> | ||||||||
| <file name="OrderService.java"> | ||||||||
| <error source="codacy.java.i18n.enforce-localized-output" line="13" | ||||||||
| message="Use localized messages instead of hardcoded strings." | ||||||||
| severity="warning" /> | ||||||||
| <error source="codacy.java.i18n.enforce-localized-output" line="24" | ||||||||
| message="Use localized messages instead of hardcoded strings." | ||||||||
| severity="warning" /> | ||||||||
| </file> | ||||||||
| <file name="PaymentService.java"> | ||||||||
| <error source="codacy.java.i18n.enforce-localized-output" line="17" | ||||||||
| message="Use localized messages instead of hardcoded strings." | ||||||||
| severity="warning" /> | ||||||||
| </file> | ||||||||
| </checkstyle> | ||||||||
|
|
||||||||
|
Comment on lines
+32
to
+33
|
||||||||
| </checkstyle> | |
| </checkstyle> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| app.start=Welcome to the Internationalized Order System | ||
| order.processing=Processing order for {0} with {1} items. | ||
| order.success=Order placed successfully for {0}! | ||
| payment.success=Payment of {1} processed for customer {0}. | ||
| error.payment=Payment could not be processed. Please try again. | ||
| button.cancel=Cancel |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| app.start=Bienvenue dans le système de commande internationalisé | ||
| order.processing=Traitement de la commande pour {0} avec {1} articles. | ||
| order.success=Commande passée avec succès pour {0}! | ||
| payment.success=Paiement de {1} traité pour le client {0}. | ||
| error.payment=Le paiement n'a pas pu être traité. Veuillez réessayer. | ||
| button.cancel=Annuler |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| #include <iostream> | ||
| #include <string> | ||
| #include <vector> | ||
| #include <ctime> | ||
| #include <iomanip> // for number formatting | ||
|
|
||
| struct Order { | ||
| int id; | ||
| std::string customer; | ||
| int quantity; | ||
| std::string status; | ||
| double price; | ||
| }; | ||
|
|
||
| class OrderManager { | ||
| std::vector<Order> orders; | ||
| int nextId = 1; | ||
|
|
||
| public: | ||
| void createOrder(const std::string& customer, int qty, double price) { | ||
| Order o{nextId++, customer, qty, "NEW", price}; | ||
| orders.push_back(o); | ||
|
|
||
| // ❌ Hardcoded success message | ||
| std::cout << "Order created successfully for customer: " | ||
| << customer << " with quantity " << qty | ||
| << " and price " << price << std::endl; | ||
| } | ||
|
|
||
| void listOrders() { | ||
| std::cout << "------ Order List ------" << std::endl; // ❌ Hardcoded label | ||
|
|
||
| for (auto& o : orders) { | ||
| std::cout << "Order ID: " << o.id << ", " | ||
| << "Customer: " << o.customer << ", " | ||
| << "Qty: " << o.quantity << ", " | ||
| // ❌ Hardcoded status mapping | ||
| << "Status: " << (o.status == "NEW" ? "New Order" : o.status) << ", " | ||
| // ❌ Locale-unaware currency formatting | ||
| << "Price: $" << std::fixed << std::setprecision(2) << o.price | ||
| << std::endl; | ||
| } | ||
|
|
||
| std::cout << "------ End of Orders ------" << std::endl; // ❌ Hardcoded footer | ||
| } | ||
|
|
||
| void deleteOrder(int id) { | ||
| for (auto it = orders.begin(); it != orders.end(); ++it) { | ||
| if (it->id == id) { | ||
| orders.erase(it); | ||
| // ❌ Hardcoded delete confirmation | ||
| std::cout << "Order deleted successfully!" << std::endl; | ||
| return; | ||
| } | ||
| } | ||
| // ❌ Hardcoded error message | ||
| std::cout << "Error: Order not found." << std::endl; | ||
| } | ||
|
|
||
| void printReport() { | ||
| // ❌ Locale-unaware date formatting (fixed US-style format) | ||
| std::time_t now = std::time(nullptr); | ||
| char buffer[80]; | ||
| std::strftime(buffer, sizeof(buffer), "%m/%d/%Y %H:%M:%S", std::localtime(&now)); | ||
| std::cout << "Report generated at: " << buffer << std::endl; | ||
|
|
||
| // ❌ Hardcoded label + locale-unaware number formatting | ||
| double revenue = 0; | ||
| for (auto& o : orders) { | ||
| revenue += o.price * o.quantity; | ||
| } | ||
|
|
||
| std::cout << "Total Orders: " << orders.size() << std::endl; | ||
| std::cout << "Total Revenue: " << revenue << std::endl; // ❌ Missing locale formatting | ||
| } | ||
| }; | ||
|
|
||
| int main() { | ||
| OrderManager manager; | ||
|
|
||
| manager.createOrder("Alice", 3, 1234.56); | ||
| manager.createOrder("Bob", 5, 98765.43); | ||
|
|
||
| manager.listOrders(); | ||
|
|
||
| manager.deleteOrder(2); | ||
| manager.deleteOrder(10); // should print error | ||
|
|
||
| manager.printReport(); | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| import java.util.Locale; | ||
| import java.util.ResourceBundle; | ||
|
|
||
| public class OrderApp { | ||
| private static final ResourceBundle messages = ResourceBundle.getBundle("Messages", Locale.ENGLISH); | ||
|
|
||
| public static void main(String[] args) { | ||
| UILayer ui = new UILayer(messages); | ||
| ui.showWelcome(); | ||
|
|
||
| OrderService orderService = new OrderService(messages); | ||
| PaymentService paymentService = new PaymentService(messages); | ||
|
|
||
| // GOOD: Using localization | ||
| orderService.processOrder("Order123", 3); | ||
|
|
||
| // BAD: Hardcoded UI label | ||
| System.out.println("=== ORDER SUMMARY ==="); // ❌ should be localized | ||
|
|
||
| // GOOD: Localized | ||
| ui.showLabel("button.cancel"); | ||
|
|
||
| // Simulate payment success | ||
| paymentService.processPayment("Carlos", 150.0, true); | ||
|
|
||
| // Simulate payment failure | ||
| paymentService.processPayment("Marie", 99.9, false); | ||
|
|
||
| // BAD: Inline error | ||
| System.out.println("Unable to generate invoice. Try again later."); // ❌ | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| // OrderController.java (excerpt with intentional i18n gaps) | ||
|
|
||
| @PostMapping | ||
| public ResponseEntity<?> createOrder(@Valid @RequestBody Order order) { | ||
| order.setId(idGen.incrementAndGet()); | ||
| orders.add(order); | ||
|
|
||
| // ❌ Hardcoded success message (i18n gap) | ||
| Map<String, Object> response = new HashMap<>(); | ||
| response.put("message", "Order created successfully!"); | ||
| response.put("order", order); | ||
| return ResponseEntity.status(HttpStatus.CREATED).body(response); | ||
| } | ||
|
|
||
| @PutMapping("/{id}") | ||
| public ResponseEntity<?> updateOrder(@PathVariable Long id, @Valid @RequestBody Order order) { | ||
| Optional<Order> existing = orders.stream().filter(o -> o.getId().equals(id)).findFirst(); | ||
| if (existing.isPresent()) { | ||
| Order o = existing.get(); | ||
| o.setCustomerName(order.getCustomerName()); | ||
| o.setQuantity(order.getQuantity()); | ||
| o.setStatus(order.getStatus()); | ||
|
|
||
| // ❌ Hardcoded update message | ||
| return ResponseEntity.ok(Map.of("message", "Order updated successfully", "order", o)); | ||
| } | ||
|
|
||
| // ❌ Hardcoded error message | ||
| return ResponseEntity.status(HttpStatus.NOT_FOUND).body(Map.of("error", "Order not found")); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| // OrderList.js (excerpt with intentional i18n gaps) | ||
|
|
||
| import React, { useEffect, useState } from "react"; | ||
|
|
||
| export default function OrderList() { | ||
| const [orders, setOrders] = useState([]); | ||
|
|
||
| useEffect(() => { | ||
| fetch("http://localhost:8080/api/orders") | ||
| .then((res) => res.json()) | ||
| .then(setOrders); | ||
| }, []); | ||
|
|
||
| return ( | ||
| <div> | ||
| {/* ❌ Hardcoded title */} | ||
| <h1>Order Management</h1> | ||
|
|
||
| <button onClick={() => alert("Create Order Clicked!")}> | ||
| {/* ❌ Hardcoded label */} | ||
| Create Order | ||
| </button> | ||
|
|
||
| <table border="1"> | ||
| <thead> | ||
| <tr> | ||
| {/* ❌ Hardcoded column headers */} | ||
| <th>Customer Name</th> | ||
| <th>Quantity</th> | ||
| <th>Status</th> | ||
| </tr> | ||
| </thead> | ||
| <tbody> | ||
| {orders.map((o) => ( | ||
| <tr key={o.id}> | ||
| <td>{o.customerName}</td> | ||
| <td>{o.quantity}</td> | ||
| {/* ❌ Hardcoded status mapping */} | ||
| <td>{o.status === "NEW" ? "New Order" : o.status}</td> | ||
| </tr> | ||
| ))} | ||
| </tbody> | ||
| </table> | ||
| </div> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| import java.text.MessageFormat; | ||
| import java.util.ResourceBundle; | ||
|
|
||
| public class OrderService { | ||
| private final ResourceBundle messages; | ||
|
|
||
| public OrderService(ResourceBundle messages) { | ||
| this.messages = messages; | ||
| } | ||
|
|
||
| public void processOrder(String customer, int count) { | ||
| // BAD: Concatenated string | ||
| System.out.println("Processing order for " + customer + " with " + count + " items."); // ❌ | ||
|
|
||
| // GOOD: Localized | ||
| String msg = messages.getString("order.processing"); | ||
| System.out.println(MessageFormat.format(msg, customer, count)); | ||
|
|
||
| if (count > 2) { | ||
| String success = messages.getString("order.success"); | ||
| System.out.println(MessageFormat.format(success, customer)); | ||
| } else { | ||
| // BAD: Hardcoded success | ||
| System.out.println("Order placed successfully!"); // ❌ | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The message field contains trailing whitespace after "hardcoded strings." on line 31. This should be removed for consistency and cleanliness.