framework/web_development/.opencode/skills/secure-coding-cybersecurity/SKILL.md
Expert guidance on secure coding practices, focusing on preventing common security errors made by AI during code generation. Use for: auditing AI-generated code, implementing secure design patterns, and ensuring code follows OWASP Top 10 standards. Covers input validation, authentication, cryptography, file handling, secure configuration, and business logic security.
npx skillsauth add b4san/ac-framework secure-coding-cybersecurityInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill establishes security as a first-class citizen in code generation and review. It recognizes that AI-generated code often prioritizes functionality over security, inheriting and propagating vulnerabilities from training data. This skill provides comprehensive guardrails, checklists, and verification steps to ensure all code—especially AI-generated—is robust, secure, and follows industry best practices.
AI models optimize for "working code" and "correct-looking output" before "secure and robust code." This introduces classic vulnerabilities at concerning rates:
Functionality over Security: If the prompt doesn't explicitly demand security, the model prioritizes the shortest solution even if it uses eval(), SQL string concatenation, or hardcoded keys.
Learning from Insecure Examples: A significant portion of publicly available code contains bad practices (hardcoded secrets, weak encryption, missing validation), and models reproduce these patterns.
Lack of Context Awareness: AI doesn't understand your business rules, threat model, or compliance requirements (PCI-DSS, HIPAA, GDPR), filling gaps with dangerous assumptions.
High CWE Rates in Studies: Empirical research consistently finds serious vulnerabilities (SQLi, XSS, buffer overflows, crypto misuse, hardcoded credentials) in AI-generated code samples.
These rules must NEVER be violated, regardless of convenience or "example purposes":
Never Prioritize Simplicity Over Security: Do not provide "clean" examples that omit input validation or use insecure defaults, even with disclaimers.
Treat AI Output as Untrusted: Always audit AI-generated snippets for hallucinated libraries, outdated patterns, and missing security controls.
Fail Closed: All logic must default to "Access Denied" if an exception occurs, validation fails, or state is unclear.
No Hardcoded Secrets: Never suggest code with hardcoded API keys, passwords, tokens, or cryptographic keys. Always use environment variables, secret managers, or secure vaults.
Parameterized Everything: Never use string concatenation or formatting for SQL queries, OS commands, HTML rendering, or LDAP filters.
Validate All Inputs: Every piece of external data must be validated and sanitized before use.
Defense in Depth: Never rely on a single security control; implement multiple layers of protection.
The Problem: AI frequently omits input validation and sanitization unless explicitly requested, leading to CWE-20 (Improper Input Validation) and the entire injection vulnerability family (SQLi, XSS, OS Command Injection, LDAP Injection).
Research Finding: Multiple studies identify SQL injection, XSS, and OS command injection as recurrent vulnerabilities in LLM-generated code.
[ ] Validate and normalize ALL user input before use, including:
[ ] Use allowlists over denylists: Define what is permitted rather than trying to block what is malicious. Use strict type checking, enum validation, and schema validation.
[ ] Parameterized queries ONLY: Never concatenate strings to build SQL queries, shell commands, LDAP filters, XPath expressions, or NoSQL queries. Always use:
[ ] XSS Prevention: Escape or sanitize all data before rendering in HTML contexts:
innerHTML, document.write, and similar dangerous APIs[ ] Disable dangerous evaluation: Never use eval(), Function(), exec(), child_process.exec(), Runtime.exec(), os.system(), or similar on user-controlled data. If dynamic execution is absolutely necessary, use strict sandboxing and allowlists.
[ ] Strict regex validation: When using regular expressions for validation:
^pattern$) over partial matchesBefore considering input handling complete:
# ❌ NEVER DO THIS - SQL Injection vulnerability
query = f"SELECT * FROM users WHERE id = {user_id}"
cursor.execute(query)
# ✅ DO THIS INSTEAD - Parameterized query
query = "SELECT * FROM users WHERE id = ?"
cursor.execute(query, (user_id,))
# ❌ NEVER DO THIS - XSS vulnerability
element.innerHTML = userInput
// ❌ NEVER DO THIS - Command Injection
const output = exec(`ls ${userInput}`);
// ✅ DO THIS INSTEAD - Safe command execution with allowlist
const allowedCommands = ['list', 'status'];
if (allowedCommands.includes(userInput)) {
const output = execFile('ls', [safePath]);
}
The Problem: AI generates authentication flows that "pass happy path tests" but ignore critical security details like rate limiting, constant-time comparison, or fine-grained authorization controls. This enables brute-force attacks, privilege escalation, and API abuse.
[ ] Secure password storage:
[ ] Constant-time comparisons: Compare tokens, passwords, and API keys using constant-time comparison functions to prevent timing attacks:
hmac.compare_digest()crypto.timingSafeEqual()MessageDigest.isEqual()[ ] Rate limiting and brute-force protection:
[ ] Authorization on every endpoint:
[ ] Secure session management:
[ ] Secure cookie configuration:
HttpOnly flag (prevents JavaScript access)Secure flag (HTTPS only)SameSite attribute (Strict or Lax)Max-Age or Expires__Host- prefix for additional protection[ ] JWT security:
[ ] Password reset security:
[ ] Multi-factor authentication (MFA):
# ❌ NEVER DO THIS - Insecure password hashing
hashed = hashlib.md5(password.encode()).hexdigest()
# ✅ DO THIS INSTEAD - Secure password hashing
hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=12))
# ❌ NEVER DO THIS - Timing attack vulnerability
if token == stored_token:
# authenticate
# ✅ DO THIS INSTEAD - Constant-time comparison
if hmac.compare_digest(token, stored_token):
# authenticate
# ❌ NEVER DO THIS - No rate limiting
@app.route('/login', methods=['POST'])
def login():
# authenticate
# ✅ DO THIS INSTEAD - Rate limiting
@limiter.limit("5 per minute")
@app.route('/login', methods=['POST'])
def login():
# authenticate
# ❌ NEVER DO THIS - Missing authorization check
@app.route('/api/documents/<doc_id>')
def get_document(doc_id):
return Document.query.get(doc_id) # No ownership check!
# ✅ DO THIS INSTEAD - Verify ownership
def get_document(doc_id):
document = Document.query.get_or_404(doc_id)
if document.owner_id != current_user.id:
abort(403)
return document
The Problem: AI models frequently copy insecure cryptographic patterns from training data: obsolete ciphers, incorrect modes, hardcoded keys, weak PRNGs, and custom cryptographic schemes. They also commonly suggest embedding secrets directly in code or configuration files.
[ ] No hardcoded secrets: Search for and eliminate:
[ ] Secure secrets management:
.env files)[ ] Modern cryptographic algorithms:
[ ] Avoid deprecated/weak algorithms:
[ ] Cryptographically secure random number generation:
secrets.token_hex(), secrets.token_urlsafe(), secrets.randbits()crypto.randomBytes(), crypto.randomUUID()SecureRandomMath.random(), random module, or other non-cryptographic RNGs for security purposes[ ] Proper key lengths and parameters:
[ ] Proper IV/nonce handling:
[ ] Never roll your own crypto:
truffleHog, git-secrets, or detect-secrets to find leaked secrets# ❌ NEVER DO THIS - Hardcoded secret
API_KEY = "sk_live_1234567890abcdef"
# ✅ DO THIS INSTEAD - Load from environment
import os
API_KEY = os.environ.get('API_KEY')
if not API_KEY:
raise ValueError("API_KEY environment variable is required")
# ❌ NEVER DO THIS - Weak encryption
encrypted = des.encrypt(data)
# ✅ DO THIS INSTEAD - Authenticated encryption
from cryptography.fernet import Fernet
key = Fernet.generate_key()
cipher = Fernet(key)
encrypted = cipher.encrypt(data)
# ❌ NEVER DO THIS - Insecure random for security
import random
token = random.randint(100000, 999999)
# ✅ DO THIS INSTEAD - Cryptographically secure random
import secrets
token = secrets.randbelow(1000000)
# ❌ NEVER DO THIS - Custom crypto scheme
def custom_hash(data):
return data[::-1] + "salt"
# ✅ DO THIS INSTEAD - Use standard library
import hashlib
hashed = hashlib.sha256(data).hexdigest()
The Problem: Documentation examples that AI learns from often omit path validation, file type checking, or size limits. This enables path traversal, remote code execution via deserialization, and Denial of Service through huge files. AI frequently uses dangerous APIs like pickle.loads() or unserialize() on untrusted data.
[ ] Path traversal prevention:
chroot jails or containerization where appropriate../, ..\, null bytes)[ ] Secure file uploads:
[ ] Deserialization security:
[ ] File permission security:
../, null bytes, Unicode normalization attacks# ❌ NEVER DO THIS - Path traversal vulnerability
filename = request.args.get('file')
with open(f"/uploads/{filename}", 'r') as f:
content = f.read()
# ✅ DO THIS INSTEAD - Safe path handling
import os
from pathlib import Path
upload_dir = Path("/uploads").resolve()
filename = request.args.get('file')
# Sanitize and validate
safe_filename = os.path.basename(filename)
file_path = (upload_dir / safe_filename).resolve()
# Ensure the resolved path is within upload_dir
if not str(file_path).startswith(str(upload_dir)):
abort(403)
# ❌ NEVER DO THIS - Unsafe deserialization
import pickle
data = pickle.loads(untrusted_input)
# ✅ DO THIS INSTEAD - Safe deserialization
import json
data = json.loads(untrusted_input)
# Validate against schema
if not validate_json_schema(data, SCHEMA):
raise ValueError("Invalid data format")
# ❌ NEVER DO THIS - Insecure file upload
file = request.files['document']
file.save(f"/uploads/{file.filename}")
// ❌ NEVER DO THIS - Extension validation bypass
const allowedExtensions = ['.jpg', '.png'];
if (allowedExtensions.includes(path.extname(filename))) {
// This can be bypassed with double extensions or null bytes
}
// ✅ DO THIS INSTEAD - Comprehensive validation
const allowedTypes = ['image/jpeg', 'image/png'];
const maxSize = 5 * 1024 * 1024; // 5MB
if (!allowedTypes.includes(file.mimetype)) {
throw new Error('Invalid file type');
}
if (file.size > maxSize) {
throw new Error('File too large');
}
// Verify magic bytes match MIME type
const magic = file.buffer.slice(0, 4);
if (!isValidMagicBytes(magic, file.mimetype)) {
throw new Error('File content does not match type');
}
The Problem: AI frequently proposes insecure example configurations: CORS set to *, disabled TLS verification, disabled CSRF protection, or verbose debug logging in production. AI may also "hallucinate" packages that don't exist or suggest typosquatted/obsoleted dependencies.
[ ] Secure CORS configuration:
* in production (only for specific development scenarios)maxAge for preflight caching[ ] TLS/SSL security:
[ ] Security headers:
[ ] CSRF protection:
[ ] Debug mode and information disclosure:
[ ] Secure logging:
[ ] Dependency security:
[ ] Container and runtime security:
securityheaders.com to verify header configuration# ❌ NEVER DO THIS - Insecure CORS
CORS(app, resources={r"/*": {"origins": "*"}})
# ✅ DO THIS INSTEAD - Explicit origins
CORS(app, resources={
r"/api/*": {
"origins": ["https://app.example.com", "https://admin.example.com"],
"methods": ["GET", "POST"],
"allow_headers": ["Content-Type", "Authorization"]
}
})
# ❌ NEVER DO THIS - Disabled TLS verification
requests.get(url, verify=False)
# ✅ DO THIS INSTEAD - Proper TLS configuration
requests.get(url, verify=True) # Default, verify certificates
# ❌ NEVER DO THIS - Debug mode in production
app.run(debug=True)
# ✅ DO THIS INSTEAD - Environment-based configuration
debug = os.environ.get('FLASK_ENV') == 'development'
app.run(debug=debug)
# ❌ NEVER DO THIS - Logging sensitive data
logger.info(f"User login: {username}, password: {password}")
// ❌ NEVER DO THIS - Information disclosure in errors
app.use((err, req, res, next) => {
res.status(500).json({ error: err.stack });
});
// ✅ DO THIS INSTEAD - Safe error handling
app.use((err, req, res, next) => {
console.error(err); // Log internally
res.status(500).json({ error: 'Internal server error' }); // Generic public message
});
The Problem: AI doesn't understand your business rules, threat model, or compliance requirements. It makes dangerous assumptions like "the input will always be valid" or "only internal users will call this API." This leads to logic vulnerabilities that aren't syntactically obvious.
[ ] Document security assumptions: Explicitly write down:
[ ] Beware of "fast paths": Review any logic that skips security controls under certain conditions:
[ ] Server-side authorization: Never rely on client-controlled data for authorization decisions:
[ ] Sensitive operation protection:
[ ] Data exposure review:
[ ] Race condition protection:
[ ] Business logic validation:
# ❌ NEVER DO THIS - Client-controlled authorization
role = request.json.get('role') # User can set their own role!
if role == 'admin':
# grant admin access
# ✅ DO THIS INSTEAD - Server-side role verification
user = get_current_user()
if not user.has_permission('admin'):
abort(403)
# ❌ NEVER DO THIS - Sensitive operation without confirmation
@app.route('/api/change-email', methods=['POST'])
def change_email():
current_user.email = request.json['new_email']
db.session.commit()
return {'status': 'success'}
# ✅ DO THIS INSTEAD - Require verification
def change_email():
new_email = request.json['new_email']
token = generate_verification_token(new_email)
send_verification_email(new_email, token)
return {'status': 'verification_sent'}
// ❌ NEVER DO THIS - Over-exposure of data
app.get('/api/users', (req, res) => {
const users = await User.findAll();
res.json(users); // Returns all fields including hashed passwords!
});
// ✅ DO THIS INSTEAD - Selective field exposure
app.get('/api/users', async (req, res) => {
const users = await User.findAll({
attributes: ['id', 'username', 'email'] // Explicitly choose fields
});
res.json(users);
});
The Problem: AI-generated code often lacks proper error handling or exposes sensitive information in error messages, stack traces, or logs. This aids attackers in reconnaissance and exploitation.
[ ] Safe error responses:
[ ] Proper exception handling:
except: or catch (Exception e)[ ] Fail securely:
[ ] Information leakage prevention:
The Problem: APIs are increasingly targeted and AI-generated code often lacks proper API security controls like rate limiting, authentication, input validation, and output encoding.
[ ] API authentication:
[ ] API rate limiting:
[ ] API versioning:
[ ] API documentation security:
[ ] Webhook security:
Stay current with the latest OWASP Top 10 vulnerabilities and ensure your applications are protected against them.
Address the most dangerous software weaknesses identified by MITRE and SANS.
Security is not a feature—it's a foundation. AI-generated code requires extra scrutiny because models prioritize functionality and aesthetics over security. This skill provides the guardrails, checklists, and verification steps needed to ensure your code is secure by design, not by accident, the examples provided in this place are from python but you need to adapt the logic from python to the codebase language.
Remember: Trust but verify. Always assume AI-generated code contains vulnerabilities until proven otherwise through rigorous review and testing.
This skill should be consulted for every code generation task, every code review, and every security audit. Security is everyone's responsibility.
development
React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.
development
Automate the generation and maintenance of unit, integration, and end-to-end tests, as well as test data generation and debugging. Use when writing tests for new features, maintaining existing tests after API/UI changes, generating synthetic test data, or debugging test failures. Essential for ensuring code quality and preventing regressions.
testing
Generate comprehensive test suites ensuring requirements are met. Strategies for Unit, Integration, and E2E testing.
development
Use when encountering any bug, test failure, or unexpected behavior, before proposing fixes