---
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: &lt; &gt; &amp; &quot;
// 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
