mcpField
S
security-checklist

security-checklist

github.com/jamditis安全438198 次安装4 天前更新
代码仓库

关于 security-checklist

这是一份按 OWASP Top 10:2025 分类的部署前应用安全清单,供团队逐项检查风险并先核对最新安全资料;它不能替代渗透测试或威胁建模。

主要功能

  1. 01按 OWASP Top 10:2025 分类审计
  2. 02四角度安全资料研究流程
  3. 03逐类部署检查项
  4. 04常见控制措施代码示例
  5. 0525 项部署前总检表

适用场景

  1. 01生产部署前审查应用
  2. 02排查访问控制和配置缺口
  3. 03检查依赖与构建链防护

安装

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

$npx skills add https://github.com/jamditis/claude-skills-journalism --skill security-checklist

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

附带文件agents/openai.yamlreferences/agent-pr-review.md

详细介绍

安全检查清单

按照 OWASP Top 10:2025 类别组织的部署前安全审计(该版本于 2025 年末发布,取代 2021 版)。这是用于避免明显灾难的基线,不能替代真正的渗透测试或威胁建模。有关超出此检查清单范围的验证深度,请参阅 OWASP ASVS 5.0(https://owasp.org/www-project-application-security-verification-standard/)。有关 API 特定范围,请参阅 OWASP API Security Top 10:2023(https://owasp.org/API-Security/editions/2023/en/0x00-header/)。

步骤 0:研究当前安全态势(首先执行)

安全知识的半衰期为 6-12 个月。以下方案最后一次验证于 2026-05-08;你读到此处时,它们可能已经过时。在应用本技能中的任何模式之前,请针对正在审计的 OWASP Top 10:2025 类别,分头开展研究,确保依据当前权威来源解读这些方案,而不是依据本文件中的快照。

默认开启,但可记录理由后跳过

默认执行以下 4 个角度的研究。仅当以下条件全部满足时才可跳过:

  • (a) 你在当前会话的过去 4 小时内,已针对同一原语运行过此技能,
  • (b) 此前的研究未发现针对正在审计的 OWASP Top 10:2025 类别的紧急安全公告,
  • (c) 你在回复中记录一行 Research skipped because <reason> 说明。

“我觉得自己知道”/“赶时间”/“用户希望尽快完成”/“已经很熟悉”都不是有效的跳过理由。本段的目的就是提醒未来的你:在检查当前情况之前,不要相信本技能正文中的默认做法。

并行派出 4 个子 Agent

每个子 Agent 返回不超过 300 词的项目符号,并附上引用。通过一条消息同时派出全部 4 个子 Agent,以便并行运行。

角度 1:权威标准。 过去 6-12 个月里,NIST/OWASP/IETF(RFC 和 Internet-Drafts)/W3C/CISA 是否发布了与正在审计的 OWASP Top 10:2025 类别有关的新内容?查找:规范定稿、弃用、替代规范、RFC 发布、草案修订、NIST SP 更新、OWASP 项目版本升级。引用文档编号和发布日期。

角度 2:在野利用。 当前有哪些在野利用行为针对正在审计的 OWASP Top 10:2025 类别?从以下来源查找:CISA Known Exploited Vulnerabilities(KEV)目录(筛选过去 6-12 个月的条目)、近期高 CVSS 分数或已遭在野利用的 CVE/GHSA 条目、数据泄露事后分析和事件报告(CSRB、供应商 RCA、安全供应商研究)。指出近期 KEV 新增条目中占主导的 CWE 模式。引用 CVE 编号和公告 URL。

角度 3:工具和库的现状。 本技能推荐的库是否仍是最新版本?相关软件包注册表(npm/PyPI/RubyGems/crates.io)中的最新主版本是什么?是否有库已弃用、被替换或合并到其他项目?是否有库更改了安全默认设置?查询当前版本:registry.npmjs.org、pypi.org、rubygems.org、crates.io、pkg.go.dev。引用软件包、版本和发布日期。

角度 4:从业者讨论。 过去 6 个月里,从业者和安全团队都在讨论什么?查阅:OWASP Cheat Sheet Series(请关注最后修改日期)、GitHub Security Lab 帖子、供应商安全博客(Cloudflare、Fastly、Snyk、Datadog、Wiz、GitGuardian)、会议演讲(Black Hat、DEF CON、OWASP Global AppSec、USENIX Security)、SANS ISC、Krebs、近期 OWASP 项目重新发布的内容。指出正在采用的模式和受到批评的反模式。引用帖子 URL、作者和日期。

在应用配方之前进行综合分析

4 份报告全部到齐后,撰写一段话,概述“截至 <today's date>,正在审计的 OWASP Top 10:2025 类别的当前状态”,并说明:

  • 当前规范基线(规范规定在 2026 年默认 SHOULD 如何设置)。
  • 过去 6-12 个月内,针对正在审计的 OWASP Top 10:2025 类别的 1-2 个活跃威胁。
  • 工具链变化(已弃用的库、框架中的新默认设置、已合并或替换的软件包)。
  • 最新的备忘单或博客更新中体现出的从业者共识变化。

如果综合分析发现此技能正文的配方存在变化(例如,某项规范在 2026-05-08 之后定稿、某个库现已弃用、某项默认设置已更改),请在回复中明确指出,并在两者冲突时覆盖技能正文。以综合分析为准。技能正文只是脚手架,不是教条。

无法运行子 Agent 时

如果你的运行环境不支持子 Agent,则在行内按相同方式进行:依次开展 4 次有针对性的搜索(搜索 Web 以查找标准、查询 KEV 目录、检查软件包注册表版本、比较最新备忘单的差异)。完成同样的一段综合分析。成本会上升,但防护不会减弱。

如何使用此检查清单

在任何生产部署之前,逐一检查全部 10 个类别。对于每个类别:阅读背景段落,逐项检查必须完成的事项,并在适用时核对代码模式参考。检查完成后,按类别各创建一个问题,记录其中的缺口。末尾的 25 项是/否快速检查是部署前摘要,不是审计本身。

如果有任何项目无法核实,请勿发布,先解决问题。

A01:2025,访问控制失效

授权失效是 Web 上遭利用最多的问题类别。2025 年版将 SSRF(服务器端请求伪造)纳入 A01,因为其根本问题相同:服务器执行了本应拒绝的请求。2024-2025 年的典型案例包括 API 端点中的对象级授权失效(根据 OWASP API Top 10:2023 API1,这仍是主要的 API 风险),以及被用作跳板、攻击云元数据端点的 SSRF。

  • 在每个端点检查授权,而不只是网关或中间件层。
  • 在控制器层默认拒绝(每条路由都显式允许,而非隐式允许)。
  • 每次获取资源时都进行对象级授权检查(防止 IDOR;不检查主体是否拥有资源,就不要暴露 ID)。
  • 对管理和特权端点进行功能级授权检查(检查角色,而不仅仅是路由)。
  • SSRF 防护:对服务器端获取的任何 URL 实施出站允许列表;禁止获取 localhost、127.0.0.0/8、链路本地地址(169.254.0.0/16)或云元数据 IP(169.254.169.254);在解析器上防止 DNS 重绑定。
  • 在平台支持的情况下启用数据库行级安全(见下方代码模式)。
  • 应用使用权限仅满足最低需求的专用数据库用户,而不是 root/admin。
代码模式:PostgreSQL / Supabase 行级安全
-- Enable RLS on table
ALTER TABLE documents ENABLE ROW LEVEL SECURITY;

-- Users can only read their own documents
CREATE POLICY "Users can read own documents" ON documents
  FOR SELECT USING (auth.uid() = user_id);

-- Users can only insert documents as themselves
CREATE POLICY "Users can insert own documents" ON documents
  FOR INSERT WITH CHECK (auth.uid() = user_id);

-- Users can only update their own documents
CREATE POLICY "Users can update own documents" ON documents
  FOR UPDATE USING (auth.uid() = user_id);

-- Users can only delete their own documents
CREATE POLICY "Users can delete own documents" ON documents
  FOR DELETE USING (auth.uid() = user_id);

A02:2025,安全配置错误

由于不安全的框架默认设置仍不断进入生产环境,配置错误在排名中上升(2021 年为 A05)。2024 年 Snowflake / UNC5537 攻击行动是典型教训:默认情况下,MFA 由各租户自行选择启用;在 Snowflake 于 2024 年更改默认设置之前,该攻击行动已大规模窃取凭据。

  • 加固镜像 / 最小化容器(使用 distroless 或精简基础镜像;除非有需要,否则不包含 shell)。
  • 移除默认凭据;在防火墙处关闭默认端口。
  • 将 CORS 配置为仅允许特定来源(生产环境中标记 Access-Control-Allow-Origin: *)。
  • 为 Web 框架设置生产模式标志:Flask debug=False、Django DEBUG=False、Express NODE_ENV=production、Rails RAILS_ENV=production。
  • 绝不向客户端返回堆栈跟踪。
  • 默认禁用云存储桶 / Blob 的公开读取权限;通过签名 URL 或经过身份验证的请求访问。
  • 管理界面不得公开访问(使用 VPN、允许列表或身份验证代理)。
  • 关闭不必要的服务和端口;将防火墙默认设置为拒绝。
  • 源代码或 git 历史记录中不得包含机密;从环境变量或机密管理器读取机密。
  • 开发 / 预发布 / 生产环境使用不同的机密。
  • 将 API 密钥的权限范围限制在最低必需权限;无需部署代码即可轮换密钥。
代码模式:环境变量设置
# .env (development only, never commit)
# Replace each <placeholder> with a real value generated locally.
# Generate JWT_SECRET with `openssl rand -hex 32` (256 bits).
DATABASE_URL=<your-database-connection-string>
JWT_SECRET=<32-byte-hex-secret>
API_KEY=<api-key-from-your-provider>
# .gitignore (mandatory)
.env
.env.local
.env.*.local
*.pem
*.key
credentials.json
secrets/
// Reading environment variables (Node.js with dotenv)
require('dotenv').config();
const dbUrl = process.env.DATABASE_URL;

// Fail fast if missing
if (!process.env.JWT_SECRET) {
  throw new Error('JWT_SECRET environment variable is required');
}
代码模式:CORS(Express.js)
const cors = require('cors');

// SAFE: specific origins
app.use(cors({
  origin: ['https://myapp.com', 'https://www.myapp.com'],
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  credentials: true
}));

不安全的模式是使用不带选项的 cors(),它会发送 Access-Control-Allow-Origin: *。这在开发环境中没问题,但在生产环境中用于带凭据的请求时绝不可用。

A03:2025,软件供应链故障

这是 2025 年新增的类别,涵盖了 2021 年 A06“易受攻击和过时的组件”。其范围不仅限于打补丁,还涵盖 SBOM、构建系统完整性、软件包来源证明以及对依赖项来源的信任。xz-utils CVE-2024-3094 后门(2024 年 3 月)是“对开源维护者进行社会工程攻击”的典型教训;Polyfill.io(2024 年 6 月)则是“受信任的 CDN 变为恶意”的典型教训。

  • 在构建时生成 SBOM(CycloneDX 1.7 = ECMA-424 第 2 版,于 2025 年 12 月获批准;或 SPDX 2.3+)。
  • 在 CI 中运行依赖项扫描(Trivy、Grype、Snyk 或 GHSA 扫描器),并在发现严重问题时使构建失败。
  • 固定版本(提交锁定文件;容器镜像中不使用 latest 等浮动标签,安全关键库不使用 ^x.y.z)。
  • 启用来源证明签名:npm provenance(2023 年 9 月正式发布)、PyPI Trusted Publishing、容器使用 Sigstore cosign。
  • 跟踪 SLSA v1.2 源代码 / 构建轨道的采用情况(于 2025-11-24 发布,https://slsa.dev/)。
  • 按计划应用补丁。启用 Renovate 或 Dependabot,并设置补丁版本自动合并。
  • 标记并替换已到生命周期末期的运行时(Node 18 于 2025 年 4 月 EOL;Python 3.8 于 2024 年 10 月 EOL)。
  • 为每个外部 <script> 和 <link rel="stylesheet"> 设置子资源完整性(Polyfill.io 教训;SRI 检查项见 A08)。

**合规提示:**OMB M-26-05(于 2026-01-23 发布)撤销了 M-22-18 + M-23-16 中针对联邦政府的 SBOM 自我证明要求。欧盟《网络韧性法案》(法规 2024/2847)的报告义务自 2026-09-11 起适用,完整义务自 2027-12-11 起适用;不要将美国的撤销视为全球范围内的撤销。

A04:2025,密码学失效

使用经过审核的高级库。不要自行实现密码学。不要手动组合 AES-CBC + HMAC,应使用 libsodium、AWS Encryption SDK 或 Tink。2026 年的规范上限为默认使用 TLS 1.3、最低使用 TLS 1.2,并禁用 TLS 1.0/1.1(RFC 8996 / BCP 195)。

  • 仅使用 HTTPS;HTTP 重定向到 HTTPS。
  • 默认使用 TLS 1.3;最低使用 TLS 1.2;禁用 TLS 1.0/1.1。
  • 设置 HSTS preload 标头:Strict-Transport-Security: max-age=63072000; includeSubDomains; preload(2 年)。
  • 设置安全 Cookie 标志(Secure、HttpOnly、SameSite=Lax 或 Strict)。
  • 数据库连接使用 SSL/TLS。
  • 备份在静态存储时加密,并经过恢复测试。
  • 密码存储使用 argon2id,并遵循 OWASP 备忘单中的参数(m=47104/t=1、m=19456/t=2、m=12288/t=3、m=9216/t=4 或 m=7168/t=5;所有参数均为 p=1)。完整策略位于此资源包的 secure-auth 技能中,请从此处添加链接。
  • 身份验证或完整性校验路径中不得使用 MD5 / SHA-1 / 无盐哈希。
  • 不得自行实现密码学,应使用 libsodium、AWS Encryption SDK、Google Tink 或同等工具。
代码模式:安全标头(使用 Helmet 的 Express.js)
const helmet = require('helmet');

app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'"],
      styleSrc: ["'self'", "'unsafe-inline'"],
      imgSrc: ["'self'", "data:", "https:"],
      frameAncestors: ["'none'"]
    },
  },
  hsts: {
    maxAge: 63072000,
    includeSubDomains: true,
    preload: true
  }
}));
// Manual headers, modern set
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('Strict-Transport-Security', 'max-age=63072000; includeSubDomains; preload');
res.setHeader('Content-Security-Policy', "default-src 'self'; frame-ancestors 'none'");
// Note: X-Frame-Options is replaced by CSP frame-ancestors. The legacy XSS-protection header is deprecated, modern browsers ignore it.

A05:2025,注入

2024—2025 年,CWE-78 OS 命令注入在 CISA KEV 中占主导地位(2024 年有 14 个条目,2025 年有 18 个),数量超过了传统 SQL 注入。CWE-22 路径遍历也有所增加(2024 年有 9 个,2025 年有 13 个)。MOVEit CVE-2023-34362 仍是 SQLi 的典型案例。

  • 所有用户输入都在服务端进行验证。客户端验证属于用户体验,不属于安全措施。
  • SQL 查询使用参数化语句(CWE-89)。绝不使用字符串拼接。
  • 调用 OS 命令时使用 argv 列表形式,并禁用 shell。对 shell 调用中使用的任何路径或文件名进行允许列表验证(CWE-78)。
  • LDAP / NoSQL / 模板注入遵循相同的参数化原则。
  • 对 HTML 输出进行转义(XSS):使用框架自动转义 + CSP3 nonce,并在支持的情况下使用 Trusted Types。
  • 标头注入:验证任何用于响应标头的用户提供值(不得包含 CR/LF)。
  • 文件上传需验证类型和大小,并存储在 webroot 之外。
  • 根据允许列表验证 URL 和重定向。
  • JSON/XML 解析器设置实体扩展限制。
代码模式:参数化 SQL(Node.js)

不安全的模式是将用户输入插入 SQL 模板字符串,然后对结果调用 db.query,这属于 CWE-89。务必使用参数化查询。

// SAFE: parameterized query, user input bound as $1
db.query('SELECT * FROM users WHERE id = $1', [req.params.id]);
代码模式:参数化 SQL(Python)
# SAFE: parameterized query, user input bound as %s placeholder
cursor.execute("SELECT * FROM users WHERE id = %s", [user_id])

不安全的模式是使用 f-string 构建 SQL 字符串并插入用户输入,这属于 CWE-89。

代码模式:命令注入(Node.js)

Node child_process 模块提供 shell 执行原语(通过 /bin/sh 运行命令字符串的原语)和 argv 列表原语(使用 shell: false 的 spawn 系列)。对于任何涉及用户数据的输入,都应使用 argv 列表原语。

const { spawn } = require('child_process');

// SAFE: argv-list invocation, shell disabled
// userInput is treated as a single argument, never re-parsed by a shell
spawn('convert', [userInput, 'output.png'], { shell: false });

不安全的模式是将插入了用户输入的模板字符串传递给 shell 执行原语,这属于 CWE-78。不要这样做。如果确实需要 shell 功能,请先对命令的每个部分进行允许列表验证。

代码模式:命令注入(Python)

Python 提供 shell 执行原语(OS shell 调用函数和 subprocess.run(..., shell=True))以及 argv 列表原语(subprocess.run([...], shell=False))。对于任何涉及用户数据的输入,都应使用 argv 列表原语。

import subprocess

# SAFE: argv-list invocation, shell disabled
# user_input is treated as a single argument, never re-parsed by a shell
subprocess.run(["convert", user_input, "output.png"], shell=False, check=True)

不安全的模式是将插入了用户输入的 f-string 传递给 OS shell 调用函数,或传递给 shell=True 的子进程调用,这些都属于 CWE-78。不要这样做。在任何路径或文件名部分进入 shell 调用边界之前,都要对其进行允许列表验证。

代码模式:XSS(React/前端)

React 会自动转义 JSX 子内容。该框架还提供了 dangerouslySetInnerHTML,这个属性名明确警告了将用户数据传入其中会发生什么。默认将内容渲染为子元素;只有先使用经过验证的净化器处理数据时,才使用这个危险属性。

// DO NOT USE: dangerouslySetInnerHTML on user content with no sanitizer
<div dangerouslySetInnerHTML={{ __html: userContent }} />

// SAFE: React escapes content automatically when rendered as a child
<div>{userContent}</div>

// SAFE: when raw HTML is genuinely required, sanitize through DOMPurify first
import DOMPurify from 'dompurify';
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userContent) }} />

对于服务器端渲染的 HTML,应使用具有自动转义功能的模板引擎(例如 EJS <%= %>、启用了自动转义的 Nunjucks {{ }} 等),而不是手动拼接字符串。

// DO NOT USE: template-string interpolation of user input into HTML
res.send(`<h1>Hello ${req.query.name}</h1>`);

// SAFE: template engine with auto-escaping
res.render('greeting', { name: req.query.name });

A06:2025,不安全设计

威胁建模和安全默认值应在设计阶段落实,而不是在事故发生后再补救。Snowflake 在 2024 年之前默认启用 MFA 的做法,是“安全默认值”的典型教训:默认不安全、需要主动选择才能安全的功能,很容易被误用。

  • 编写代码前对新功能进行威胁建模(安全方面使用 STRIDE,隐私方面使用 LINDDUN)。
  • 在编写用例的同时编写滥用场景。
  • 在设计层面遵循最小权限原则(服务、角色、作用域)。
  • 在设计阶段加入速率限制,而不是事后补救:按用户/IP 对 API 端点进行速率限制,对登录端点实施更严格的限制,配置请求大小限制,并为所有外部调用设置超时。
  • 在应用前方配置 CDN 或 DDoS 防护。
  • 设置安全默认值,让安全选项成为最容易选择的路径;主动选择应针对不安全选项,而非安全选项。

A07:2025,身份验证失败

此类别于 2021 年从“身份识别和身份验证失败”更名。本套件中的 secure-auth 技能已提供默认设置;此处的检查清单项目引用相关内容,不再重复。NIST SP 800-63B-4 于 2025-07-31 正式发布(https://csrc.nist.gov/pubs/sp/800/63/b/4/final)。

  • 单因素密码至少为 15 个字符(NIST SP 800-63B-4)。不设组合规则。不要求定期轮换。
  • 注册或更改密码时检查泄露密码黑名单(Have I Been Pwned API 或同等服务)。
  • 使用 argon2id 对密码进行哈希处理(也可接受 bcrypt cost ≥10 或 scrypt)。绝不使用 MD5、SHA-1 或明文。
  • 所有账户均可使用 MFA;在 AAL3 级别必须使用抗钓鱼 MFA(WebAuthn / passkey)。
  • 会话令牌须为密码学安全的随机值(crypto.randomBytes 或同等方法)。
  • 会话须设置过期时间(普通应用为 24 小时,敏感数据应用的时间更短)。
  • 注销时在服务器端使会话失效。
  • 密码重置令牌须为一次性令牌,并在 1 小时内过期。
  • 对登录失败尝试进行速率限制(例如,尝试 5 次后进入冷却期)。
  • 权限变更时重新生成会话(登录、角色提升)。
  • 轮换刷新令牌并检测重用情况。
  • 代码、日志或错误消息中不得包含凭据。

关键教训: Change Healthcare,2024 年 2 月(Citrix 远程访问门户未启用 MFA,https://www.unitedhealthgroup.com/newsroom/2024/2024-04-22-uhg-update-on-change-healthcare-cyberattack.html);Snowflake / UNC5537,2024 年(MFA 默认启用,但由每个租户选择是否启用);Storm-0558,2023 年(完整验证令牌;CSRB 审查报告见 https://www.cisa.gov/resources-tools/resources/CSRB-Review-Summer-2023-MEO-Intrusion);23andMe,2023 年(通过关联账户进行图遍历攻击,扩大影响范围)。

A08:2025,软件或数据完整性故障

注意:“软件或数据”中的“或”至关重要。涵盖 CI/CD 流水线完整性、签名更新渠道和反序列化安全。CWE-502(反序列化)在 2024—2025 年的 KEV 中占主导地位(2024 年有 11 项,2025 年有 14 项)。

  • CI/CD 流水线完整性:构建签名、分支保护、强制审核,流水线配置中不得包含明文机密。
  • 验证更新渠道:自动更新程序执行签名检查;容器映像使用 Sigstore cosign。
  • 反序列化防护:绝不使用原生二进制反序列化器或 YAML 不受限的加载原语反序列化不可信输入。跨越信任边界时仅使用 JSON。
  • 为每个外部 <script> 和 <link rel="stylesheet"> 添加子资源完整性(Subresource Integrity),参见 Polyfill.io 教训:https://sansec.io/research/polyfill-supply-chain-attack。
  • 不得引用未固定 SRI 哈希的 CDN 第三方脚本。
  • 审查拉取请求的 AI Agent 审查者应将 PR 文件视为不可信数据,从基础提交获取审核规则,仅持有范围受限、有效期短的令牌,并且只能发表评论。参见 references/agent-pr-review.md。
代码模式:反序列化(Python)

Python 原生的二进制反序列化原语会在不可信输入上执行任意代码;loads 会运行对象构造函数,包括攻击者构造的任何 __reduce__ 载荷。JSON 不会。在任何信任边界上,都应使用 JSON。YAML 也存在同样的风险:裸加载器会运行 Python 代码;请使用 safe_load。

import json
import yaml

# DO NOT USE: pickle.loads runs arbitrary code on untrusted input,
# any object's __reduce__ method executes at parse time. CWE-502 sink.
#   import pickle
#   obj = pickle.loads(request.body)

# DO NOT USE: yaml.load with no Loader argument is equivalent to yaml.Loader and runs code:
#   config = yaml.load(request.body)

# SAFE: JSON parsing returns plain data (dict / list / str / number / bool / None)
data = json.loads(request.body)

# SAFE: when YAML is genuinely required, use safe_load
config = yaml.safe_load(request.body)

CWE-502(反序列化不可信数据)在 2024—2025 年主导了 CISA KEV 目录(2024 年有 11 项,2025 年有 14 项)。同样的警告也适用于 Java(ObjectInputStream.readObject)、.NET(BinaryFormatter、NetDataContractSerializer、LosFormatter、SoapFormatter),以及任何会对任意对象进行“反序列化”的 Node 软件包。跨越信任边界传入数据时,JSON 是唯一安全的选择。

代码模式:SRI

<script src="https://cdn.example.com/lib.js"
        integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
        crossorigin="anonymous"></script>

不安全的做法是引用外部脚本却不设置 integrity 属性,这意味着 CDN 上的任何更改都会在你的源站上下文中运行。Polyfill.io 2024 年的事件正是如此。

A09:2025,安全日志记录与告警故障

注意:2025 年版强调的是“告警”而非“监控”,将重点重新放在主动响应上,而不仅仅是收集数据。Okta HAR 事件(2023 年)是重要教训:由于日志边界处的清理不足,客户上传的调试文件中包含有效的会话令牌。

  • 记录身份验证事件(登录、登出、失败尝试)、授权失败、管理员操作和支付事件。
  • 日志不得包含密码、令牌、JWT、API 密钥、个人身份信息、会话 ID、信用卡信息,或包含用户数据的完整请求正文。
  • 集中记录日志并制定保留策略(安全日志至少保留 90 天;合规要求需要时则保留更久)。
  • 安全存储日志(静态加密、访问控制)。
  • 针对不可能的跨地移动、大量身份验证失败、权限提升模式配置告警。
  • 错误消息不得向客户端泄露系统信息(参见 A10)。

重要教训: Okta HAR 文件事件,https://sec.okta.com/articles/harfiles/

代码模式:切勿记录的内容
// SAFE: structured logging with field allowlist
console.log('Login attempt:', { email, success: false, reason: 'invalid_password' });
console.log('Request:', { endpoint: req.path, method: req.method, userId: req.user?.id });

不安全的做法是记录完整请求正文或凭据对象,这会泄露用户提供的所有机密。绝不记录密码字段、令牌字段、完整请求正文或会话标识符。

A10:2025,异常情况处理不当

2025 年新增类别。CWE 目录为此类别指定了 CWE-1445,涵盖 24 个 CWE,包括 CWE-209/234/274/476/636。CrowdStrike Channel File 291 事件(2024 年 7 月)是重要教训:将未经验证的配置文件部署到生产环境,导致 850 万台 Windows 主机出现蓝屏死机(BSOD)。

  • 安全相关代码路径默认采取失败关闭策略(不要在身份验证/授权/完整性检查失败时捕获所有异常并继续执行)。
  • 错误响应不会泄露结构、堆栈跟踪或内部 ID。
  • 在部署到生产环境前验证配置。采用分阶段发布、金丝雀发布比例,以及暂存环境与生产环境之间的验证关卡。
  • 捕获 Exception 的代码块不会悄无声息地吞掉安全相关故障。
  • 测试异常路径(超时、内存不足、部分写入、网络分区),大多数安全回归问题都藏在这里。
  • 为所有外部调用设置超时,并明确处理超时情况。

重要教训: CrowdStrike Falcon Channel File 291 根本原因分析(RCA),https://www.crowdstrike.com/en-us/blog/falcon-content-update-preliminary-post-incident-report/

部署前摘要:25 项是/否检查

在审计结束时执行此检查。如果任何一项答案为 N,请勿发布。

  1. 是否强制使用 TLS 1.3(最低 TLS 1.2,禁用 1.0/1.1)?是/否
  2. 是否设置了 HSTS 预加载标头 max-age=63072000; includeSubDomains; preload?是/否
  3. 是否使用 argon2id 进行密码哈希(或使用成本 ≥10 的 bcrypt/scrypt)?是/否
  4. 是否要求密码至少 15 个字符,不设置字符组合规则,也不强制定期更换?是/否
  5. 是否为所有账户提供抗钓鱼 MFA?是/否
  6. 会话令牌是否为加密安全的随机值,并在注销时失效?是/否
  7. SQL 查询是否都使用参数化查询?是/否
  8. OS 命令是否使用 argv 列表形式,并禁用 shell?是/否
  9. HTML 输出是否自动转义,并设置了包含 frame-ancestors 的 CSP?是/否
  10. CORS 是否限定为特定源(生产环境中不使用 *)?是/否
  11. 是否在控制器层级实施默认拒绝授权?是/否
  12. 每次获取资源时是否都执行对象级授权(无 IDOR)?是/否
  13. SSRF 是否设有出站允许列表和元数据 IP 屏蔽列表?是/否
  14. 在受支持的情况下,是否启用了数据库行级安全?是/否
  15. 代码或 git 历史记录中是否没有机密信息,且所有机密信息都从环境变量/机密管理器读取?是/否
  16. 是否设置了生产模式标志(debug=False、NODE_ENV=production 等)?是/否
  17. 是否从不向客户端返回堆栈跟踪?是/否
  18. 是否在构建时生成 SBOM,并在 CI 中进行扫描?是/否
  19. 所有第三方脚本是否都固定了 SRI 哈希?是/否
  20. 依赖项是否通过锁定文件固定版本,且没有使用浮动容器标签?是/否
  21. 是否标记并替换已结束生命周期的运行时?是/否
  22. 是否记录身份验证事件、授权失败和管理员操作(不包含机密信息)?是/否
  23. 是否已配置针对大量身份验证失败和权限提升的警报?是/否
  24. 安全相关代码路径是否采取失败关闭策略?是/否
  25. 是否已验证配置并通过分阶段部署发布?是/否

事件响应快速修复

“我以明文存储了密码”
  1. 立即添加密码哈希(使用 argon2id;参见 secure-auth 技能)。
  2. 强制所有用户重置密码。
  3. 使所有现有会话失效。
  4. 检查泄露迹象(数据库是否曾暴露,或是否以不安全的方式备份?)。
“我的 API 密钥在 git 历史记录中”
  1. 立即轮换密钥(生成新密钥)。
  2. 撤销旧密钥。
  3. 使用 git filter-repo(优先于 git filter-branch)或 BFG Repo-Cleaner 从历史记录中移除密钥。
  4. 强制推送,并与团队协调。
“我不知道自己记录了哪些数据”
  1. 在代码库中搜索 console.log、logger.、print(。
  2. 检查记录的内容。
  3. 使用字段允许列表实现结构化日志记录。
  4. 设置日志轮换和保留策略。
“我的数据库可公开访问”
  1. 立即更改数据库凭据。
  2. 配置防火墙规则(仅允许应用服务器 IP)。
  3. 为连接启用 SSL/TLS。
  4. 检查访问日志中是否存在未经授权的查询。

合规快速参考

你可能需要关注:

  • GDPR(欧盟用户):数据删除权、同意、违规通知。
  • CCPA(加州用户):与 GDPR 类似。
  • PCI DSS(信用卡):不要存储卡号;请使用支付处理商。
  • HIPAA(健康数据):加密、访问控制、审计日志。
  • SOC 2(企业销售):安全控制文档。
  • SEC Form 8-K Item 1.05(在美国上市的公司):重大网络安全事件须在 4 个工作日内披露(自 2023-12-18 起生效)。
  • EU Cyber Resilience Act(Reg 2024/2847):适用于含数字元素的产品;报告义务自 2026-09-11 起生效,全部义务自 2027-12-11 起生效。
  • OMB M-26-05(美国联邦供应商):撤销了联邦范围内的 SBOM 自我证明要求(于 2026-01-23 发布)。机构特定要求仍可能适用。

对于任何用户数据,至少需要:

  1. 说明数据收集情况的隐私政策。
  2. 为用户提供请求删除数据的途径。
  3. 对传输中(HTTPS)和静态数据进行加密。
  4. 访问日志和审计跟踪。
  5. 事件响应计划(即使是基础版也可以)。

参考文件

构建或审查使用编码 Agent 审查拉取请求的机器人时,请阅读将 AI Agent 用作拉取请求审查者。

资源

标准和框架
漏洞数据
供应链
事件参考
合规
测试工具

评论

支持 Markdown