Language-Specific Risks in AI-Generated Code
Language-specific security risks in AI-generated code: Python (pickle, eval, subprocess), JavaScript (prototype pollution, eval), Rust (unsafe blocks), and Go (SQL injection in string formatting).
Loading...
Language-specific security risks in AI-generated code: Python (pickle, eval, subprocess), JavaScript (prototype pollution, eval), Rust (unsafe blocks), and Go (SQL injection in string formatting).
While the CWE-mapped vulnerability patterns from the previous page apply across languages, each programming language has unique features, idioms, and ecosystem characteristics that create language-specific risks in AI-generated code. This page covers the most significant risks in Python, JavaScript, Rust, and Go.
Python's flexibility and extensive standard library create multiple avenues for AI-generated vulnerabilities. The language's "batteries included" philosophy means there are often both secure and insecure ways to accomplish the same task, and models frequently choose the insecure option.
pickle is Python's native serialization format, and it is fundamentally insecure: deserializing a pickle object executes arbitrary code. AI models frequently suggest pickle for serialization tasks because it is the most common serialization mechanism in Python training data.
# AI-generated: arbitrary code execution via pickle
import pickle
def load_user_preferences(data):
return pickle.loads(data) # Executes arbitrary code in the data
# AI-generated: insecure file loading
def load_model(path):
with open(path, 'rb') as f:
return pickle.load(f) # Dangerous if path is user-controlled
# Secure alternatives
import json
def load_user_preferences(data):
return json.loads(data) # Cannot execute code
# For ML models, use safetensors or verify signatures
The pickle risk is amplified in machine learning contexts where models frequently suggest pickle or torch.load() (which uses pickle internally) for loading model weights. An attacker who can supply a malicious model file achieves code execution.
AI models frequently suggest eval() for tasks that involve dynamic computation, string-to-number conversion, or configuration parsing:
# AI-generated: code execution via eval
def calculate(expression):
return eval(expression) # Arbitrary code execution
def parse_config_value(value_str):
return eval(value_str) # Intended for "True"/"False", executes anything
# Secure alternatives
import ast
def calculate(expression):
return ast.literal_eval(expression) # Only evaluates literals
def parse_config_value(value_str):
return {'true': True, 'false': False}.get(value_str.lowerAI models frequently use shell=True in subprocess calls or use os.system() because these patterns are more common in training data:
# AI-generated: command injection via shell=True
def ping_host(hostname):
result = subprocess.run(
f"ping -c 4 {hostname}",
shell=True, # Enables command injection
capture_output=True,
text=True
)
return result.stdout
# Secure alternative
def ping_host(hostname):
result = subprocess.run(
["ping", "-c", "4", hostname], # No shell interpretation
# AI-generated: arbitrary code execution via YAML
import yaml
def load_config(path):
with open(path) as f:
return yaml.load(f) # Unsafe loader, can execute code
# Secure alternative
def load_config(path):
with open(path) as f:
return yaml.safe_load(f) # Only loads basic typesJavaScript's prototype-based inheritance, dynamic typing, and browser execution context create unique vulnerability patterns in AI-generated code.
AI models generate code that is vulnerable to prototype pollution — modifying Object.prototype through user-controlled input. This is especially common in object merging and configuration handling:
// AI-generated: prototype pollution via recursive merge
function deepMerge(target, source) {
for (const key in source) {
if (typeof source[key] === 'object' && source[key] !== null) {
if (!target[key]) target[key] = {};
deepMerge(target[key], source[key]);
} else {
target[key] =
// AI-generated: code execution via eval
function processTemplate(template, data) {
return eval('`' + template + '`'); // Template with code execution
}
// AI-generated: indirect eval via Function constructor
function createValidator(rule) {
return new Function('value', `return ${rule}`);
}
// Secure alternatives depend on the use case:
// - Template literals: use a templating library (Handlebars, EJS with escaping)
// - Validation: use a schema validation library (Joi, Zod)AI models frequently generate regular expressions that are vulnerable to catastrophic backtracking:
// AI-generated: ReDoS-vulnerable email validation
const emailRegex = /^([a-zA-Z0-9]+\.)*[a-zA-Z0-9]+@([a-zA-Z0-9]+\.)*[a-zA-Z]{2,}$/;
// Catastrophic backtracking on: "aaaaaaaaaaaaaaaaaa@" + "a".repeat(100)
// Secure alternative: use a dedicated validation library
const { z } = require('zod');
const emailSchema = z.string().email();AI models often suggest npm install of packages without version pinning or security consideration, and may suggest deprecated or unmaintained packages that have known vulnerabilities.
Rust's memory safety guarantees are a significant security advantage, but AI models can undermine these guarantees by suggesting unsafe blocks, and Rust's complexity means models sometimes generate code that compiles but has logical safety issues.
AI models trained on systems programming code may suggest unsafe blocks for operations that can be accomplished safely:
// AI-generated: unnecessary unsafe for string conversion
fn to_string(bytes: &[u8]) -> String {
unsafe { String::from_utf8_unchecked(bytes.to_vec()) }
// Undefined behavior if bytes is not valid UTF-8
}
// Secure alternative
fn to_string(bytes: &[u8]) -> Result<String, std::string::FromUtf8Error> {
String::from_utf8(bytes.to_vec())
}// AI-generated: unsafe pointer arithmetic
fn get_element(data: &[u32], index: usize) -> u32 {
unsafe { *data.as_ptr().add(index) }
// No bounds checking — buffer overflow
}
// Secure alternative
fn get_element(data: &[u32], index: usize) -> Option<u32> {
data.get(index).copied()
}Models may suggest raw pointer operations for performance optimization that are unnecessary and dangerous:
// AI-generated: use-after-free potential
fn process_data(data: Vec<u8>) -> *const u8 {
let ptr = data.as_ptr();
// data is dropped here, ptr is dangling
ptr
}When generating code that interacts with C libraries through FFI, models may not properly handle the safety boundaries:
// AI-generated: missing null check on FFI return
extern "C" {
fn get_user_name() -> *const c_char;
}
fn user_name() -> String {
unsafe {
CStr::from_ptr(get_user_name()) // Crashes if null is returned
.to_string_lossy()
.into_owned()
}
}Go's simplicity and explicit error handling create specific patterns where AI-generated code introduces vulnerabilities.
Go's fmt.Sprintf is frequently used by AI models to construct SQL queries:
// AI-generated: SQL injection
func GetUser(db *sql.DB, username string) (*User, error) {
query := fmt.Sprintf("SELECT * FROM users WHERE username = '%s'", username)
row := db.QueryRow(query)
// ...
}
// Secure alternative
func GetUser(db *sql.DB, username string) (*User, error) {
row :=
Go's explicit error handling requires checking every error return. AI models frequently generate code that silently discards errors:
// AI-generated: ignored errors
func writeConfig(path string, data []byte) {
f, _ := os.Create(path) // Error ignored
f.Write(data) // Error ignored, f may be nil
f.Close() // Error ignored
}
// Secure alternative
func writeConfig(path string, data []byte) error {
f, err := os.Create(path)
AI models often generate Go HTTP servers without proper timeout configuration, leading to denial-of-service vulnerabilities:
// AI-generated: no timeouts, vulnerable to slowloris
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil) // No timeouts configured
}
// Secure alternative
func main() {
srv := &http.Server{
Addr: ":8080",
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
IdleTimeout: 60 * time
When reviewing AI-generated code in any language, check for:
| Check | Python | JavaScript | Rust | Go |
|---|---|---|---|---|
| Deserialization | pickle, yaml.load | JSON.parse (usually safe) | serde (usually safe) | encoding/gob |
| Code execution | eval, exec | eval, Function | unsafe blocks | exec.Command |
| Input validation | Missing sanitization | Prototype pollution | Type system helps | Missing validation |
| Error handling | Bare except | Missing catch | Unwrap panics | Ignored errors |
| Crypto | hashlib.md5 | crypto (subtle API) | External crates | crypto/md5 |