mcpField
S
security

security

github.com/alexanderstephenthompson安全36 次安装
代码仓库

关于 security

面向处理用户数据、身份验证或外部输入的 Agent 与开发者的安全规范技能,提供安全编码指导、构建与审查清单、可检查规则,以及密钥和依赖项检查脚本。

主要功能

  1. 01输入验证与注入防护
  2. 02身份验证与授权指导
  3. 03数据保护与密钥处理
  4. 04API、上传与日志防护
  5. 05构建和代码审查清单
  6. 06规则及安全扫描脚本

适用场景

  1. 01在实现前规划安全措施
  2. 02审查代码中的安全违规
  3. 03检查代码库中的密钥与易受攻击依赖项

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/alexanderstephenthompson/claude-hub --skill security

安装后在 Claude Code 中输入/security确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

assets/
threat-model-template.md
security-checklist.md
references/
owasp-top-10.md
input-validation.md
auth-patterns.md
scripts/
scan_secrets.py
check_dependencies.py

详细介绍

安全技能

版本: 1.0 来源: 安全标准

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

问题

AI Agent 默认会优先让代码运行起来,而不是确保代码安全。如果没有明确的安全标准,每次会话都会选择最省事的方式——用字符串拼接构造查询、为图方便硬编码机密信息、为求速度授予宽泛权限。这些选择并非出于恶意;当提示词中没有安全要求时,它们只是阻力最小的做法。这些标准将安全模式设为默认路径。

使用方式

  • 构建者: 在编写任何涉及用户输入、身份验证或外部服务的代码之前,请阅读 ## Builder Checklist。必须在设计中融入安全,而不是事后打补丁。
  • 重构者: 使用 ## Enforced Rules 查找安全违规项。阅读说明性章节,了解修复指导。
  • 两者: 说明性章节是权威标准。检查清单和规则表是对相同内容的精简呈现。

核心原则

  1. 安全设计 — 从一开始就融入安全,而不是事后考虑
  2. 纵深防御 — 采用多层安全措施,不依赖单一防护点
  3. 最小权限 — 仅授予完成任务所需的最低访问权限
  4. 安全失败 — 错误不应暴露漏洞或敏感数据
  5. 零信任 — 绝不信任输入,始终进行验证
  6. 假设已遭入侵 — 以攻击者会入侵系统为前提进行设计,将影响范围降至最低

OWASP Top 10(2021)

需要防范的严重漏洞:

#漏洞防范措施
1访问控制失效对每个请求检查授权
2加密失效使用强加密,绝不自行实现加密方案
3注入使用参数化查询、验证输入
4不安全的设计进行威胁建模、采用安全架构
5安全配置错误使用安全默认设置、妥善处理错误
6易受攻击的组件保持依赖项更新、定期审计
7身份验证失效使用强身份验证、MFA 和安全的会话管理
8完整性失效验证代码和数据完整性、对发布版本签名
9日志记录失效记录安全事件、保护日志数据
10SSRF验证并通过允许列表限制服务端 URL

输入验证

黄金法则

绝不信任用户输入。 所有输入都可能是恶意的。

验证策略
1. Validate → 2. Sanitize → 3. Encode (for output context)
SQL 注入防范
# ❌ NEVER - String concatenation
query = f"SELECT * FROM users WHERE id = {user_id}"

# ✅ ALWAYS - Parameterized queries
cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))

# ✅ ALWAYS - ORM with parameters
User.objects.filter(id=user_id)
XSS 防范
// ❌ 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);
命令注入防范
# ❌ NEVER - Shell execution with user input
os.system(f"ls {user_path}")
subprocess.call(f"convert {filename}", shell=True)

# ✅ ALWAYS - Argument arrays (no shell)
subprocess.run(["ls", user_path], shell=False)
subprocess.run(["convert", filename], shell=False)
输入验证模式
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
    )

身份验证与授权

密码要求
要求最低标准
长度12 个字符
复杂度达到长度要求后无需额外要求
常见密码禁用排名前 10,000 的常见密码
已泄露密码使用 HaveIBeenPwned 检查
密码存储
# ✅ Use bcrypt, Argon2, or 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)

绝不要:

  • 以明文存储密码
  • 使用 MD5 或 SHA1 处理密码
  • 自行实现哈希算法
会话管理
# 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
}
授权检查
# ✅ 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

数据保护

加密要求
数据类型静态存储传输中
密码哈希(bcrypt/Argon2)TLS 1.2+
PII(姓名、电子邮件、地址)AES-256TLS 1.2+
支付数据AES-256 + PCI DSSTLS 1.3
健康数据AES-256 + HIPAATLS 1.3
会话令牌不适用TLS 1.2+
API 密钥AES-256TLS 1.2+
敏感数据处理
# ✅ 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:]}"
数据保留
  • 不再需要时删除数据
  • 实施数据过期策略
  • 提供用户数据导出/删除功能(GDPR)
  • 安全擦除已删除的数据(而不仅仅是标记为已删除)

API 安全

速率限制
# 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
}
CORS 配置
# ✅ 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,
}

# ❌ NEVER in production
CORS_CONFIG = {
    "origins": "*",  # Allows any origin!
}
API 响应安全
# ❌ Never expose internal errors
def handle_error(error):
    # Don't send: stack traces, SQL errors, file paths
    return {"error": "An error occurred"}, 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
安全标头
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",
}

密钥管理

环境变量
# ✅ Store secrets in environment
export DATABASE_URL="postgres://..."
export API_KEY="..."
export JWT_SECRET="..."

# ❌ NEVER commit secrets to code
DATABASE_URL = "postgres://user:password@host/db"  # In code!
密钥要求
密钥类型轮换周期存储方式
API 密钥90 天Vault/环境变量
数据库密码90 天Vault/环境变量
JWT 密钥30 天Vault/环境变量
加密密钥1 年HSM/KMS
用户密码泄露时在数据库中哈希存储
.gitignore
# Secrets - NEVER commit
.env
.env.local
.env.*.local
*.pem
*.key
credentials.json
secrets.yaml
config/secrets/*

文件上传安全

验证清单
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
安全文件名生成
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}"

日志记录与监控

应记录的内容
# ✅ 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",
]
不应记录的内容
# ❌ NEVER log these
NEVER_LOG = [
    "password",
    "password_hash",
    "credit_card",
    "ssn",
    "api_key",
    "session_token",
    "jwt_token",
    "private_key",
]
结构化安全日志
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),
    })

构建者清单

在编写处理用户数据、身份验证或外部输入的代码之前,请根据这些约束核对你的计划。构建者在编写代码前阅读本节;重构者则使用“强制规则”表和完整说明。

每次发布前
  • 代码或版本控制中没有密钥
  • 所有用户输入均已验证和清理
  • SQL 查询使用参数化语句
  • 所有受保护的端点均已启用身份验证
  • 所有资源均已进行授权检查
  • 强制使用 HTTPS(不使用 HTTP)
  • 已配置安全标头
  • 已启用速率限制
  • 错误消息不会泄露敏感信息
  • 依赖项已更新并经过审计
  • 文件上传已验证并安全存储
  • 日志记录了安全事件
  • CORS 配置严格
代码审查安全重点
  • 所有入口点均进行输入验证
  • 对输出进行编码以防止 XSS
  • 已进行访问控制检查
  • 没有硬编码密钥
  • 错误处理得当(不显示堆栈跟踪)
  • 使用安全的默认设置
  • 第三方库确有必要且可信

强制规则

这些规则由 check.js(clean-team)进行确定性检查。更新这些标准时,请同步更新对应的 check.js 规则,反之亦然。

规则 ID严重性检查内容
no-document-write错误使用 document.write()(存在 DOM 注入风险)
no-hardcoded-secrets错误字符串字面量中的 API 密钥、令牌、密码
no-innerHTML警告赋值给 .innerHTML(存在 XSS 风险)

参考资料

  • references/owasp-top-10.md — OWASP 漏洞详细指南
  • references/input-validation.md — 完整的输入验证模式
  • references/auth-patterns.md — 身份验证和授权模式

资源文件

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

脚本

  • scripts/scan_secrets.py — 扫描代码中意外提交的密钥
  • scripts/check_dependencies.py — 检查依赖项是否存在已知漏洞

评论

支持 Markdown