Files
opencode-skill/skills/security-coder/SKILL.md
Kunthawat Greethong 7edf5bc4d0 feat: Import 35+ skills, merge duplicates, add openclaw installer
Major updates:
- Added 35+ new skills from awesome-opencode-skills and antigravity repos
- Merged SEO skills into seo-master
- Merged architecture skills into architecture
- Merged security skills into security-auditor and security-coder
- Merged testing skills into testing-master and testing-patterns
- Merged pentesting skills into pentesting
- Renamed website-creator to thai-frontend-dev
- Replaced skill-creator with github version
- Removed Chutes references (use MiniMax API instead)
- Added install-openclaw-skills.sh for cross-platform installation
- Updated .env.example with MiniMax API credentials
2026-03-26 11:37:39 +07:00

325 lines
7.4 KiB
Markdown

---
name: security-coder
description: |
Master secure coding skill combining frontend, backend, and mobile security coding.
XSS prevention, injection prevention, authentication, API security.
Use when writing secure code or fixing security vulnerabilities.
---
# Security Coder
Comprehensive secure coding skill combining: frontend security, backend security, and mobile security coding practices.
---
## Quick Reference
| Task | Use Section |
|------|-------------|
| Prevent XSS | **Frontend Security** |
| Secure APIs | **Backend Security** |
| Mobile app security | **Mobile Security** |
| Fix vulnerabilities | **Common Fixes** |
| Input validation | **Input Security** |
| Auth implementation | **Authentication** |
---
## Frontend Security (XSS Prevention)
### Output Handling
| Unsafe | Safe |
|--------|------|
| `element.innerHTML = userInput` | `element.textContent = userInput` |
| `document.write(userInput)` | `element.appendChild(safeEl)` |
| `eval(userInput)` | Never eval user input |
| `href=userInput` (javascript:) | Validate protocol, use `#` for unknown |
### Sanitization
```javascript
// Use DOMPurify for HTML content
import DOMPurify from 'dompurify';
const clean = DOMPurify.sanitize(dirty, { ALLOWED_TAGS: ['b', 'i'] });
// Always use textContent for user data
element.textContent = userData;
// Encode for context
// HTML: < > & "
// JS: \x3C \x3E \u2028 \u2029
// URL: encodeURIComponent()
// CSS: escape or use allowlist
```
### Content Security Policy (CSP)
```http
Content-Security-Policy:
default-src 'self';
script-src 'self' 'nonce-{random}' https://trusted-cdn.com;
style-src 'self' 'nonce-{random}';
img-src 'self' https: data:;
font-src 'self';
connect-src 'self' https://api.example.com;
frame-ancestors 'none';
base-uri 'self';
form-action 'self';
```
### Safe DOM Manipulation
- Always prefer `textContent` over `innerHTML`
- Use `document.createElement()` over `document.write()`
- Validate URLs before setting `href`, `src`, `action`
- Use `srcdoc` only with sanitized content
---
## Backend Security (Injection Prevention)
### SQL Injection Prevention
```python
# BAD - vulnerable
query = f"SELECT * FROM users WHERE id = {user_id}"
# GOOD - parameterized
query = "SELECT * FROM users WHERE id = %s"
cursor.execute(query, (user_id,))
# GOOD - ORM
user = User.query.filter_by(id=user_id).first()
```
### NoSQL Injection Prevention
```python
# Validate input types
if not isinstance(user_id, int):
raise ValueError("Invalid ID type")
# Use parameterized queries
result = db.users.find_one({"_id": ObjectId(user_id)})
```
### Command Injection Prevention
```python
# NEVER use user input in shell commands
# BAD
os.system(f"grep {user_input} file")
# GOOD - subprocess with list
subprocess.run(["grep", user_input, "file"], shell=False)
# GOOD - shlex.quote
os.system(f"grep {shlex.quote(user_input)} file")
```
### Input Validation
```python
# Allowlist validation
import re
def validate_email(email):
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
return re.match(pattern, email) is not None
# Type validation
def get_user_id(user_id):
if isinstance(user_id, str) and user_id.isdigit():
return int(user_id)
raise ValueError("Invalid user ID")
# Range validation
def get_page(page, max_page=100):
page = int(page)
if page < 1:
page = 1
return min(page, max_page)
```
---
## API Security
### Authentication Headers
```http
Authorization: Bearer <jwt_token>
X-API-Key: <api_key>
```
### Rate Limiting
```python
# Implement rate limiting
from functools import wraps
import time
def rate_limit(max_calls, period):
def decorator(func):
calls = {}
@wraps(func)
def wrapper(*args, **kwargs):
now = time.time()
key = func.__name__
if key not in calls:
calls[key] = []
calls[key] = [t for t in calls[key] if now - t < period]
if len(calls[key]) >= max_calls:
raise TooManyRequestsError()
calls[key].append(now)
return func(*args, **kwargs)
return wrapper
return decorator
```
### Security Headers
```python
response.headers.update({
'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
'X-Content-Type-Options': 'nosniff',
'X-Frame-Options': 'DENY',
'X-XSS-Protection': '1; mode=block',
'Referrer-Policy': 'strict-origin-when-cross-origin',
'Permissions-Policy': 'geolocation=(), microphone=(), camera=()',
'Content-Security-Policy': "default-src 'self'"
})
```
### CORS Configuration
```python
# Strict CORS
ALLOWED_ORIGINS = ['https://app.example.com']
@app.after_request
def add_cors(response):
origin = request.headers.get('Origin')
if origin in ALLOWED_ORIGINS:
response.headers['Access-Control-Allow-Origin'] = origin
response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE'
response.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization'
response.headers['Access-Control-Allow-Credentials'] = 'true'
return response
```
---
## Authentication Security
### Password Hashing
```python
# Use bcrypt or Argon2
import bcrypt
def hash_password(password):
return bcrypt.hashpw(password.encode(), bcrypt.gensalt())
def verify_password(password, hashed):
return bcrypt.checkpw(password.encode(), hashed)
# Or Argon2
from argon2 import PasswordHasher
ph = PasswordHasher()
hash = ph.hash("secret")
ph.verify(hash, "secret")
```
### JWT Security
```python
# Sign with RS256 (asymmetric)
# Verify with public key
import jwt
# Token structure
payload = {
'sub': user_id,
'exp': datetime.utcnow() + timedelta(hours=1),
'iat': datetime.utcnow(),
'scope': ['read', 'write'] # Minimal scopes
}
# Short expiration, no sensitive data
token = jwt.encode(payload, private_key, algorithm='RS256')
```
### Session Management
```python
# Secure session config
SESSION_COOKIE = {
'httponly': True, # No JS access
'secure': True, # HTTPS only
'samesite': 'Lax', # CSRF protection
'max-age': 3600, # 1 hour
}
```
---
## Mobile Security
### iOS Security
- Keychain for sensitive data
- Certificate pinning
- jailbreak detection
- Biometric auth (Face ID, Touch ID)
- Obfuscate API keys
### Android Security
- Keystore for keys
- Network security config
- ProGuard/R8 obfuscation
- Safe browsing API
- Biometric auth
### React Native
```javascript
// Secure storage
import * as Keychain from 'react-native-keychain';
// Certificate pinning
const sslPinning = {
certs: ['cert1', 'cert2']
};
```
---
## Common Security Fixes
### IDOR Prevention
```python
# Always verify ownership
def get_document(doc_id, user_id):
doc = Document.query.get(doc_id)
if doc.owner_id != user_id:
abort(403) # Forbidden
return doc
```
### CSRF Prevention
```python
# Use CSRF tokens
from flask_wtf import FlaskForm
from wtforms import SubmitField
class MyForm(FlaskForm):
csrf_token = HiddenField()
submit = SubmitField()
```
### XXE Prevention
```python
# Disable XML external entities
import defusedxml
ET = defusedxml.ElementSafeTypes
```
---
## Security Checklist
- [ ] Input validation on all user data
- [ ] Parameterized queries (no string interpolation)
- [ ] Output encoding for context
- [ ] CSRF tokens on forms
- [ ] Secure session configuration
- [ ] HTTPS only
- [ ] Security headers
- [ ] Rate limiting
- [ ] Logging without sensitive data
- [ ] Error messages without stack traces