<!-- 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 OWASP Top 10 (2021 edition) is the most widely referenced standard for web application security awareness. It represents a broad consensus on the most critical security risks facing web applications, ranked by prevalence, exploitability, and impact. Security agents use this skill to identify, classify, and remediate web application vulnerabilities across the full development lifecycle.
Each category aggregates related CWEs (Common Weakness Enumerations) and provides actionable prevention guidance. The 2021 edition introduced three new categories (Insecure Design, Software and Data Integrity Failures, SSRF) and restructured several existing ones from the 2017 edition.
Map the observed vulnerability or concern to one of the 10 categories:
| Rank | Category | Key CWEs |
|---|---|---|
| A01 | Broken Access Control | CWE-200, CWE-284, CWE-285, CWE-352 |
| A02 | Cryptographic Failures | CWE-259, CWE-327, CWE-328, CWE-331 |
| A03 | Injection | CWE-79, CWE-89, CWE-78, CWE-94 |
| A04 | Insecure Design | CWE-209, CWE-256, CWE-501, CWE-522 |
| A05 | Security Misconfiguration | CWE-16, CWE-611, CWE-1004 |
| A06 | Vulnerable and Outdated Components | CWE-1104 |
| A07 | Identification and Authentication Failures | CWE-287, CWE-297, CWE-384 |
| A08 | Software and Data Integrity Failures | CWE-502, CWE-829 |
| A09 | Security Logging and Monitoring Failures | CWE-117, CWE-223, CWE-778 |
| A10 | Server-Side Request Forgery (SSRF) | CWE-918 |
For the identified category, determine:
Each category has specific prevention strategies. Apply the controls relevant to your technology stack:
A01 - Broken Access Control:
A02 - Cryptographic Failures:
A03 - Injection:
A04 - Insecure Design:
A05 - Security Misconfiguration:
A06 - Vulnerable and Outdated Components:
A07 - Identification and Authentication Failures:
A08 - Software and Data Integrity Failures:
A09 - Security Logging and Monitoring Failures:
A10 - Server-Side Request Forgery (SSRF):
Use appropriate security testing tools to validate:
After applying fixes, confirm the vulnerability is resolved:
Vulnerable code (Python/FastAPI):
# VULNERABLE - string concatenation in SQL query
@router.get("/users")
async def get_users(search: str, db: AsyncSession = Depends(get_db)):
query = f"SELECT * FROM users WHERE name LIKE '%{search}%'"
result = await db.execute(text(query))
return result.fetchall()
Fixed code using parameterized queries:
# SECURE - parameterized query prevents SQL injection
@router.get("/users")
async def get_users(search: str, db: AsyncSession = Depends(get_db)):
query = text("SELECT * FROM users WHERE name LIKE :search")
result = await db.execute(query, {"search": f"%{search}%"})
return result.fetchall()
Even better, use SQLAlchemy ORM:
# SECURE - ORM with safe query building
@router.get("/users")
async def get_users(search: str, db: AsyncSession = Depends(get_db)):
stmt = select(User).where(User.name.ilike(f"%{search}%")).limit(100)
result = await db.execute(stmt)
return result.scalars().all()
Vulnerable code (no ownership check):
# VULNERABLE - any authenticated user can access any tenant's data
@router.get("/tenants/{tenant_id}/reports/{report_id}")
async def get_report(tenant_id: str, report_id: str, db: AsyncSession = Depends(get_db)):
report = await db.get(Report, report_id)
if not report:
raise HTTPException(status_code=404)
return report
Fixed code with RBAC and tenant isolation:
# SECURE - enforces tenant isolation and role-based access
@router.get("/tenants/{tenant_id}/reports/{report_id}")
async def get_report(
tenant_id: str,
report_id: str,
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
# Verify user belongs to the requested tenant
if current_user.tenant_id != tenant_id:
raise HTTPException(status_code=403, detail="Access denied")
# Verify user has the required role
if "reports:read" not in current_user.permissions:
raise HTTPException(status_code=403, detail="Insufficient permissions")
# Fetch with tenant scoping to prevent IDOR
stmt = (
select(Report)
.where(Report.id == report_id, Report.tenant_id == tenant_id)
)
report = (await db.execute(stmt)).scalar_one_or_none()
if not report:
raise HTTPException(status_code=404)
return report
import logging
import json
from datetime import datetime, timezone
class SecurityAuditFormatter(logging.Formatter):
"""Structured JSON formatter for security-relevant events."""
def format(self, record: logging.LogRecord) -> str:
log_entry = {
"timestamp": datetime.now(timezone.utc).isoformat(),
"level": record.levelname,
"logger": record.name,
"message": record.getMessage(),
"module": record.module,
"function": record.funcName,
}
# Add security context if present
for field in ("user_id", "tenant_id", "action", "resource", "outcome", "ip_address"):
if hasattr(record, field):
log_entry[field] = getattr(record, field)
return json.dumps(log_entry)
# Configure security audit logger
security_logger = logging.getLogger("security.audit")
security_logger.setLevel(logging.INFO)
handler = logging.StreamHandler()
handler.setFormatter(SecurityAuditFormatter())
security_logger.addHandler(handler)
# Usage in authentication flow
def log_auth_event(user_id: str, tenant_id: str, action: str, outcome: str, ip: str):
security_logger.info(
"Authentication event",
extra={
"user_id": user_id,
"tenant_id": tenant_id,
"action": action,
"outcome": outcome,
"ip_address": ip,
},
)
# Example calls
log_auth_event("usr_123", "tnt_456", "login", "success", "203.0.113.42")
log_auth_event("usr_789", "tnt_456", "login", "failure_invalid_password", "198.51.100.7")
A01 - Broken Access Control:
A02 - Cryptographic Failures:
A03 - Injection:
A04 - Insecure Design:
A05 - Security Misconfiguration:
A06 - Vulnerable Components:
A07 - Authentication Failures:
A08 - Integrity Failures:
A09 - Logging Failures:
A10 - SSRF: