mcpField
V
vibe-security

vibe-security

github.com/nickcrew安全6283 次安装18 周前更新
代码仓库

关于 vibe-security

vibe-security 是面向 Web 应用开发与审查的安全编码指南。它按访问控制、XSS、CSRF 和 SSRF 等攻击面组织检查项,并提供验证步骤与防护实践。

主要功能

  1. 01识别相关 Web 攻击面
  2. 02审查访问控制与授权
  3. 03检查 XSS 和 CSRF 防护
  4. 04采用安全重定向与密码实践
  5. 05验证响应头并测试安全修复

适用场景

  1. 01审查接收用户输入的 API 路由
  2. 02实现身份验证与会话控制
  3. 03评估文件上传和重定向处理
  4. 04检查安全响应头和 CSP 策略

安装

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

$npx skills add https://github.com/nickcrew/claude-cortex --skill vibe-security

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

详细介绍

Web 应用安全编码指南

Web 应用的全面安全编码实践。从漏洞猎手的视角审视代码,在尽可能确保应用安全的同时,不影响功能。

适用场景

  • 编写新的 Web 应用端点或 API 路由
  • 审查涉及用户输入、身份验证或文件上传的 PR
  • 实现身份验证、授权或会话管理
  • 处理文件上传、重定向或基于 URL 的功能
  • 添加安全标头或 CSP 策略
  • 避免用于基础设施/网络安全——请改用 defense-in-depth

工作流

步骤 1:识别攻击面

确定待审查代码涉及哪些安全领域:

领域触发条件
访问控制任何需要身份验证的端点、多租户数据
XSS在 HTML、JavaScript 或 CSS 中渲染用户输入
CSRF会更改状态的端点(POST、PUT、DELETE)
SSRF服务端向用户提供的 URL 发出请求
SQL 注入动态数据库查询
文件上传任何文件上传功能
路径遍历文件路径中的用户输入
步骤 2:应用特定领域的检查

使用下方相关章节作为各个已识别领域的检查清单。

步骤 3:验证安全标头

确保所有响应都包含必需的标头(参见安全标头检查清单)。

步骤 4:审查并测试
  • 验证修复不会破坏功能
  • 使用各章节列出的绕过技术进行测试
  • 如有可用的自动化安全扫描工具,请运行扫描

核心原则:

  • 深度防御:切勿依赖单一安全控制
  • 安全失败:发生故障时应默认拒绝访问
  • 最小权限:仅授予所需的最低权限
  • 输入验证:切勿信任用户输入,务必在服务端验证所有输入
  • 输出编码:根据数据渲染的上下文进行适当编码

访问控制问题

当用户能够访问超出其预期权限的资源或执行相应操作时,就会产生访问控制漏洞。

核心要求

对于每个需要身份验证的数据项和操作:

  1. 用户级授权

    • 每个用户只能访问或修改自己的数据
    • 任何用户都不应访问其他用户或组织的数据
    • 始终在数据层验证所有权,而不只是路由层
  2. 使用 UUID 代替连续 ID

    • 使用 UUIDv4 或类似的不可猜测标识符
    • 例外:只有在用户明确要求时,才使用连续 ID
  3. 账号生命周期处理

    • 当用户被移出组织时:立即撤销所有访问令牌和会话
    • 当账号被删除/停用时:使所有活动会话和 API 密钥失效
    • 实现令牌撤销列表,或采用带刷新机制的短期令牌
授权检查清单
  • 每次请求都验证用户是否拥有该资源(不要信任客户端数据)
  • 检查多租户应用中的组织成员资格
  • 针对基于角色的操作,验证角色权限
  • 权限发生任何变化后,重新验证权限
  • 检查父资源所有权(例如,访问评论时,验证用户是否拥有其所属的帖子)
应避免的常见陷阱
  • IDOR(不安全的直接对象引用):始终验证请求用户是否有权访问请求中的资源 ID
  • 权限提升:在服务端验证角色变更;切勿信任客户端提供的角色信息
  • 水平越权:权限级别相同的用户 A 访问用户 B 的资源
  • 垂直越权:普通用户访问管理员功能
  • 批量赋值:筛选用户可更新的字段;不要盲目接受请求正文中的所有字段
实现模式
# Pseudocode for secure resource access
function getResource(resourceId, currentUser):
    resource = database.find(resourceId)
    
    if resource is null:
        return 404  # Don't reveal if resource exists
    
    if resource.ownerId != currentUser.id:
        if not currentUser.hasOrgAccess(resource.orgId):
            return 404  # Return 404, not 403, to prevent enumeration
    
    return resource

客户端漏洞

跨站脚本攻击(XSS)

所有用户可直接或间接控制的输入都必须经过净化,以防止 XSS。

需要防护的输入来源

直接输入:

  • 表单字段(电子邮件、姓名、简介、评论等)
  • 搜索查询
  • 上传时的文件名
  • 富文本编辑器 / 所见即所得内容

间接输入:

  • URL 参数和查询字符串
  • URL 片段(哈希值)
  • 应用中使用的 HTTP 标头(如果会显示 Referer、User-Agent)
  • 向用户显示的第三方 API 数据
  • WebSocket 消息
  • 来自 iframe 的 postMessage 数据
  • 如果会渲染 LocalStorage/SessionStorage 值

经常被忽略的输入:

  • 会反映用户输入的错误消息
  • 接受 HTML 的 PDF / 文档生成器
  • 包含用户数据的电子邮件模板
  • 管理面板中的日志查看器
  • 渲染为 HTML 的 JSON 响应
  • SVG 文件上传(可能包含 JavaScript)
  • Markdown 渲染(如果允许 HTML)
防护策略
  1. 输出编码(针对具体上下文)

    • HTML 上下文:对 HTML 实体进行编码(< → &lt;)
    • JavaScript 上下文:进行 JavaScript 转义
    • URL 上下文:进行 URL 编码
    • CSS 上下文:进行 CSS 转义
    • 使用框架内置的转义功能(React 的 JSX、Vue 的 {{ }} 等)
  2. 内容安全策略(CSP)

    Content-Security-Policy: 
      default-src 'self';
      script-src 'self';
      style-src 'self' 'unsafe-inline';
      img-src 'self' data: https:;
      font-src 'self';
      connect-src 'self' https://api.yourdomain.com;
      frame-ancestors 'none';
      base-uri 'self';
      form-action 'self';
    
    • 避免在脚本中使用 'unsafe-inline' 和 'unsafe-eval'
    • 必要时,为内联脚本使用 nonce 或哈希
    • 报告违规行为:report-uri /csp-report
  3. 输入净化

    • 使用成熟的库(HTML 可使用 DOMPurify)
    • 为富文本设置允许的标签 / 属性白名单
    • 移除或编码危险模式
  4. 其他标头

    • X-Content-Type-Options: nosniff
    • X-Frame-Options: DENY(或使用 CSP frame-ancestors)

跨站请求伪造(CSRF)

所有会更改状态的端点都必须防范 CSRF 攻击。

需要 CSRF 防护的端点

已验证身份的操作:

  • 所有 POST、PUT、PATCH、DELETE 请求
  • 任何会更改状态的 GET 请求(请改用正确的 HTTP 方法)
  • 文件上传
  • 设置更改
  • 支付 / 交易端点

身份验证前的操作:

  • 登录端点(防止登录 CSRF)
  • 注册端点
  • 密码重置请求端点
  • 密码更改端点
  • 电子邮件 / 电话验证端点
  • OAuth 回调端点
防护机制
  1. CSRF 令牌

    • 生成经过加密的随机令牌
    • 将令牌与用户会话绑定
    • 在每个会更改状态的请求中验证
    • 登录后重新生成(避免与会话固定攻击叠加)
  2. SameSite Cookie

    Set-Cookie: session=abc123; SameSite=Strict; Secure; HttpOnly
    
    • Strict:Cookie 从不随跨站请求发送(安全性最高)
    • Lax:Cookie 会随顶级导航发送(安全性与便利性的良好平衡)
    • 始终与 CSRF 令牌结合使用,实现纵深防御
  3. 双重提交 Cookie 模式

    • 在 Cookie 和请求正文 / 标头中都发送 CSRF 令牌
    • 由服务端验证二者是否匹配
边缘情况和常见错误
  • 令牌存在性检查:CSRF 验证绝不能取决于令牌是否存在,必须始终要求提供令牌
  • 每个表单使用单独的令牌:对于敏感操作,可考虑为每个表单使用唯一令牌
  • JSON API:不要假定 JSON 内容类型可以防止 CSRF;应验证 Origin/Referer 标头并使用令牌
  • CORS 配置错误:过于宽松的 CORS 配置可能绕过 SameSite Cookie
  • 子域名:应限定 CSRF 令牌的作用域,因为子域名接管可能导致 CSRF
  • Flash / PDF 上传:旧版浏览器插件可能绕过 SameSite
  • 带有副作用的 GET 请求:绝不要通过 GET 执行状态更改
  • 令牌泄露:不要在 URL 中包含 CSRF 令牌
  • URL 中的令牌与标头中的令牌:优先使用自定义标头(X-CSRF-Token),而不是 URL 参数
验证清单
  • 令牌具有密码学安全的随机性(使用安全随机生成器)
  • 令牌与用户会话绑定
  • 所有更改状态的请求都在服务端验证令牌
  • 缺少令牌 = 拒绝请求
  • 身份验证状态发生变化时重新生成令牌
  • 设置 SameSite Cookie 属性
  • 会话 Cookie 设置 Secure 和 HttpOnly 标志

密钥和敏感数据泄露

客户端代码不应访问任何密钥或敏感信息。

切勿在客户端代码中暴露

API 密钥和机密信息:

  • 第三方 API 密钥(Stripe、AWS 等)
  • 数据库连接字符串
  • JWT 签名密钥
  • 加密密钥
  • OAuth 客户端机密
  • 内部服务 URL/凭据

敏感用户数据:

  • 完整信用卡号
  • 社会安全号码
  • 密码(即使经过哈希处理)
  • 安全问题/答案
  • 完整电话号码(应屏蔽:--1234)
  • 显示时不需要的敏感个人身份信息(PII)

基础设施详情:

  • 内部 IP 地址
  • 数据库架构
  • 调试信息
  • 生产环境中的堆栈跟踪
  • 服务器软件版本
密钥可能隐藏的位置(请检查!)
  • JavaScript 包(包括源映射)
  • HTML 注释
  • 隐藏表单字段
  • 数据属性
  • LocalStorage/SessionStorage
  • SSR 应用中的初始状态/水合数据
  • 通过构建工具暴露的环境变量(NEXT_PUBLIC_、REACT_APP_)
最佳实践
  1. 环境变量:将密钥存储在 .env 文件中
  2. 仅限服务端:仅从后端发起需要使用密钥的 API 调用

开放重定向

任何接受 URL 并据此进行重定向的端点,都必须防范开放重定向攻击。

防护策略
  1. 允许列表验证

    allowed_domains = ['yourdomain.com', 'app.yourdomain.com']
    
    function isValidRedirect(url):
        parsed = parseUrl(url)
        return parsed.hostname in allowed_domains
    
  2. 仅允许相对 URL

    • 仅接受路径(例如 /dashboard),不接受完整 URL
    • 验证路径以 / 开头且不包含 //
  3. 间接引用

    • 使用映射替代原始 URL:?redirect=dashboard → 查找对应的 /dashboard
需要拦截的绕过手法
手法示例生效原因
@ 符号https://[email protected]浏览器会导航至 evil.com,并将 legit.com 作为用户名
滥用子域名https://legit.com.evil.com子域名由 evil.com 所有
协议技巧javascript:alert(1)通过重定向实施 XSS
双重 URL 编码%252f%252fevil.com双重解码后变为 //evil.com
反斜杠https://legit.com\@evil.com某些解析器会将 \ 规范化为 /
空字节https://legit.com%00.evil.com某些解析器会在空字节处截断
制表符/换行符https://legit.com%09.evil.com空白字符混淆
Unicode 规范化https://legіt.com(西里尔字母 і)IDN 同形异义字攻击
Data URLdata:text/html,<script>...直接执行载荷
协议相对 URL//evil.com使用当前页面的协议
滥用片段https://legit.com#@evil.com不同库的解析方式不同
IDN 同形异义字攻击防护
  • 验证前将 URL 转换为 Punycode
  • 对敏感重定向,可考虑完全屏蔽非 ASCII 域名

密码安全
密码要求
  • 至少 8 个字符(建议 12 个或更多)
  • 不设最大长度(或设置很高的上限,例如 128 个字符)
  • 允许所有字符,包括特殊字符
  • 不强制要求使用特定类型的字符(让用户自行选择强密码)
存储
  • 使用 Argon2id、bcrypt 或 scrypt
  • 切勿使用 MD5、SHA1 或纯 SHA256

服务端漏洞

服务端请求伪造(SSRF)

任何由服务器向用户提供或影响的 URL 发起请求的功能,都必须受到保护。

可能存在漏洞的功能
  • Webhook(用户提供回调 URL)
  • URL 预览
  • 根据 URL 生成 PDF
  • 从 URL 获取图片/文件
  • 从 URL 导入的功能
  • RSS/Feed 阅读器
  • 使用用户提供端点的 API 集成
  • 代理功能
  • HTML 转 PDF/图片转换器
防护策略
  1. 允许列表方案(首选)

    • 仅允许向预先批准的域名发送请求
    • 为集成维护严格的允许列表
  2. 网络隔离

    • 在隔离网络中运行获取 URL 的服务
    • 阻止访问内部网络和云元数据
需要阻止的 IP 和 DNS 绕过技术
技术示例描述
十进制 IPhttp://2130706433将 127.0.0.1 表示为十进制
八进制 IPhttp://0177.0.0.1八进制表示
十六进制 IPhttp://0x7f.0x0.0x0.0x1十六进制表示
IPv6 本地主机http://[::1]IPv6 环回地址
IPv4 映射的 IPv6http://[::ffff:127.0.0.1]IPv4 映射的 IPv6
缩写 IPv6http://[::]全零地址
DNS 重绑定攻击者的 DNS 返回内部 IP第一次请求解析为外部 IP,第二次解析为内部 IP
指向内部地址的 CNAME攻击者的域名将 CNAME 指向内部地址DNS 指向内部主机名
URL 解析器混淆http://attacker.com#@internal不同的解析行为
重定向链外部 URL 重定向到内部地址谨慎跟随重定向
IPv6 作用域 IDhttp://[fe80::1%25eth0]接口作用域 IPv6
少见的 IP 格式http://127.1缩写 IP 表示法
防止 DNS 重绑定
  1. 发起请求前解析 DNS
  2. 验证解析后的 IP 不是内部地址
  3. 在请求期间固定解析后的 IP(不要重新解析)
  4. 或者:延迟后解析两次,确保两次都解析到同一个外部 IP
云元数据防护

阻止访问云元数据端点:

  • AWS:169.254.169.254
  • GCP:metadata.google.internal、169.254.169.254、http://metadata
  • Azure:169.254.169.254
  • DigitalOcean:169.254.169.254
实施检查清单
  • 验证 URL scheme 仅为 HTTP/HTTPS
  • 解析 DNS 并验证 IP 不是私有/内部地址
  • 明确阻止云元数据 IP
  • 限制或禁用跟随重定向
  • 如果跟随重定向,则验证每一跳
  • 为请求设置超时
  • 限制响应大小
  • 尽可能使用网络隔离

不安全的文件上传

文件上传必须验证类型、内容和大小,以防止各种攻击。

验证要求

1. 文件类型验证

  • 根据允许列表检查文件扩展名
  • 验证魔数/文件签名是否与预期类型相符
  • 切勿只依赖单项检查

2. 文件内容验证

  • 读取并验证魔数
  • 对于图片:尝试使用图像库处理(以检测格式错误的文件)
  • 对于文档:扫描宏和嵌入对象
  • 检查多态文件(可被视为多种类型的有效文件)

3. 文件大小限制

  • 在服务端设置最大文件大小
  • 同时配置 Web 服务器/代理的限制
  • 考虑按文件类型设置限制(图片的限制应小于视频)
常见绕过方式和攻击
攻击描述防护措施
扩展名绕过shell.php.jpg检查完整扩展名,使用允许列表
空字节shell.php%00.jpg清理文件名,检查是否包含空字节
双扩展名shell.jpg.php仅允许单个扩展名
MIME 类型伪造将 Content-Type 设置为 image/jpeg验证魔数
魔数注入在恶意文件前添加有效魔数检查整个文件结构,而不只是文件头
多格式文件文件既是有效的 JPEG,也是有效的 JavaScript按预期类型解析文件;如果无效则拒绝
含 JavaScript 的 SVG<svg onload="alert(1)">清理 SVG,或完全禁止
通过文件上传进行 XXE 攻击恶意 DOCX、XLSX(它们基于 XML)在解析器中禁用外部实体
ZIP 路径穿越压缩包中的 ../../../etc/passwd验证解压后的路径
ImageMagick 漏洞利用特制图像保持 ImageMagick 为最新版本,并使用 policy.xml
文件名注入文件名中的 ; rm -rf /清理文件名,使用随机名称
内容类型混淆浏览器 MIME 嗅探设置 X-Content-Type-Options: nosniff
魔数字节参考
类型魔数字节(十六进制)
JPEGFF D8 FF
PNG89 50 4E 47 0D 0A 1A 0A
GIF47 49 46 38
PDF25 50 44 46
ZIP50 4B 03 04
DOCX/XLSX50 4B 03 04(基于 ZIP)
安全处理上传文件
  1. 重命名文件:使用随机 UUID 名称,丢弃原始文件名
  2. 存储在 webroot 之外:或使用单独的域名存储上传文件
  3. 使用正确的响应头提供文件:
    • Content-Disposition: attachment(强制下载)
    • X-Content-Type-Options: nosniff
    • Content-Type 与实际文件类型匹配
  4. 使用 CDN/单独的域名:将上传内容与主应用隔离
  5. 设置严格的权限:上传的文件不应具有可执行权限

SQL 注入

当用户输入未经妥善处理就被纳入 SQL 查询时,就会发生 SQL 注入。

防护方法

1. 参数化查询(预处理语句) — 主要防御措施

-- VULNERABLE
query = "SELECT * FROM users WHERE id = " + userId

-- SECURE
query = "SELECT * FROM users WHERE id = ?"
execute(query, [userId])

2. 使用 ORM

  • 使用会自动进行参数化处理的 ORM 方法
  • 谨慎使用 ORM 中的原始查询方法
  • 留意 ORM 特有的注入点

3. 输入验证

  • 验证数据类型(整数应为整数)
  • 在适用时,将允许的值列入白名单
  • 这是纵深防御措施,而非主要防御措施
需要留意的注入点
  • WHERE 子句
  • ORDER BY 子句(常被忽视——不能使用参数,必须使用白名单)
  • LIMIT/OFFSET 值
  • 表名和列名(不能参数化——必须使用白名单)
  • INSERT 值
  • UPDATE SET 值
  • 包含动态列表的 IN 子句
  • LIKE 模式(还要转义通配符:%、_)
其他防御措施
  • 最小权限原则:数据库用户应仅拥有所需的最低权限
  • 禁用危险函数:例如 SQL Server 中的 xp_cmdshell
  • 错误处理:绝不向用户暴露 SQL 错误

XML 外部实体(XXE)

当 XML 解析器处理用户提供的 XML 中的外部实体引用时,就会产生 XXE 漏洞。

易受攻击的场景

直接输入 XML:

  • SOAP API
  • XML-RPC
  • XML 文件上传
  • 配置文件解析
  • RSS/Atom 订阅源处理

间接处理 XML:

  • 在服务器端将 JSON/其他格式转换为 XML
  • Office 文档(DOCX、XLSX、PPTX 是包含 XML 的 ZIP 文件)
  • SVG 文件(基于 XML)
  • SAML 断言
  • 含 XFA 表单的 PDF
按语言/解析器进行防护

Java:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
dbf.setExpandEntityReferences(false);

Python(lxml):

from lxml import etree
parser = etree.XMLParser(resolve_entities=False, no_network=True)
# Or use defusedxml library

PHP:

libxml_disable_entity_loader(true);
// Or use XMLReader with proper settings

Node.js:

// Use libraries that disable DTD processing by default
// If using libxmljs, set { noent: false, dtdload: false }

.NET:

XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Prohibit;
settings.XmlResolver = null;
XXE 防护检查清单
  • 如果可能,完全禁用 DTD 处理
  • 禁用外部实体解析
  • 禁用外部 DTD 加载
  • 禁用 XInclude 处理
  • 使用最新的已修补 XML 解析器版本
  • 如果需要 DTD,在解析前验证/清理 XML
  • 尽可能考虑使用 JSON 替代 XML

路径遍历

当用户输入控制文件路径时,可能会发生路径遍历漏洞,从而访问预期目录之外的文件。

易受攻击的模式
# VULNERABLE
file_path = "/uploads/" + user_input
file_path = base_dir + request.params['file']
template = "templates/" + user_provided_template
防护策略

1. 避免在路径中使用用户输入

# Instead of using user input directly
# Use indirect references
files = {'report': '/reports/q1.pdf', 'invoice': '/invoices/2024.pdf'}
file_path = files.get(user_input)  # Returns None if invalid

2. 规范化和验证

import os

def safe_join(base_directory, user_path):
    # Ensure base is absolute and normalized
    base = os.path.abspath(os.path.realpath(base_directory))
    
    # Join and then resolve the result
    target = os.path.abspath(os.path.realpath(os.path.join(base, user_path)))
    
    # Ensure the commonpath is the base directory
    if os.path.commonpath([base, target]) != base:
        raise ValueError("Error!")
    
    return target

3. 输入净化

  • 移除或拒绝 .. 序列
  • 移除或拒绝绝对路径标识符(/、C:)
  • 将允许的字符列入白名单(字母数字字符、连字符、下划线)
  • 如适用,验证文件扩展名
路径遍历检查清单
  • 切勿在文件路径中直接使用用户输入
  • 规范化路径,并验证其是否位于基准目录内
  • 如适用,限制文件扩展名
  • 使用各种编码和绕过技术进行测试

安全标头检查清单

在所有响应中包含以下标头:

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Content-Security-Policy: [see XSS section]
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
Cache-Control: no-store (for sensitive pages)

JWT 安全性

JWT 配置错误可能导致完全绕过身份验证和伪造令牌。

漏洞
漏洞防护措施
alg: none 攻击始终在服务端验证算法,并拒绝 none
算法混淆明确指定预期算法,绝不从令牌推导算法
弱 HMAC 密钥使用 256 位以上的密码学安全随机密钥
缺少过期时间始终设置 exp 声明
令牌存储在 localStorage 中将令牌存储在 httpOnly、Secure、SameSite=Strict Cookie 中,绝不存储在 localStorage 中
安全实现
// 1. SIGNING
// Always use environment variables for secrets
const secret = process.env.JWT_SECRET; 

const token = jwt.sign({
  sub: userId,
  iat: Math.floor(Date.now() / 1000),
  exp: Math.floor(Date.now() / 1000) + (15 * 60), // 15 mins (Short-lived)
  jti: crypto.randomUUID() // Unique ID for revocation/blacklisting
}, secret, { 
  algorithm: 'HS256' 
});

// 2. SENDING (Cookie Best Practices)
// Protect against XSS and CSRF
res.cookie('token', token, {
  httpOnly: true, 
  secure: true,    
  sameSite: 'strict'
});

// 3. VERIFYING
// CRITICAL: Whitelist the allowed algorithm
jwt.verify(token, secret, { algorithms: ['HS256'] }, (err, decoded) => {
  if (err) {
    // Handle invalid token
  }
  // Trust the payload
});
JWT 检查清单
  • 验证时明确指定算法(绝不信任令牌标头)
  • 拒绝 alg: none
  • 密钥由 256 位以上的随机数据组成(不是密码或短语)
  • 始终设置并验证 exp 声明
  • 将令牌存储在 httpOnly Cookie 中(而非 localStorage/sessionStorage)
  • 实现刷新令牌轮换(旧刷新令牌在使用后失效)

API 安全性

批量赋值

接受未经筛选的请求正文可能导致权限提升。

// VULNERABLE — user can set { role: "admin" } in request body
User.update(req.body)

// SECURE — whitelist allowed fields
const allowed = ['name', 'email', 'avatar']
const updates = pick(req.body, allowed)
User.update(updates)

这适用于任何 ORM/框架——始终明确指定请求可以修改哪些字段。

GraphQL
漏洞防护措施
在生产环境中启用内省在生产环境中禁用内省。
查询深度攻击实施查询深度限制(例如,最多 10 层)。
查询复杂度攻击计算并强制执行严格的查询开销限制。
批处理攻击限制单个请求中允许的操作数量。
const server = new ApolloServer({
  introspection: process.env.NODE_ENV !== 'production',
  validationRules: [
    depthLimit(10),
    costAnalysis({ maximumCost: 1000 })
  ]
})

通用安全原则

生成代码时,始终:

  1. 在服务端验证所有输入 — 切勿只信任客户端验证
  2. 使用参数化查询 — 切勿将用户输入拼接到查询中
  3. 根据上下文对输出进行编码 — HTML、JS、URL、CSS 上下文需要使用不同的编码方式
  4. 执行身份验证检查 — 在每个端点上执行,而不仅仅是在路由层
  5. 执行授权检查 — 验证用户是否有权访问特定资源
  6. 使用安全的默认设置
  7. 安全地处理错误 — 不要向用户泄露堆栈跟踪或内部详细信息
  8. 保持依赖项更新 — 使用工具跟踪存在漏洞的依赖项

不确定时,选择限制更严格、更安全的选项,并在注释中记录相关安全考量。

评论

支持 Markdown