From security
Provides fix patterns for SQL, command, and XSS injection vulnerabilities with vulnerable/secure code examples in Python (SQLAlchemy/psycopg2), JavaScript/TypeScript (Node.js/Prisma/Knex), and Java (JDBC).
How this skill is triggered — by the user, by Claude, or both
Slash command
/security:remediation-injectionThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Actionable fix patterns for injection-based security vulnerabilities.
Actionable fix patterns for injection-based security vulnerabilities.
User input directly concatenated into SQL queries allows attackers to manipulate database queries.
Don't:
# VULNERABLE: String concatenation
def get_user_bad(user_id):
query = f"SELECT * FROM users WHERE id = '{user_id}'"
cursor.execute(query)
return cursor.fetchone()
# VULNERABLE: Format strings
query = "SELECT * FROM users WHERE name = '%s'" % username
Do:
# SECURE: Parameterized queries with psycopg2
def get_user_safe(user_id):
query = "SELECT * FROM users WHERE id = %s"
cursor.execute(query, (user_id,))
return cursor.fetchone()
# SECURE: SQLAlchemy ORM
def get_user_orm(user_id):
return db.session.query(User).filter(User.id == user_id).first()
# SECURE: SQLAlchemy with text() and bindparams
from sqlalchemy import text
query = text("SELECT * FROM users WHERE id = :user_id")
result = db.session.execute(query, {"user_id": user_id})
Don't:
// VULNERABLE: String concatenation
const query = `SELECT * FROM users WHERE id = '${userId}'`;
db.query(query);
// VULNERABLE: Template literals
const sql = `SELECT * FROM products WHERE name LIKE '%${searchTerm}%'`;
Do:
// SECURE: Parameterized queries (mysql2)
const query = 'SELECT * FROM users WHERE id = ?';
db.query(query, [userId]);
// SECURE: Parameterized with named placeholders (pg)
const query = 'SELECT * FROM users WHERE id = $1';
await client.query(query, [userId]);
// SECURE: Prisma ORM
const user = await prisma.user.findUnique({
where: { id: userId }
});
// SECURE: Knex.js query builder
const user = await knex('users').where('id', userId).first();
Don't:
// VULNERABLE: String concatenation
String query = "SELECT * FROM users WHERE id = '" + userId + "'";
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query);
Do:
// SECURE: PreparedStatement
String query = "SELECT * FROM users WHERE id = ?";
PreparedStatement pstmt = conn.prepareStatement(query);
pstmt.setString(1, userId);
ResultSet rs = pstmt.executeQuery();
// SECURE: JPA/Hibernate with named parameters
@Query("SELECT u FROM User u WHERE u.id = :userId")
User findByUserId(@Param("userId") String userId);
Don't:
// VULNERABLE: fmt.Sprintf in queries
query := fmt.Sprintf("SELECT * FROM users WHERE id = '%s'", userID)
rows, err := db.Query(query)
Do:
// SECURE: Parameterized queries
query := "SELECT * FROM users WHERE id = $1"
rows, err := db.Query(query, userID)
// SECURE: With sqlx
var user User
err := db.Get(&user, "SELECT * FROM users WHERE id = $1", userID)
ASVS: V1.2.1, V1.2.2 References: OWASP SQL Injection Prevention
User input passed to shell commands allows attackers to execute arbitrary system commands.
Don't:
# VULNERABLE: shell=True with user input
import subprocess
subprocess.run(f"grep {pattern} {filename}", shell=True)
# VULNERABLE: os.system
import os
os.system(f"convert {input_file} {output_file}")
Do:
# SECURE: subprocess with argument list (no shell)
import subprocess
import shlex
result = subprocess.run(
['grep', pattern, filename],
capture_output=True,
text=True
)
# SECURE: If shell is required, use shlex.quote
if shell_required:
safe_filename = shlex.quote(filename)
subprocess.run(f"process {safe_filename}", shell=True)
# SECURE: Use libraries instead of shell commands
from PIL import Image
img = Image.open(input_file)
img.save(output_file)
Don't:
// VULNERABLE: exec with user input
const { exec } = require('child_process');
exec(`grep ${pattern} ${filename}`);
// VULNERABLE: String interpolation in shell command
exec(`convert ${inputFile} ${outputFile}`);
Do:
// SECURE: execFile with argument array
const { execFile } = require('child_process');
execFile('grep', [pattern, filename], (error, stdout) => {
console.log(stdout);
});
// SECURE: spawn with arguments
const { spawn } = require('child_process');
const grep = spawn('grep', [pattern, filename]);
// SECURE: Use libraries instead of shell commands
const sharp = require('sharp');
await sharp(inputFile).toFile(outputFile);
Don't:
// VULNERABLE: Runtime.exec with concatenation
String cmd = "grep " + pattern + " " + filename;
Runtime.getRuntime().exec(cmd);
Do:
// SECURE: ProcessBuilder with argument list
ProcessBuilder pb = new ProcessBuilder("grep", pattern, filename);
pb.redirectErrorStream(true);
Process process = pb.start();
ASVS: V1.2.3 References: OWASP OS Command Injection
User input rendered in HTML without proper encoding allows script injection.
Don't:
// VULNERABLE: innerHTML with user input
element.innerHTML = userInput;
// VULNERABLE: document.write
document.write(userData);
// VULNERABLE: jQuery html()
$('#content').html(userInput);
Do:
// SECURE: textContent for plain text
element.textContent = userInput;
// SECURE: DOMPurify for HTML content
import DOMPurify from 'dompurify';
element.innerHTML = DOMPurify.sanitize(userHtml);
// SECURE: Create elements programmatically
const link = document.createElement('a');
link.href = sanitizeUrl(userUrl);
link.textContent = userText;
parent.appendChild(link);
// SECURE: jQuery text()
$('#content').text(userInput);
Don't:
// VULNERABLE: dangerouslySetInnerHTML without sanitization
function Comment({ content }) {
return <div dangerouslySetInnerHTML={{ __html: content }} />;
}
// VULNERABLE: href with user input (javascript: URLs)
<a href={userUrl}>Click here</a>
Do:
// SECURE: React auto-escapes by default
function Comment({ content }) {
return <div>{content}</div>;
}
// SECURE: Sanitize if HTML is required
import DOMPurify from 'dompurify';
function RichContent({ html }) {
const clean = DOMPurify.sanitize(html);
return <div dangerouslySetInnerHTML={{ __html: clean }} />;
}
// SECURE: Validate URLs
function SafeLink({ url, text }) {
const isValid = /^https?:\/\//.test(url);
if (!isValid) return <span>{text}</span>;
return <a href={url}>{text}</a>;
}
Don't:
# VULNERABLE: Marking as safe without sanitization
from markupsafe import Markup
return Markup(f"<div>{user_input}</div>")
# VULNERABLE: Disabling autoescaping
{% autoescape false %}
{{ user_content }}
{% endautoescape %}
Do:
# SECURE: Let Jinja2 auto-escape (default)
return render_template('page.html', content=user_input)
# Template: auto-escaped by default
<div>{{ content }}</div>
# SECURE: Use bleach for allowing specific HTML
import bleach
allowed_tags = ['b', 'i', 'u', 'a']
allowed_attrs = {'a': ['href']}
clean = bleach.clean(user_html, tags=allowed_tags, attributes=allowed_attrs)
ASVS: V3.3.1, V1.3.1 References: OWASP XSS Prevention
| Vulnerability | Fix Pattern | Key Libraries |
|---|---|---|
| SQL Injection | Parameterized queries | ORM, prepared statements |
| Command Injection | Argument arrays, no shell | subprocess, execFile |
| XSS | Auto-escaping, sanitization | DOMPurify, bleach |
remediation-crypto - Cryptography fixesremediation-auth - Authentication/authorization fixesremediation-config - Configuration fixesvulnerability-patterns - Detection patternsnpx claudepluginhub zate/cc-plugins --plugin securityTeaches the universal injection pattern across SQL, XSS, command injection, and other interpreters. Useful for code review, secure design, and developer training.
Detects SQL, command, and template injection caused by user input reaching an interpreter without parameterization. Checks concatenated query strings, shell commands, eval/exec calls, and unsafe template usage.
Detects SQL injection vulnerabilities by tracing user inputs through code to database queries, flagging unsafe patterns like concatenation and unparameterized ORMs. Scans frameworks including Django, Rails, Express, Go.