Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Injection Prevention

ASecurity

Injection prevention patterns for SQL, XSS, command injection, path traversal, LDAP, and template injection across major languages, including edge cases such as ORDER BY, IN clauses, and second-order injection. Use when writing or fixing code that builds queries, commands, paths, or HTML from input.

4 stars
0 votes
0 copies
1 views
Added 10/1/2026
developmentjavascriptpythonrustgojavashellsqlreactvueangular

Works with

cursorcliapi

Security Analysis

A100/100

Scanned 10/1/2026

$npx -y skills add HermeticOrmus/LibreSecOps-Claude-Code --skill injection-prevention --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Injection Prevention?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Injection Prevention
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/hermeticormus-injection-prevention/badge)](https://www.skillsdirectory.com/skills/hermeticormus-injection-prevention)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: "injection-prevention"
description: "Injection prevention patterns for SQL, XSS, command injection, path traversal, LDAP, and template injection across major languages, including edge cases such as ORDER BY, IN clauses, and second-order injection. Use when writing or fixing code that builds queries, commands, paths, or HTML from input."
---

# Injection Prevention

> Comprehensive injection prevention patterns for SQL, XSS, command injection, path traversal, LDAP, and template injection across all major languages and frameworks.

## Knowledge Base

### The Fundamental Principle

Injection occurs when untrusted data is interpreted as code or structure by a downstream processor. The universal prevention is to ensure the processor can distinguish data from code. This is achieved through:

1. **Parameterization** -- Sending data through a separate channel from code (prepared statements, argument arrays)
2. **Context-aware encoding** -- Transforming data so it is inert in the target context (HTML encoding, URL encoding)
3. **Allowlist validation** -- Accepting only data that matches a known-safe pattern (enum values, regex matching)

Denylist filtering (blocking known-bad characters) is almost always insufficient because there are too many encoding variations and bypass techniques.

### SQL Injection

**Root cause**: User input concatenated into SQL query strings.

**Prevention by language**:

```python
# VULNERABLE
cursor.execute(f"SELECT * FROM users WHERE name = '{name}'")

# SECURE - Parameterized query
cursor.execute("SELECT * FROM users WHERE name = %s", (name,))

# SECURE - Django ORM (parameterized by default)
User.objects.filter(name=name)

# VULNERABLE - Django raw with string formatting
User.objects.raw(f"SELECT * FROM users WHERE name = '{name}'")

# SECURE - Django raw with params
User.objects.raw("SELECT * FROM users WHERE name = %s", [name])
```

```javascript
// VULNERABLE
db.query(`SELECT * FROM users WHERE name = '${name}'`);

// SECURE - Parameterized (pg library)
db.query('SELECT * FROM users WHERE name = $1', [name]);

// SECURE - Prisma ORM (parameterized by default)
prisma.user.findMany({ where: { name } });

// VULNERABLE - Sequelize literal
sequelize.query(`SELECT * FROM users WHERE name = '${name}'`);

// SECURE - Sequelize parameterized
sequelize.query('SELECT * FROM users WHERE name = :name', {
  replacements: { name }
});
```

```java
// VULNERABLE
Statement stmt = conn.createStatement();
stmt.execute("SELECT * FROM users WHERE name = '" + name + "'");

// SECURE - PreparedStatement
PreparedStatement ps = conn.prepareStatement(
    "SELECT * FROM users WHERE name = ?"
);
ps.setString(1, name);
ResultSet rs = ps.executeQuery();

// SECURE - JPA/Hibernate named parameters
Query q = em.createQuery(
    "SELECT u FROM User u WHERE u.name = :name"
);
q.setParameter("name", name);
```

```go
// VULNERABLE
db.Query("SELECT * FROM users WHERE name = '" + name + "'")

// SECURE - Parameterized
db.Query("SELECT * FROM users WHERE name = $1", name)

// SECURE - GORM (parameterized by default)
db.Where("name = ?", name).Find(&users)
```

**Tricky cases**:
- **ORDER BY**: Cannot be parameterized in most databases. Use allowlist validation: `if column not in ALLOWED_COLUMNS: raise Error`
- **LIKE clauses**: Parameterize the value but escape `%` and `_` within user input: `WHERE name LIKE '%' || $1 || '%'` with `%` and `_` escaped in the parameter
- **IN clauses**: Generate the right number of placeholders: `WHERE id IN ($1, $2, $3)` with one param per value
- **Table/column names**: Cannot be parameterized. Strict allowlist validation required.
- **Second-order injection**: Data stored safely in the database but later retrieved and used in an unsafe query. The fix is to parameterize ALL queries, not just those with direct user input.

### Cross-Site Scripting (XSS)

**Root cause**: Untrusted data rendered in HTML without proper context-aware encoding.

**Context-specific encoding**:

| Context | Encoding | Example |
|---------|----------|---------|
| HTML body | HTML entity encoding | `<` -> `&lt;` |
| HTML attribute | HTML attribute encoding | `"` -> `&quot;` |
| JavaScript | JavaScript encoding | `'` -> `\x27` |
| URL parameter | URL encoding | ` ` -> `%20` |
| CSS | CSS encoding | `(` -> `\28` |

**Framework auto-escaping** (know what your framework does and does not escape):

| Framework | Auto-escapes | Bypass syntax (dangerous) |
|-----------|-------------|---------------------------|
| React JSX | Yes (HTML context) | `dangerouslySetInnerHTML` |
| Angular | Yes (HTML context) | `bypassSecurityTrustHtml()` |
| Vue | Yes (`{{ }}`) | `v-html` directive |
| Django templates | Yes (`{{ }}`) | `|safe` filter, `{% autoescape off %}` |
| Jinja2 | Yes (if configured) | `|safe` filter, `Markup()` |
| Rails ERB | No (`<%= %>`) / Yes (`<%== %>`) | `raw()`, `html_safe` |
| Go html/template | Yes | Using `text/template` instead |

**DOM-based XSS**: The server never sees the payload. It exists entirely in client-side JavaScript.

```javascript
// VULNERABLE - DOM XSS
document.getElementById('output').innerHTML = location.hash.substring(1);

// SECURE - Use textContent for text
document.getElementById('output').textContent = location.hash.substring(1);

// SECURE - Use DOMPurify for HTML that must be rendered
import DOMPurify from 'dompurify';
document.getElementById('output').innerHTML = DOMPurify.sanitize(userHtml);
```

**Content Security Policy** (defense-in-depth):
```
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none';
```

### Command Injection

**Root cause**: User input passed to shell interpreters.

**Prevention**: Use argument arrays, never shell strings.

```python
# VULNERABLE
os.system(f"convert {filename} output.png")
subprocess.call(f"convert {filename} output.png", shell=True)

# SECURE - Argument array, no shell
subprocess.run(["convert", filename, "output.png"], shell=False)
```

```javascript
// VULNERABLE
exec(`convert ${filename} output.png`);

// SECURE - execFile with argument array
execFile("convert", [filename, "output.png"]);
```

```go
// VULNERABLE
exec.Command("sh", "-c", "convert " + filename + " output.png")

// SECURE - Direct command with argument array
exec.Command("convert", filename, "output.png")
```

**Additional safeguards**: Validate filename against allowlist pattern (`[a-zA-Z0-9._-]+`), use full path for command (`/usr/bin/convert`), drop privileges if possible.

### Path Traversal

**Root cause**: User input used to construct file paths without canonicalization and boundary checking.

```python
# VULNERABLE
filepath = os.path.join(UPLOAD_DIR, user_filename)
with open(filepath) as f: return f.read()

# SECURE - Canonical path validation
filepath = os.path.join(UPLOAD_DIR, user_filename)
canonical = os.path.realpath(filepath)
if not canonical.startswith(os.path.realpath(UPLOAD_DIR)):
    raise SecurityError("Path traversal attempt")
with open(canonical) as f: return f.read()
```

```go
// SECURE - filepath.Clean + prefix check
cleaned := filepath.Clean(filepath.Join(uploadDir, userFilename))
if !strings.HasPrefix(cleaned, filepath.Clean(uploadDir)) {
    return errors.New("path traversal attempt")
}
```

**Bypass awareness**: `../`, `..%2f`, `..%252f` (double encoding), `....//` (filter bypass), null bytes (`%00` in older systems), symlink following.

### Template Injection (SSTI)

**Root cause**: User input inserted into template code rather than template data.

```python
# VULNERABLE - User input in template string
template = Template(f"Hello {user_input}")
template.render()

# SECURE - User input as template variable
template = Template("Hello {{ name }}")
template.render(name=user_input)
```

If users must provide template-like input, use a sandboxed template engine (Jinja2 SandboxedEnvironment) and validate against dangerous constructs.

## Patterns

### Pattern: Input Validation Layer
Create a validation layer at the application boundary that rejects invalid input before it reaches business logic. Use schema validation libraries (Joi, Zod, Pydantic, marshmallow) with strict type definitions.

### Pattern: Output Encoding Layer
Centralize output encoding in template helpers or middleware rather than relying on individual developers to encode at each output point. Choose frameworks with auto-escaping enabled by default.

### Pattern: Parameterized Everywhere
Use parameterized interfaces for all structured data contexts (SQL, LDAP, XPath), not just the ones you think receive user input. Data flows change; parameterized queries are safe regardless of data source.

## Anti-Patterns

- **Denylist filtering**: Blocking `<script>` does not prevent `<img onerror=>`, `<svg onload=>`, or hundreds of other XSS vectors
- **Escaping for SQL instead of parameterizing**: Manual escaping is error-prone and database-specific. Parameterized queries are universally correct
- **Client-side-only validation**: Any validation in JavaScript can be bypassed by sending requests directly. Server-side validation is mandatory
- **WAF as the sole defense**: WAFs are bypassable. They are a useful layer but not a substitute for secure code
- **Double encoding to "fix" display issues**: If output encoding breaks your display, you are encoding at the wrong layer, not "too much"
- **Stripping instead of rejecting**: Silently removing dangerous characters changes user input in unexpected ways and may be bypassed. Reject invalid input with a clear error

## References

- OWASP Injection Prevention Cheat Sheet -- https://cheatsheetseries.owasp.org/cheatsheets/Injection_Prevention_Cheat_Sheet.html
- OWASP XSS Prevention Cheat Sheet -- https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Scripting_Prevention_Cheat_Sheet.html
- OWASP SQL Injection Prevention -- https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html
- OWASP OS Command Injection Defense -- https://cheatsheetseries.owasp.org/cheatsheets/OS_Command_Injection_Defense_Cheat_Sheet.html
- OWASP Input Validation Cheat Sheet -- https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.html
- CWE-89: SQL Injection -- https://cwe.mitre.org/data/definitions/89.html
- CWE-79: Cross-site Scripting -- https://cwe.mitre.org/data/definitions/79.html
- CWE-78: OS Command Injection -- https://cwe.mitre.org/data/definitions/78.html
- CWE-22: Path Traversal -- https://cwe.mitre.org/data/definitions/22.html

Attribution

HermeticOrmusHermeticOrmus
View sourceSee grades on GitHubMore from HermeticOrmus →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Clean Code

Pragmatic coding standards - concise, direct, no over-engineering, no unnecessary comments

304955 votes

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

286712 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2222 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Writing Plans

Use when you have a spec or requirements for a multi-step task, before touching code

2927051 votes
View all in development →