<!-- AUTO-GENERATED by export-plugins.py — DO NOT EDIT -->
npx claudepluginhub frank-luongt/faos-skills-marketplace --plugin faos-security-engineerThis skill uses the workspace's default tool permissions.
Implements structured self-debugging workflow for AI agent failures: capture errors, diagnose patterns like loops or context overflow, apply contained recoveries, and generate introspection reports.
Designs and optimizes AI agent action spaces, tool definitions, observation formats, error recovery, and context for higher task completion rates.
Compares coding agents like Claude Code and Aider on custom YAML-defined codebase tasks using git worktrees, measuring pass rate, cost, time, and consistency.
The CWE/SANS Top 25 is a curated list of the most prevalent and dangerous software weaknesses maintained by MITRE. Unlike OWASP (which focuses on web/API risks), CWE classifies root-cause weaknesses in software -- memory corruption, injection flaws, improper validation -- that lead to exploitable vulnerabilities. Each weakness has a unique CWE identifier used across CVE databases, SAST tools, and compliance frameworks.
This skill organizes the Top 25 by category, provides language-specific applicability, and maps each weakness to concrete prevention patterns and SAST rules. It is designed for developers performing code reviews, security engineers configuring static analysis, and architects establishing secure coding standards.
Determine which CWE category the suspected issue belongs to. Use the categories below to narrow down from broad symptoms (e.g., "crash on malformed input") to a specific CWE ID.
For known CVEs related to the weakness, look up:
# Query NIST NVD for a specific CVE
curl -s "https://services.nvd.nist.gov/rest/json/cves/2.0?cveId=CVE-2024-XXXXX" | \
jq '.vulnerabilities[0].cve.metrics'
Each CWE has a specific mitigation pattern. Apply the pattern from the relevant category below. Mitigations should be implemented at the earliest possible phase (design > implementation > testing).
Run static analysis to confirm the fix and prevent regression:
# Semgrep scan for Python security issues
semgrep scan --config p/python-security --config p/owasp-top-ten \
--severity ERROR --error ./src/
# Bandit scan for Python-specific weaknesses
bandit -r ./src/ -ll -ii --format json -o bandit-report.json
# CodeQL analysis (GitHub Actions)
# Configured in .github/workflows/codeql.yml
Write tests that specifically exercise the weakness vector to prevent reintroduction:
# Example: regression test for SQL injection (CWE-89)
import pytest
class TestSQLInjectionPrevention:
"""Regression tests ensuring parameterized queries are used."""
@pytest.mark.parametrize("malicious_input", [
"'; DROP TABLE users; --",
"1 OR 1=1",
"1 UNION SELECT * FROM credentials",
])
async def test_user_lookup_rejects_injection(self, client, malicious_input):
response = await client.get(f"/api/v1/users?search={malicious_input}")
assert response.status_code in (200, 400) # Must not cause 500
# Verify no data leak from other tables
data = response.json()
assert "credentials" not in str(data).lower()
These weaknesses affect languages without automatic memory management (C, C++, Rust unsafe blocks). They are the leading cause of critical remote code execution (RCE) vulnerabilities.
| CWE | Name | CVSS Range | Languages |
|---|---|---|---|
| CWE-787 | Out-of-Bounds Write | 8.0-10.0 | C, C++ |
| CWE-125 | Out-of-Bounds Read | 5.0-8.0 | C, C++ |
| CWE-416 | Use After Free | 8.0-10.0 | C, C++ |
| CWE-476 | NULL Pointer Dereference | 4.0-7.0 | C, C++, Java |
| CWE-190 | Integer Overflow | 5.0-9.0 | C, C++, Java |
Prevention Pattern: Use memory-safe languages (Python, Rust, Go) where possible. For C/C++, enable compiler sanitizers (-fsanitize=address,undefined), use smart pointers, and enforce bounds checking.
Injection weaknesses occur when untrusted data is sent to an interpreter as part of a command or query. They affect all languages that interface with databases, shells, or rendering engines.
| CWE | Name | CVSS Range | Languages |
|---|---|---|---|
| CWE-89 | SQL Injection | 7.0-10.0 | All (DB-connected) |
| CWE-79 | Cross-Site Scripting (XSS) | 4.0-8.0 | JavaScript, HTML |
| CWE-78 | OS Command Injection | 8.0-10.0 | All |
| CWE-94 | Code Injection | 8.0-10.0 | Python, PHP, JS |
| CWE-77 | Command Injection | 8.0-10.0 | All |
Prevention Pattern: Use parameterized queries (SQL), context-aware output encoding (XSS), and avoid shell=True in subprocess calls. Never construct commands by string concatenation with user input.
| CWE | Name | CVSS Range | Languages |
|---|---|---|---|
| CWE-287 | Improper Authentication | 7.0-10.0 | All |
| CWE-798 | Hard-Coded Credentials | 7.0-9.0 | All |
| CWE-306 | Missing Authentication for Critical Function | 7.0-10.0 | All |
| CWE-522 | Insufficiently Protected Credentials | 5.0-8.0 | All |
Prevention Pattern: Use established authentication frameworks, never hard-code secrets, enforce MFA on sensitive operations, and store credentials in secret managers (not config files or environment variables in source).
| CWE | Name | CVSS Range | Languages |
|---|---|---|---|
| CWE-862 | Missing Authorization | 7.0-9.0 | All |
| CWE-863 | Incorrect Authorization | 6.0-9.0 | All |
| CWE-269 | Improper Privilege Management | 7.0-9.0 | All |
Prevention Pattern: Implement default-deny authorization, check ownership on every resource access (see @owasp-api-top10 API1), enforce least-privilege, and use framework-level middleware rather than per-handler checks.
| CWE | Name | CVSS Range | Languages |
|---|---|---|---|
| CWE-327 | Broken or Risky Crypto Algorithm | 5.0-8.0 | All |
| CWE-330 | Insufficient Randomness | 4.0-7.0 | All |
| CWE-916 | Weak Password Hashing | 5.0-8.0 | All |
Prevention Pattern: Use modern algorithms (AES-256-GCM, SHA-256+, Ed25519), OS-provided CSPRNG (secrets module in Python, not random), and bcrypt/argon2 for password hashing. Never implement custom cryptography.
| CWE | Name | CVSS Range | Languages |
|---|---|---|---|
| CWE-20 | Improper Input Validation | 4.0-9.0 | All |
| CWE-22 | Path Traversal | 5.0-9.0 | All |
| CWE-352 | Cross-Site Request Forgery (CSRF) | 4.0-8.0 | Web frameworks |
| CWE-434 | Unrestricted File Upload | 7.0-10.0 | All (file handling) |
| CWE-611 | XXE (XML External Entity) | 5.0-9.0 | Java, Python, PHP |
Prevention Pattern: Validate all input against strict schemas (type, length, format, range). Use allow-lists over deny-lists. Canonicalize file paths before access. Disable XML external entity processing by default.
from sqlalchemy import select, text
from sqlalchemy.ext.asyncio import AsyncSession
# BAD: String concatenation -- vulnerable to CWE-89
async def search_users_insecure(db: AsyncSession, search_term: str):
query = text(f"SELECT * FROM users WHERE name LIKE '%{search_term}%'")
result = await db.execute(query)
return result.all()
# GOOD: Parameterized query -- immune to CWE-89
async def search_users_secure(db: AsyncSession, search_term: str):
query = text("SELECT * FROM users WHERE name LIKE :search")
result = await db.execute(query, {"search": f"%{search_term}%"})
return result.all()
# BEST: Use SQLAlchemy ORM -- parameterization is automatic
async def search_users_orm(db: AsyncSession, search_term: str):
stmt = select(User).where(User.name.ilike(f"%{search_term}%"))
result = await db.execute(stmt)
return result.scalars().all()
import os
from pathlib import Path
from fastapi import APIRouter, HTTPException, status
router = APIRouter()
UPLOAD_DIR = Path("/app/uploads")
# BAD: No path validation -- vulnerable to CWE-22
@router.get("/files/{filename}")
async def get_file_insecure(filename: str):
file_path = UPLOAD_DIR / filename # filename could be "../../etc/passwd"
return file_path.read_text()
# GOOD: Path canonicalization and containment check
@router.get("/files/{filename}")
async def get_file_secure(filename: str):
# Reject obvious traversal attempts
if ".." in filename or filename.startswith("/"):
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Invalid filename",
)
# Resolve to absolute path and verify containment
file_path = (UPLOAD_DIR / filename).resolve()
if not file_path.is_relative_to(UPLOAD_DIR.resolve()):
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Access denied",
)
if not file_path.is_file():
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
return file_path.read_text()
# .semgrep/rules/cwe-79-xss.yaml
rules:
- id: cwe-79-jinja2-autoescape-disabled
patterns:
- pattern: jinja2.Environment(..., autoescape=False, ...)
message: >
Jinja2 autoescape is disabled (CWE-79). This allows cross-site scripting
when rendering user-controlled data. Set autoescape=True or use
select_autoescape().
severity: ERROR
metadata:
cwe:
- "CWE-79: Improper Neutralization of Input During Web Page Generation"
confidence: HIGH
category: security
languages: [python]
- id: cwe-79-markupsafe-bypass
patterns:
- pattern: markupsafe.Markup($USER_INPUT)
message: >
Wrapping user input in Markup() bypasses HTML escaping (CWE-79).
Only use Markup() for trusted, pre-sanitized content.
severity: WARNING
metadata:
cwe:
- "CWE-79: Improper Neutralization of Input During Web Page Generation"
confidence: MEDIUM
category: security
languages: [python]
- id: cwe-79-fastapi-html-response
patterns:
- pattern: |
from fastapi.responses import HTMLResponse
...
HTMLResponse(content=<... $USER_INPUT ...>)
message: >
User input rendered directly in HTMLResponse without escaping (CWE-79).
Use a template engine with autoescape or html.escape().
severity: ERROR
metadata:
cwe:
- "CWE-79: Improper Neutralization of Input During Web Page Generation"
confidence: MEDIUM
category: security
languages: [python]
# Run the custom rule alongside built-in rules
semgrep scan --config .semgrep/rules/ --config p/python-security \
--severity ERROR --error ./src/
Path.resolve() and verify containment before accesssecrets module (not random) for any security-sensitive random valuessubprocess.run(..., shell=True) with user-controllable argumentsrandom module for tokens, passwords, or cryptographic keys-fsanitize=address,undefined in CIshell=True with user input)eval(), exec(), or dynamic code execution with untrusted inputsecrets module used for all security-sensitive random generation