security

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Security Skill

安全技能

Version: 1.0 Source: Security Standards
Security must be built in from the start, not bolted on later. These standards apply to all code that handles user data, authentication, or external input.

版本: 1.0 来源: 安全标准
安全必须从一开始就融入设计,而不是事后追加。这些标准适用于所有处理用户数据、身份验证或外部输入的代码。

Core Principles

核心原则

  1. Security by Design — Build security in from the start, not as an afterthought
  2. Defense in Depth — Multiple layers of security; no single point of failure
  3. Least Privilege — Grant minimum access required for the task
  4. Fail Securely — Errors should not expose vulnerabilities or sensitive data
  5. Zero Trust — Never trust input, always verify
  6. Assume Breach — Design as if attackers will get in; minimize blast radius

  1. 设计安全 — 从一开始就融入安全设计,而非事后补充
  2. 深度防御 — 多层安全防护,无单点故障
  3. 最小权限 — 仅授予完成任务所需的最低权限
  4. 安全失败 — 错误不应暴露漏洞或敏感数据
  5. 零信任 — 绝不信任任何输入,始终进行验证
  6. 假设已被攻破 — 按照攻击者已入侵的场景进行设计,最小化影响范围

OWASP Top 10 (2021)

OWASP Top 10(2021版)

Critical vulnerabilities to prevent:
#VulnerabilityPrevention
1Broken Access ControlCheck authorization on every request
2Cryptographic FailuresUse strong encryption, never roll your own
3InjectionParameterized queries, input validation
4Insecure DesignThreat modeling, secure architecture
5Security MisconfigurationSecure defaults, proper error handling
6Vulnerable ComponentsKeep dependencies updated, audit regularly
7Auth FailuresStrong auth, MFA, secure session management
8Integrity FailuresVerify code/data integrity, sign releases
9Logging FailuresLog security events, protect log data
10SSRFValidate and allowlist server-side URLs

需防范的关键漏洞:
序号漏洞类型防范措施
1访问控制失效对每个请求进行授权检查
2加密失败使用强加密算法,绝不自行实现加密
3注入攻击使用参数化查询、输入验证
4不安全设计威胁建模、安全架构设计
5安全配置错误使用安全默认配置、正确处理错误
6易受攻击的组件定期更新依赖、进行审计
7身份验证失败强身份验证、多因素认证(MFA)、安全会话管理
8完整性失败验证代码/数据完整性、对发布版本签名
9日志记录失败记录安全事件、保护日志数据
10SSRF(服务器端请求伪造)验证并使用白名单限制服务器端URL

Input Validation

输入验证

The Golden Rule

黄金法则

Never trust user input. All input is potentially malicious.
绝不信任用户输入。所有输入都可能是恶意的。

Validation Strategy

验证策略

1. Validate → 2. Sanitize → 3. Encode (for output context)
1. 验证 → 2. 清理 → 3. 编码(根据输出场景)

SQL Injection Prevention

SQL注入防范

python
undefined
python
undefined

❌ NEVER - String concatenation

❌ 绝对不要 - 字符串拼接

query = f"SELECT * FROM users WHERE id = {user_id}"
query = f"SELECT * FROM users WHERE id = {user_id}"

✅ ALWAYS - Parameterized queries

✅ 务必使用 - 参数化查询

cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))
cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))

✅ ALWAYS - ORM with parameters

✅ 务必使用 - 带参数的ORM

User.objects.filter(id=user_id)
undefined
User.objects.filter(id=user_id)
undefined

XSS Prevention

XSS攻击防范

javascript
// ❌ NEVER - Direct HTML insertion
element.innerHTML = userInput;
document.write(userInput);

// ✅ ALWAYS - Text content (auto-escapes)
element.textContent = userInput;

// ✅ ALWAYS - Template literals with escaping
const escaped = escapeHtml(userInput);
javascript
// ❌ 绝对不要 - 直接插入HTML
element.innerHTML = userInput;
document.write(userInput);

// ✅ 务必使用 - 文本内容(自动转义)
element.textContent = userInput;

// ✅ 务必使用 - 带转义的模板字符串
const escaped = escapeHtml(userInput);

Command Injection Prevention

命令注入防范

python
undefined
python
undefined

❌ NEVER - Shell execution with user input

❌ 绝对不要 - 使用用户输入执行Shell命令

os.system(f"ls {user_path}") subprocess.call(f"convert {filename}", shell=True)
os.system(f"ls {user_path}") subprocess.call(f"convert {filename}", shell=True)

✅ ALWAYS - Argument arrays (no shell)

✅ 务必使用 - 参数数组(不通过Shell)

subprocess.run(["ls", user_path], shell=False) subprocess.run(["convert", filename], shell=False)
undefined
subprocess.run(["ls", user_path], shell=False) subprocess.run(["convert", filename], shell=False)
undefined

Input Validation Patterns

输入验证示例

python
import re

def validate_email(email: str) -> bool:
    """Validate email format."""
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return bool(re.match(pattern, email)) and len(email) <= 254

def validate_username(username: str) -> bool:
    """Validate username: alphanumeric, 3-30 chars."""
    pattern = r'^[a-zA-Z0-9_]{3,30}$'
    return bool(re.match(pattern, username))

def validate_url(url: str, allowed_domains: list[str]) -> bool:
    """Validate URL against allowlist."""
    from urllib.parse import urlparse
    parsed = urlparse(url)
    return (
        parsed.scheme in ('http', 'https') and
        parsed.netloc in allowed_domains
    )

python
import re

def validate_email(email: str) -> bool:
    """验证邮箱格式。"""
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return bool(re.match(pattern, email)) and len(email) <= 254

def validate_username(username: str) -> bool:
    """验证用户名:仅允许字母数字和下划线,长度3-30位。"""
    pattern = r'^[a-zA-Z0-9_]{3,30}$'
    return bool(re.match(pattern, username))

def validate_url(url: str, allowed_domains: list[str]) -> bool:
    """根据白名单验证URL。"""
    from urllib.parse import urlparse
    parsed = urlparse(url)
    return (
        parsed.scheme in ('http', 'https') and
        parsed.netloc in allowed_domains
    )

Authentication & Authorization

身份验证与授权

Password Requirements

密码要求

RequirementMinimum
Length12 characters
ComplexityNot required if length met
Common passwordsBlock top 10,000
Breached passwordsCheck against HaveIBeenPwned
要求最小值
长度12个字符
复杂度满足长度要求则无需强制复杂度
常见密码阻止前10000个最常见密码
泄露密码对照HaveIBeenPwned数据库检查

Password Storage

密码存储

python
undefined
python
undefined

✅ Use bcrypt, Argon2, or scrypt

✅ 使用bcrypt、Argon2或scrypt

import bcrypt
def hash_password(password: str) -> bytes: """Hash password with bcrypt.""" salt = bcrypt.gensalt(rounds=12) return bcrypt.hashpw(password.encode(), salt)
def verify_password(password: str, hashed: bytes) -> bool: """Verify password against hash.""" return bcrypt.checkpw(password.encode(), hashed)

**NEVER:**
- Store passwords in plain text
- Use MD5 or SHA1 for passwords
- Roll your own hashing
import bcrypt
def hash_password(password: str) -> bytes: """使用bcrypt哈希密码。""" salt = bcrypt.gensalt(rounds=12) return bcrypt.hashpw(password.encode(), salt)
def verify_password(password: str, hashed: bytes) -> bool: """验证密码与哈希值是否匹配。""" return bcrypt.checkpw(password.encode(), hashed)

**绝对不要:**
- 明文存储密码
- 使用MD5或SHA1存储密码
- 自行实现哈希算法

Session Management

会话管理

python
undefined
python
undefined

Session security settings

会话安全配置

SESSION_CONFIG = { "cookie_secure": True, # HTTPS only "cookie_httponly": True, # No JavaScript access "cookie_samesite": "Lax", # CSRF protection "session_lifetime": 3600, # 1 hour max "regenerate_on_login": True # Prevent session fixation }
undefined
SESSION_CONFIG = { "cookie_secure": True, # 仅通过HTTPS传输 "cookie_httponly": True, # 禁止JavaScript访问 "cookie_samesite": "Lax", # CSRF防护 "session_lifetime": 3600, # 最长1小时 "regenerate_on_login": True # 防止会话固定攻击 }
undefined

Authorization Checks

授权检查

python
undefined
python
undefined

✅ Check authorization on EVERY request

✅ 对每个请求都进行授权检查

def get_document(user, document_id): document = Document.get(document_id)
# Always verify ownership/access
if document.owner_id != user.id and not user.is_admin:
    raise PermissionError("Access denied")

return document

---
def get_document(user, document_id): document = Document.get(document_id)
# 始终验证所有权/访问权限
if document.owner_id != user.id and not user.is_admin:
    raise PermissionError("访问被拒绝")

return document

---

Data Protection

数据保护

Encryption Requirements

加密要求

Data TypeAt RestIn Transit
PasswordsHashed (bcrypt/Argon2)TLS 1.2+
PII (name, email, address)AES-256TLS 1.2+
Payment dataAES-256 + PCI DSSTLS 1.3
Health dataAES-256 + HIPAATLS 1.3
Session tokensN/ATLS 1.2+
API keysAES-256TLS 1.2+
数据类型静态数据传输中数据
密码哈希处理(bcrypt/Argon2)TLS 1.2+
个人身份信息(姓名、邮箱、地址)AES-256加密TLS 1.2+
支付数据AES-256加密 + PCI DSS合规TLS 1.3
健康数据AES-256加密 + HIPAA合规TLS 1.3
会话令牌不适用TLS 1.2+
API密钥AES-256加密TLS 1.2+

Sensitive Data Handling

敏感数据处理

python
undefined
python
undefined

✅ Mask sensitive data in logs

✅ 在日志中脱敏敏感数据

def log_user_action(user, action, data): safe_data = { "user_id": user.id, "email": mask_email(user.email), # j***@example.com "action": action, # Never log: passwords, tokens, full credit cards } logger.info("User action", extra=safe_data)
def mask_email(email: str) -> str: """Mask email for logging.""" local, domain = email.split("@") return f"{local[0]}***@{domain}"
def mask_card(card: str) -> str: """Show only last 4 digits.""" return f"--****-{card[-4:]}"
undefined
def log_user_action(user, action, data): safe_data = { "user_id": user.id, "email": mask_email(user.email), # j***@example.com "action": action, # 绝对不要记录:密码、令牌、完整信用卡号 } logger.info("用户操作", extra=safe_data)
def mask_email(email: str) -> str: """对邮箱进行脱敏以便记录。""" local, domain = email.split("@") return f"{local[0]}***@{domain}"
def mask_card(card: str) -> str: """仅显示最后4位数字。""" return f"--****-{card[-4:]}"
undefined

Data Retention

数据保留

  • Delete data when no longer needed
  • Implement data expiration policies
  • Provide user data export/deletion (GDPR)
  • Securely wipe deleted data (not just mark deleted)

  • 不再需要时删除数据
  • 实施数据过期策略
  • 提供用户数据导出/删除功能(符合GDPR)
  • 安全擦除已删除数据(而非仅标记为删除)

API Security

API安全

Rate Limiting

速率限制

python
undefined
python
undefined

Implement rate limiting per endpoint

为每个端点实现速率限制

RATE_LIMITS = { "/api/login": "5/minute", # Prevent brute force "/api/register": "3/minute", # Prevent spam "/api/password-reset": "3/hour", "/api/*": "100/minute", # General limit }
undefined
RATE_LIMITS = { "/api/login": "5/minute", # 防止暴力破解 "/api/register": "3/minute", # 防止垃圾注册 "/api/password-reset": "3/hour", "/api/*": "100/minute", # 通用限制 }
undefined

CORS Configuration

CORS配置

python
undefined
python
undefined

✅ Specific origins only

✅ 仅允许特定源

CORS_CONFIG = { "origins": [ "https://app.example.com", "https://admin.example.com", ], "methods": ["GET", "POST", "PUT", "DELETE"], "allow_credentials": True, "max_age": 3600, }
CORS_CONFIG = { "origins": [ "https://app.example.com", "https://admin.example.com", ], "methods": ["GET", "POST", "PUT", "DELETE"], "allow_credentials": True, "max_age": 3600, }

❌ NEVER in production

❌ 生产环境绝对不要这样配置

CORS_CONFIG = { "origins": "*", # Allows any origin! }
undefined
CORS_CONFIG = { "origins": "*", # 允许任何源! }
undefined

API Response Security

API响应安全

python
undefined
python
undefined

❌ Never expose internal errors

❌ 绝对不要暴露内部错误

def handle_error(error): # Don't send: stack traces, SQL errors, file paths return {"error": "An error occurred"}, 500
def handle_error(error): # 不要返回:堆栈跟踪、SQL错误、文件路径 return {"error": "发生错误"}, 500

✅ Log details, return generic message

✅ 记录详细信息,返回通用提示

def handle_error(error): logger.error(f"Internal error: {error}", exc_info=True) return {"error": "Internal server error"}, 500
undefined
def handle_error(error): logger.error(f"内部错误:{error}", exc_info=True) return {"error": "内部服务器错误"}, 500
undefined

Security Headers

安全头

python
SECURITY_HEADERS = {
    "Strict-Transport-Security": "max-age=31536000; includeSubDomains",
    "X-Content-Type-Options": "nosniff",
    "X-Frame-Options": "DENY",
    "X-XSS-Protection": "1; mode=block",
    "Content-Security-Policy": "default-src 'self'",
    "Referrer-Policy": "strict-origin-when-cross-origin",
}

python
SECURITY_HEADERS = {
    "Strict-Transport-Security": "max-age=31536000; includeSubDomains",
    "X-Content-Type-Options": "nosniff",
    "X-Frame-Options": "DENY",
    "X-XSS-Protection": "1; mode=block",
    "Content-Security-Policy": "default-src 'self'",
    "Referrer-Policy": "strict-origin-when-cross-origin",
}

Secrets Management

密钥管理

Environment Variables

环境变量

bash
undefined
bash
undefined

✅ Store secrets in environment

✅ 将密钥存储在环境变量中

export DATABASE_URL="postgres://..." export API_KEY="..." export JWT_SECRET="..."
export DATABASE_URL="postgres://..." export API_KEY="..." export JWT_SECRET="..."

❌ NEVER commit secrets to code

❌ 绝对不要将密钥提交到代码中

DATABASE_URL = "postgres://user:password@host/db" # In code!
undefined
DATABASE_URL = "postgres://user:password@host/db" # 写在代码里!
undefined

Secret Requirements

密钥要求

Secret TypeRotation PeriodStorage
API keys90 daysVault/env vars
Database passwords90 daysVault/env vars
JWT secrets30 daysVault/env vars
Encryption keys1 yearHSM/KMS
User passwordsOn compromiseHashed in DB
密钥类型轮换周期存储方式
API密钥90天密钥管理系统/环境变量
数据库密码90天密钥管理系统/环境变量
JWT密钥30天密钥管理系统/环境变量
加密密钥1年硬件安全模块/密钥管理服务
用户密码泄露时轮换数据库中哈希存储

.gitignore

.gitignore

gitignore
undefined
gitignore
undefined

Secrets - NEVER commit

密钥 - 绝对不要提交

.env .env.local .env.*.local *.pem .key credentials.json secrets.yaml config/secrets/

---
.env .env.local .env.*.local *.pem .key credentials.json secrets.yaml config/secrets/

---

File Upload Security

文件上传安全

Validation Checklist

验证清单

python
def validate_upload(file) -> bool:
    """Validate uploaded file."""

    # 1. Check file size
    MAX_SIZE = 10 * 1024 * 1024  # 10MB
    if file.size > MAX_SIZE:
        raise ValueError("File too large")

    # 2. Check extension against allowlist
    ALLOWED_EXTENSIONS = {'.jpg', '.jpeg', '.png', '.pdf'}
    ext = Path(file.name).suffix.lower()
    if ext not in ALLOWED_EXTENSIONS:
        raise ValueError("File type not allowed")

    # 3. Verify magic bytes (don't trust extension)
    magic_bytes = file.read(8)
    file.seek(0)
    if not is_valid_magic(magic_bytes, ext):
        raise ValueError("File content doesn't match extension")

    # 4. Generate safe filename
    safe_name = generate_safe_filename(file.name)

    # 5. Store outside web root
    storage_path = UPLOAD_DIR / safe_name  # Not in /public!

    return True
python
def validate_upload(file) -> bool:
    """验证上传的文件。"""

    # 1. 检查文件大小
    MAX_SIZE = 10 * 1024 * 1024  # 10MB
    if file.size > MAX_SIZE:
        raise ValueError("文件过大")

    # 2. 检查扩展名是否在白名单中
    ALLOWED_EXTENSIONS = {'.jpg', '.jpeg', '.png', '.pdf'}
    ext = Path(file.name).suffix.lower()
    if ext not in ALLOWED_EXTENSIONS:
        raise ValueError("不允许的文件类型")

    # 3. 验证魔术字节(不要信任扩展名)
    magic_bytes = file.read(8)
    file.seek(0)
    if not is_valid_magic(magic_bytes, ext):
        raise ValueError("文件内容与扩展名不匹配")

    # 4. 生成安全文件名
    safe_name = generate_safe_filename(file.name)

    # 5. 存储在Web根目录之外
    storage_path = UPLOAD_DIR / safe_name  # 不要放在/public目录下!

    return True

Safe Filename Generation

安全文件名生成

python
import uuid
import re
from pathlib import Path

def generate_safe_filename(original: str) -> str:
    """Generate safe filename, preserving extension."""
    ext = Path(original).suffix.lower()
    # Use UUID, not original filename
    return f"{uuid.uuid4()}{ext}"

python
import uuid
import re
from pathlib import Path

def generate_safe_filename(original: str) -> str:
    """生成安全文件名,保留扩展名。"""
    ext = Path(original).suffix.lower()
    # 使用UUID,而非原始文件名
    return f"{uuid.uuid4()}{ext}"

Logging & Monitoring

日志与监控

What to Log

需要记录的内容

python
undefined
python
undefined

✅ Log these security events

✅ 记录以下安全事件

SECURITY_EVENTS = [ "login_success", "login_failure", "logout", "password_change", "password_reset_request", "permission_denied", "invalid_token", "rate_limit_exceeded", "suspicious_input", "admin_action", ]
undefined
SECURITY_EVENTS = [ "login_success", "login_failure", "logout", "password_change", "password_reset_request", "permission_denied", "invalid_token", "rate_limit_exceeded", "suspicious_input", "admin_action", ]
undefined

What NOT to Log

绝对不要记录的内容

python
undefined
python
undefined

❌ NEVER log these

❌ 绝对不要记录这些内容

NEVER_LOG = [ "password", "password_hash", "credit_card", "ssn", "api_key", "session_token", "jwt_token", "private_key", ]
undefined
NEVER_LOG = [ "password", "password_hash", "credit_card", "ssn", "api_key", "session_token", "jwt_token", "private_key", ]
undefined

Structured Security Logging

结构化安全日志

python
def log_security_event(event_type: str, user_id: str, details: dict):
    """Log security event with context."""
    logger.info("security_event", extra={
        "event_type": event_type,
        "user_id": user_id,
        "timestamp": datetime.utcnow().isoformat(),
        "ip_address": get_client_ip(),
        "user_agent": get_user_agent(),
        **sanitize_details(details),
    })

python
def log_security_event(event_type: str, user_id: str, details: dict):
    """记录带上下文的安全事件。"""
    logger.info("security_event", extra={
        "event_type": event_type,
        "user_id": user_id,
        "timestamp": datetime.utcnow().isoformat(),
        "ip_address": get_client_ip(),
        "user_agent": get_user_agent(),
        **sanitize_details(details),
    })

Security Checklist

安全检查清单

Before Every Release

每次发布前检查

  • No secrets in code or version control
  • All user input validated and sanitized
  • SQL queries use parameterized statements
  • Authentication on all protected endpoints
  • Authorization checks on all resources
  • HTTPS enforced (no HTTP)
  • Security headers configured
  • Rate limiting in place
  • Error messages don't leak sensitive info
  • Dependencies updated and audited
  • File uploads validated and stored safely
  • Logging captures security events
  • CORS configured restrictively
  • 代码或版本控制中无密钥
  • 所有用户输入均已验证和清理
  • SQL查询使用参数化语句
  • 所有受保护端点均有身份验证
  • 所有资源均有授权检查
  • 强制使用HTTPS(禁止HTTP)
  • 已配置安全头
  • 已启用速率限制
  • 错误信息未泄露敏感信息
  • 依赖已更新并审计
  • 文件上传已验证并安全存储
  • 日志已捕获安全事件
  • CORS配置严格

Code Review Security Focus

代码评审安全重点

  • Input validation at all entry points
  • Output encoding for XSS prevention
  • Access control checks present
  • No hardcoded secrets
  • Proper error handling (no stack traces)
  • Secure defaults used
  • Third-party libraries are necessary and trusted

  • 所有入口点均有输入验证
  • 输出编码以防范XSS攻击
  • 存在访问控制检查
  • 无硬编码密钥
  • 正确处理错误(无堆栈跟踪)
  • 使用安全默认配置
  • 第三方库必要且可信

References

参考资料

  • references/owasp-top-10.md
    — Detailed OWASP vulnerability guide
  • references/input-validation.md
    — Complete input validation patterns
  • references/auth-patterns.md
    — Authentication and authorization patterns
  • references/owasp-top-10.md
    — OWASP漏洞详细指南
  • references/input-validation.md
    — 完整输入验证模式
  • references/auth-patterns.md
    — 身份验证与授权模式

Assets

资源

  • assets/security-checklist.md
    — Pre-release security checklist
  • assets/threat-model-template.md
    — Threat modeling template
  • assets/security-checklist.md
    — 发布前安全检查清单
  • assets/threat-model-template.md
    — 威胁建模模板

Scripts

脚本

  • scripts/scan_secrets.py
    — Scan code for accidentally committed secrets
  • scripts/check_dependencies.py
    — Check dependencies for known vulnerabilities
  • scripts/scan_secrets.py
    — 扫描代码中意外提交的密钥
  • scripts/check_dependencies.py
    — 检查依赖项的已知漏洞