Help us improve
Share bugs, ideas, or general feedback.
<!-- AUTO-GENERATED by export-plugins.py — DO NOT EDIT -->
npx claudepluginhub frank-luongt/faos-skills-marketplace --plugin faos-security-engineerHow this skill is triggered — by the user, by Claude, or both
Slash command
/faos-security-engineer:owasp-top10The summary Claude sees in its skill listing — used to decide when to auto-load this skill
<!-- AUTO-GENERATED by export-plugins.py — DO NOT EDIT -->
Provides OWASP Top 10 guidelines, secure Python/Flask coding patterns, prevention strategies, and remediation for access control and cryptographic vulnerabilities.
Audits web applications against OWASP Top 10 (2021) vulnerabilities with quick and deep scan modes, outputting actionable findings per category.
Reviews code and architectures against OWASP Top 10:2025 web application security risks. Useful for vulnerability audits, codebase reviews, remediation guidance, and secure coding patterns.
Share bugs, ideas, or general feedback.
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: