--- 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 X-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