security-first
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSecurity First - Shield Your Code
安全优先 - 守护你的代码
🎯 When to Use This Skill
🎯 何时使用本技能
Use BEFORE:
- Deploying to production
- Handling sensitive data
- Opening API endpoints
- Processing user input
- Storing passwords
- Accepting file uploads
- Going live with payments
请在以下场景前使用:
- 部署到生产环境
- 处理敏感数据
- 开放API端点
- 处理用户输入
- 存储密码
- 接受文件上传
- 上线支付功能
⚡ 5-Minute Security Audit
⚡ 5分钟安全审计
WITH MCP (Security Scanner):
借助MCP(安全扫描工具):
"Run complete security audit on my codebase"
"Find and fix all OWASP Top 10 vulnerabilities""Run complete security audit on my codebase"
"Find and fix all OWASP Top 10 vulnerabilities"WITHOUT MCP - Quick Scan:
无MCP时 - 快速扫描:
bash
undefinedbash
undefined1. Find hardcoded secrets (CRITICAL!)
1. 查找硬编码密钥(重中之重!)
grep -r "password|secret|token|api[_-]key" --include=".js" --include=".env" | grep -v ".example"
grep -r "password|secret|token|api[_-]key" --include=".js" --include=".env" | grep -v ".example"
2. Check for SQL injection
2. 检查SQL注入风险
grep -r "query.+|query.${" --include="*.js"
grep -r "query.+|query.${" --include="*.js"
3. Find eval/exec usage
3. 查找eval/exec的使用
grep -r "eval(|exec(|Function(" --include="*.js"
grep -r "eval(|exec(|Function(" --include="*.js"
4. Check dependencies
4. 检查依赖包安全性
npm audit # or pip check, bundle audit
npm audit # 或 pip check, bundle audit
5. Find unvalidated input
5. 查找未验证的输入
grep -r "req.body|req.query|req.params" --include="*.js" | grep -v "validate|sanitize"
undefinedgrep -r "req.body|req.query|req.params" --include="*.js" | grep -v "validate|sanitize"
undefined🛡️ OWASP Top 10 Checklist (2024)
🛡️ OWASP Top 10 检查清单(2024版)
1. Injection (SQL, NoSQL, Command) 💉
1. 注入攻击(SQL、NoSQL、命令注入)💉
Vulnerable Code:
javascript
// ❌ NEVER DO THIS
const query = `SELECT * FROM users WHERE id = ${req.params.id}`;
db.query(query); // SQL Injection!
// ❌ Command injection
exec(`ping ${userInput}`); // Dangerous!Secure Code:
javascript
// ✅ Parameterized queries
const query = 'SELECT * FROM users WHERE id = ?';
db.query(query, [req.params.id]);
// ✅ For MongoDB
User.findOne({ _id: sanitize(req.params.id) });
// ✅ Command execution
const { spawn } = require('child_process');
spawn('ping', [userInput], { shell: false });存在漏洞的代码:
javascript
// ❌ 绝对不要这么做
const query = `SELECT * FROM users WHERE id = ${req.params.id}`;
db.query(query); // 存在SQL注入风险!
// ❌ 命令注入风险
exec(`ping ${userInput}`); // 非常危险!安全代码示例:
javascript
// ✅ 使用参数化查询
const query = 'SELECT * FROM users WHERE id = ?';
db.query(query, [req.params.id]);
// ✅ MongoDB安全写法
User.findOne({ _id: sanitize(req.params.id) });
// ✅ 安全的命令执行
const { spawn } = require('child_process');
spawn('ping', [userInput], { shell: false });2. Broken Authentication 🔐
2. 身份验证机制缺陷 🔐
Security Checklist:
javascript
// ✅ Strong password requirements
function validatePassword(password) {
const requirements = {
minLength: 12,
hasUpperCase: /[A-Z]/.test(password),
hasLowerCase: /[a-z]/.test(password),
hasNumbers: /\d/.test(password),
hasSpecialChar: /[!@#$%^&*]/.test(password),
notCommon: !commonPasswords.includes(password)
};
return Object.values(requirements).every(req => req);
}
// ✅ Secure session management
app.use(session({
secret: process.env.SESSION_SECRET, // From environment
resave: false,
saveUninitialized: false,
cookie: {
secure: true, // HTTPS only
httpOnly: true, // No JS access
maxAge: 3600000, // 1 hour
sameSite: 'strict' // CSRF protection
}
}));
// ✅ Rate limiting
const rateLimit = require('express-rate-limit');
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5, // 5 attempts
message: 'Too many login attempts'
});
app.post('/login', loginLimiter, loginHandler);安全检查清单代码示例:
javascript
// ✅ 强密码要求验证
function validatePassword(password) {
const requirements = {
minLength: 12,
hasUpperCase: /[A-Z]/.test(password),
hasLowerCase: /[a-z]/.test(password),
hasNumbers: /\d/.test(password),
hasSpecialChar: /[!@#$%^&*]/.test(password),
notCommon: !commonPasswords.includes(password)
};
return Object.values(requirements).every(req => req);
}
// ✅ 安全的会话管理
app.use(session({
secret: process.env.SESSION_SECRET, // 从环境变量获取
resave: false,
saveUninitialized: false,
cookie: {
secure: true, // 仅HTTPS下可用
httpOnly: true, // 禁止JS访问
maxAge: 3600000, // 1小时有效期
sameSite: 'strict' // 防CSRF攻击
}
}));
// ✅ 访问频率限制
const rateLimit = require('express-rate-limit');
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15分钟
max: 5, // 最多5次尝试
message: '登录尝试次数过多'
});
app.post('/login', loginLimiter, loginHandler);3. Sensitive Data Exposure 🔒
3. 敏感数据泄露 🔒
Never Store in Code:
javascript
// ❌ WRONG
const API_KEY = "sk_live_abcd1234";
const DB_PASSWORD = "admin123";
// ✅ CORRECT - Use environment variables
const API_KEY = process.env.API_KEY;
const DB_PASSWORD = process.env.DB_PASSWORD;
// ✅ Use .env file (never commit!)
require('dotenv').config();
// ✅ Encrypt sensitive data at rest
const crypto = require('crypto');
const algorithm = 'aes-256-gcm';
function encrypt(text) {
const key = Buffer.from(process.env.ENCRYPTION_KEY, 'hex');
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv(algorithm, key, iv);
let encrypted = cipher.update(text, 'utf8', 'hex');
encrypted += cipher.final('hex');
const authTag = cipher.getAuthTag();
return {
encrypted,
iv: iv.toString('hex'),
authTag: authTag.toString('hex')
};
}绝对不要在代码中存储:
javascript
// ❌ 错误写法
const API_KEY = "sk_live_abcd1234";
const DB_PASSWORD = "admin123";
// ✅ 正确写法 - 使用环境变量
const API_KEY = process.env.API_KEY;
const DB_PASSWORD = process.env.DB_PASSWORD;
// ✅ 使用.env文件(绝对不要提交到代码仓库!)
require('dotenv').config();
// ✅ 静态敏感数据加密
const crypto = require('crypto');
const algorithm = 'aes-256-gcm';
function encrypt(text) {
const key = Buffer.from(process.env.ENCRYPTION_KEY, 'hex');
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv(algorithm, key, iv);
let encrypted = cipher.update(text, 'utf8', 'hex');
encrypted += cipher.final('hex');
const authTag = cipher.getAuthTag();
return {
encrypted,
iv: iv.toString('hex'),
authTag: authTag.toString('hex')
};
}4. XML External Entities (XXE) 📄
4. XML外部实体注入(XXE)📄
javascript
// ❌ Vulnerable XML parsing
const libxmljs = require('libxmljs');
const doc = libxmljs.parseXml(userInput); // XXE vulnerable!
// ✅ Safe XML parsing
const parser = new DOMParser();
const doc = parser.parseFromString(userInput, 'text/xml');
// ✅ Or disable external entities
const options = {
xmlMode: true,
recognizeSelfClosing: true,
decodeEntities: false // Disable entity expansion
};javascript
// ❌ 存在XXE漏洞的XML解析
const libxmljs = require('libxmljs');
const doc = libxmljs.parseXml(userInput); // 存在XXE漏洞!
// ✅ 安全的XML解析
const parser = new DOMParser();
const doc = parser.parseFromString(userInput, 'text/xml');
// ✅ 或禁用外部实体
const options = {
xmlMode: true,
recognizeSelfClosing: true,
decodeEntities: false // 禁用实体扩展
};5. Broken Access Control 🚪
5. 访问控制机制缺陷 🚪
javascript
// ❌ No authorization check
app.get('/api/user/:id', (req, res) => {
const user = User.findById(req.params.id);
res.json(user); // Anyone can see any user!
});
// ✅ Proper authorization
app.get('/api/user/:id', authenticate, (req, res) => {
// Check if user can access this resource
if (req.user.id !== req.params.id && !req.user.isAdmin) {
return res.status(403).json({ error: 'Forbidden' });
}
const user = User.findById(req.params.id);
res.json(user);
});
// ✅ Role-based access control (RBAC)
const authorize = (roles) => {
return (req, res, next) => {
if (!roles.includes(req.user.role)) {
return res.status(403).json({ error: 'Insufficient permissions' });
}
next();
};
};
app.delete('/api/users/:id', authenticate, authorize(['admin']), deleteUser);javascript
// ❌ 未做权限校验
app.get('/api/user/:id', (req, res) => {
const user = User.findById(req.params.id);
res.json(user); // 任何人都能查看所有用户信息!
});
// ✅ 正确的权限校验
app.get('/api/user/:id', authenticate, (req, res) => {
// 检查用户是否有权限访问该资源
if (req.user.id !== req.params.id && !req.user.isAdmin) {
return res.status(403).json({ error: '禁止访问' });
}
const user = User.findById(req.params.id);
res.json(user);
});
// ✅ 基于角色的访问控制(RBAC)
const authorize = (roles) => {
return (req, res, next) => {
if (!roles.includes(req.user.role)) {
return res.status(403).json({ error: '权限不足' });
}
next();
};
};
app.delete('/api/users/:id', authenticate, authorize(['admin']), deleteUser);6. Security Misconfiguration ⚙️
6. 安全配置错误 ⚙️
bash
undefinedbash
undefined✅ Security headers
✅ 设置安全响应头
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"],
scriptSrc: ["'self'"],
imgSrc: ["'self'", "data:", "https:"],
},
},
hsts: {
maxAge: 31536000,
includeSubDomains: true,
preload: true
}
}));
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"],
scriptSrc: ["'self'"],
imgSrc: ["'self'", "data:", "https:"],
},
},
hsts: {
maxAge: 31536000,
includeSubDomains: true,
preload: true
}
}));
✅ Disable unnecessary features
✅ 禁用不必要的功能
app.disable('x-powered-by'); # Hide Express
app.disable('x-powered-by'); # 隐藏Express框架标识
✅ Error handling (don't leak info)
✅ 错误处理(避免泄露敏感信息)
app.use((err, req, res, next) => {
console.error(err.stack); // Log full error
// Send generic message to client
res.status(500).json({
error: 'Internal server error',
// Don't send: err.stack or err.message
});
});
undefinedapp.use((err, req, res, next) => {
console.error(err.stack); // 记录完整错误信息
// 向客户端返回通用错误信息
res.status(500).json({
error: '服务器内部错误',
// 绝对不要返回:err.stack 或 err.message
});
});
undefined7. Cross-Site Scripting (XSS) 🎭
7. 跨站脚本攻击(XSS)🎭
javascript
// ❌ Vulnerable to XSS
app.get('/search', (req, res) => {
res.send(`Results for: ${req.query.q}`); // XSS!
});
// ✅ Sanitize output
const DOMPurify = require('isomorphic-dompurify');
app.get('/search', (req, res) => {
const clean = DOMPurify.sanitize(req.query.q);
res.send(`Results for: ${clean}`);
});
// ✅ React automatically escapes
<div>{userInput}</div> // Safe
// ❌ But dangerouslySetInnerHTML is dangerous
<div dangerouslySetInnerHTML={{__html: userInput}} /> // XSS!
// ✅ Content-Type headers
res.set('Content-Type', 'text/plain'); // Not HTML
res.set('X-Content-Type-Options', 'nosniff');javascript
// ❌ 存在XSS漏洞
app.get('/search', (req, res) => {
res.send(`搜索结果:${req.query.q}`); // XSS漏洞!
});
// ✅ 对输出内容进行清理
const DOMPurify = require('isomorphic-dompurify');
app.get('/search', (req, res) => {
const clean = DOMPurify.sanitize(req.query.q);
res.send(`搜索结果:${clean}`);
});
// ✅ React会自动转义内容
<div>{userInput}</div> // 安全写法
// ❌ 但dangerouslySetInnerHTML存在风险
<div dangerouslySetInnerHTML={{__html: userInput}} /> // XSS漏洞!
// ✅ 设置正确的Content-Type响应头
res.set('Content-Type', 'text/plain'); // 非HTML格式
res.set('X-Content-Type-Options', 'nosniff');8. Insecure Deserialization 📦
8. 不安全的反序列化 📦
javascript
// ❌ Dangerous deserialization
const userData = JSON.parse(req.body.data);
eval(userData.code); // Code execution!
// ✅ Validate before deserializing
const schema = Joi.object({
name: Joi.string().required(),
age: Joi.number().min(0).max(120)
});
const { error, value } = schema.validate(JSON.parse(req.body.data));
if (error) return res.status(400).json({ error });
// ✅ Never deserialize untrusted data into code
// Use JSON.parse() only, never eval() or Function()javascript
// ❌ 危险的反序列化操作
const userData = JSON.parse(req.body.data);
eval(userData.code); // 可能导致代码执行!
// ✅ 反序列化前先验证数据
const schema = Joi.object({
name: Joi.string().required(),
age: Joi.number().min(0).max(120)
});
const { error, value } = schema.validate(JSON.parse(req.body.data));
if (error) return res.status(400).json({ error });
// ✅ 绝对不要对不可信数据进行可执行代码的反序列化
// 仅使用JSON.parse(),绝对不要用eval()或Function()9. Components with Known Vulnerabilities 📚
9. 使用存在已知漏洞的组件 📚
bash
undefinedbash
undefined✅ Regular dependency checks
✅ 定期检查依赖包安全性
Add to package.json
添加到package.json
{
"scripts": {
"security": "npm audit && npm outdated",
"security:fix": "npm audit fix",
"preinstall": "npm audit"
}
}
{
"scripts": {
"security": "npm audit && npm outdated",
"security:fix": "npm audit fix",
"preinstall": "npm audit"
}
}
✅ Automated updates (GitHub)
✅ 自动更新(GitHub)
.github/dependabot.yml
.github/dependabot.yml
version: 2
updates:
- package-ecosystem: "npm" directory: "/" schedule: interval: "daily" open-pull-requests-limit: 10
undefinedversion: 2
updates:
- package-ecosystem: "npm" directory: "/" schedule: interval: "daily" open-pull-requests-limit: 10
undefined10. Insufficient Logging & Monitoring 📊
10. 日志与监控不足 📊
javascript
// ✅ Comprehensive logging
const winston = require('winston');
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' }),
],
});
// ✅ Log security events
function logSecurityEvent(event, user, details) {
logger.warn({
type: 'SECURITY',
event,
user: user?.id,
ip: user?.ip,
timestamp: new Date().toISOString(),
details
});
}
// Usage
logSecurityEvent('FAILED_LOGIN', req.user, {
attempts: failedAttempts,
ip: req.ip
});
logSecurityEvent('UNAUTHORIZED_ACCESS', req.user, {
resource: req.path,
method: req.method
});javascript
// ✅ 完善的日志记录
const winston = require('winston');
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' }),
],
});
// ✅ 记录安全事件
function logSecurityEvent(event, user, details) {
logger.warn({
type: 'SECURITY',
event,
user: user?.id,
ip: user?.ip,
timestamp: new Date().toISOString(),
details
});
}
// 使用示例
logSecurityEvent('FAILED_LOGIN', req.user, {
attempts: failedAttempts,
ip: req.ip
});
logSecurityEvent('UNAUTHORIZED_ACCESS', req.user, {
resource: req.path,
method: req.method
});🔐 Password Security
🔐 密码安全
javascript
// ✅ NEVER store plain text passwords!
const bcrypt = require('bcrypt');
// Hashing
async function hashPassword(password) {
const saltRounds = 12; // Higher = more secure but slower
return await bcrypt.hash(password, saltRounds);
}
// Verifying
async function verifyPassword(password, hash) {
return await bcrypt.compare(password, hash);
}
// ✅ Password reset flow
async function resetPassword(email) {
// 1. Generate secure token
const token = crypto.randomBytes(32).toString('hex');
// 2. Store hashed token with expiry
await storeResetToken(email, hashToken(token), Date.now() + 3600000);
// 3. Send unhashed token via email
await sendEmail(email, `Reset link: ${BASE_URL}/reset?token=${token}`);
}javascript
// ✅ 绝对不要存储明文密码!
const bcrypt = require('bcrypt');
// 密码哈希
async function hashPassword(password) {
const saltRounds = 12; // 数值越高越安全,但速度越慢
return await bcrypt.hash(password, saltRounds);
}
// 密码验证
async function verifyPassword(password, hash) {
return await bcrypt.compare(password, hash);
}
// ✅ 密码重置流程
async function resetPassword(email) {
// 1. 生成安全的重置令牌
const token = crypto.randomBytes(32).toString('hex');
// 2. 存储哈希后的令牌及过期时间
await storeResetToken(email, hashToken(token), Date.now() + 3600000);
// 3. 通过邮件发送未哈希的令牌
await sendEmail(email, `重置链接:${BASE_URL}/reset?token=${token}`);
}🚪 API Security
🚪 API安全
javascript
// ✅ API Security Checklist
const apiSecurity = {
// 1. Authentication
authentication: 'Bearer token (JWT)',
// 2. Rate limiting
rateLimit: {
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100 // requests per window
},
// 3. Input validation
validateInput: (data, schema) => {
return Joi.validate(data, schema);
},
// 4. CORS configuration
cors: {
origin: process.env.ALLOWED_ORIGINS?.split(',') || false,
credentials: true
},
// 5. API versioning
versioning: '/api/v1/',
// 6. Request size limit
bodyLimit: '10mb',
// 7. Timeout
timeout: 30000, // 30 seconds
// 8. HTTPS only
httpsOnly: true
};javascript
// ✅ API安全检查清单
const apiSecurity = {
// 1. 身份验证
authentication: 'Bearer token (JWT)',
// 2. 访问频率限制
rateLimit: {
windowMs: 15 * 60 * 1000, // 15分钟
max: 100 // 每个窗口最多100次请求
},
// 3. 输入验证
validateInput: (data, schema) => {
return Joi.validate(data, schema);
},
// 4. CORS配置
cors: {
origin: process.env.ALLOWED_ORIGINS?.split(',') || false,
credentials: true
},
// 5. API版本管理
versioning: '/api/v1/',
// 6. 请求大小限制
bodyLimit: '10mb',
// 7. 请求超时
timeout: 30000, // 30秒
// 8. 仅允许HTTPS访问
httpsOnly: true
};📋 Security Deployment Checklist
📋 部署前安全检查清单
markdown
undefinedmarkdown
undefinedPre-Deployment Security Checklist
部署前安全检查清单
Code Security
代码安全
- No hardcoded secrets
- All inputs validated
- SQL queries parameterized
- XSS protection enabled
- CSRF tokens implemented
- Authentication required
- Authorization checks present
- Rate limiting configured
- 无硬编码密钥
- 所有输入均已验证
- SQL查询使用参数化写法
- 已启用XSS防护
- 已实现CSRF令牌
- 已启用身份验证
- 已添加权限校验
- 已配置访问频率限制
Dependencies
依赖包
- shows 0 vulnerabilities
npm audit - All packages from trusted sources
- Lock file committed
- Licenses reviewed
- 显示0个漏洞
npm audit - 所有包均来自可信源
- 已提交锁文件
- 已审查许可证
Configuration
配置
- Environment variables used
- HTTPS enforced
- Security headers set
- CORS configured
- Error messages sanitized
- Debug mode disabled
- Source maps disabled in production
- 使用环境变量存储敏感配置
- 已强制使用HTTPS
- 已设置安全响应头
- 已正确配置CORS
- 错误信息已清理
- 已禁用调试模式
- 生产环境已禁用源映射
Data Protection
数据保护
- Passwords hashed (bcrypt)
- Sensitive data encrypted
- PII fields marked
- Data retention policy set
- Backups encrypted
- 密码已使用bcrypt哈希
- 敏感数据已加密
- 个人身份信息(PII)字段已标记
- 已设置数据保留策略
- 备份数据已加密
Infrastructure
基础设施
- Firewall rules configured
- Ports minimized
- SSH keys only (no passwords)
- Monitoring enabled
- Logging configured
- Incident response plan ready
undefined- 已配置防火墙规则
- 已最小化开放端口
- 仅允许SSH密钥登录(禁用密码登录)
- 已启用监控
- 已配置日志记录
- 已制定事件响应计划
undefined🚨 Incident Response Plan
🚨 安全事件响应计划
javascript
// security-incident.js
class SecurityIncident {
async respond(incident) {
// 1. Detect
this.log('INCIDENT_DETECTED', incident);
// 2. Contain
await this.blockIP(incident.sourceIP);
await this.disableAccount(incident.userId);
// 3. Investigate
const logs = await this.gatherLogs(incident);
// 4. Remediate
await this.patchVulnerability(incident.vulnerability);
// 5. Recover
await this.restoreService();
// 6. Lessons Learned
await this.documentIncident(incident);
// 7. Notify
await this.notifyStakeholders(incident);
}
}javascript
// security-incident.js
class SecurityIncident {
async respond(incident) {
// 1. 检测
this.log('INCIDENT_DETECTED', incident);
// 2. 遏制
await this.blockIP(incident.sourceIP);
await this.disableAccount(incident.userId);
// 3. 调查
const logs = await this.gatherLogs(incident);
// 4. 修复
await this.patchVulnerability(incident.vulnerability);
// 5. 恢复
await this.restoreService();
// 6. 经验总结
await this.documentIncident(incident);
// 7. 通知相关方
await this.notifyStakeholders(incident);
}
}💡 Security Quick Wins
💡 安全快速优化方案
bash
undefinedbash
undefined1. Add security.txt
1. 添加security.txt文件
echo "Contact: security@example.com" > public/.well-known/security.txt
echo "Contact: security@example.com" > public/.well-known/security.txt
2. Enable Dependabot
2. 启用Dependabot
gh api repos/:owner/:repo --method PUT --field security_and_analysis[secret_scanning][status]=enabled
gh api repos/:owner/:repo --method PUT --field security_and_analysis[secret_scanning][status]=enabled
3. Add pre-commit hooks
3. 添加提交前钩子
npm install --save-dev husky
npx husky add .husky/pre-commit "npm audit"
npm install --save-dev husky
npx husky add .husky/pre-commit "npm audit"
4. Security headers test
4. 测试安全响应头
curl -I https://yoursite.com | grep -i "strict-transport|content-security|x-frame"
Remember: Security is not a feature, it's a requirement! 🛡️curl -I https://yoursite.com | grep -i "strict-transport|content-security|x-frame"
记住:安全不是一个功能,而是一项必备要求! 🛡️