| name | security-hardening |
| description | Apply OWASP Top 10 mitigations as concrete grep-able patterns and code fixes during development and review. Trigger on "harden application", "OWASP review", "security controls", "injection prevention", "XSS prevention", or security audit response. Do not use for security-best-practices (language-specific secure coding guidance), security-threat-model (threat enumeration and abuse paths), or auth-patterns (authentication/authorization implementation). |
| license | Apache-2.0 |
| compatibility | {"clients":["openai-codex","gemini-cli","opencode","github-copilot"]} |
| metadata | {"owner":"codex","domain":"security-hardening","maturity":"draft","risk":"low","tags":["security","hardening"]} |
Purpose
Apply OWASP Top 10 mitigations to code during development and review. Each vulnerability class has specific, checkable defenses—not vague "be careful" advice. This skill translates threat categories into grep-able patterns and concrete fixes.
When to use this skill
Use when:
- Code review with security focus
- Hardening existing application before launch
- Adding security controls to new feature
- Responding to security audit findings
Do NOT use when:
- Full penetration testing needed (hire specialists)
- Compliance audit (use compliance-specific checklists)
- Infrastructure security (different skill set)
Operating procedure
-
A01:2021 - Broken Access Control (most critical):
@app.get("/users/{user_id}/data")
def get_user_data(user_id: int):
return db.get_user_data(user_id)
@app.get("/users/{user_id}/data")
def get_user_data(user_id: int, current_user: User = Depends(get_current_user)):
if current_user.id != user_id and not current_user.is_admin:
raise HTTPException(403, "Not authorized")
return db.get_user_data(user_id)
-
A02:2021 - Cryptographic Failures:
password_hash = hashlib.md5(password.encode()).hexdigest()
from passlib.hash import argon2
password_hash = argon2.hash(password)
API_KEY = "sk-1234567890"
API_KEY = os.environ["API_KEY"]
-
A03:2021 - Injection (SQL, Command, LDAP):
query = f"SELECT * FROM users WHERE email = ''"
query =
cursor.execute(query, (email,))
os.system()
subprocess.run([, user_filename, ], check=)
Output defaults
## Security Review: [Component/Feature]
### Findings
| ID | Category | Severity | Location | Issue | Fix |
|----|----------|----------|----------|-------|-----|
| 1 | A03 Injection | High | api/users.py:45 | SQL string formatting | Use parameterized query |
| 2 | A01 Access Control | Medium | api/orders.py:23 | Missing ownership check | Add user_id verification |
### Mitigations Applied
- [ ] Input validation on all endpoints
- [ ] Parameterized queries for all DB access
- [ ] Authorization checks on resource access
- [ ] Rate limiting on auth endpoints
- [ ] Security headers configured
### Headers to Set
Content-Security-Policy: default-src 'self'
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Strict-Transport-Security: max-age=31536000; includeSubDomains
References
Failure handling
- Finding too many issues: Prioritize by exploitability and impact; fix critical auth/injection first
- Can't fix without major refactor: Document as tech debt with risk assessment; add compensating controls
- Third-party library vulnerable: Check if newer version available; if not, evaluate alternatives or add wrapper validation
- Security vs. usability conflict: Document the tradeoff explicitly; get business decision rather than silently accepting risk
- Not sure if issue is exploitable: Assume it is; fix it anyway—defense in depth