如果团队还没有正式的安全岗位,最容易发生的不是“没人懂安全”,而是安全要求太晚进入项目:接口已经写完、依赖已经引入、权限模型已经散落在各处,最后只能靠补丁式修复。下面这份清单适合初创或早期技术团队放进开发规范、代码评审模板和上线前检查中,核心依据是 OWASP 安全编码实践,并结合 OWASP Top 10:2025 中强调的高风险类别进行整理。

先把清单定位说清楚
OWASP Top 10 不是完整的安全标准,也不应该被当成“勾完十项就安全”的证明。它更适合作为团队沟通 Web 应用主要风险的共同语言,用来帮助开发、测试、运维和产品负责人理解哪些问题更常见、影响更大。
对初创团队来说,更实用的做法是:把 OWASP 安全编码实践变成开发前置要求,再用 OWASP Top 10:2025 的风险分类校准优先级。也就是说,不要等漏洞出现后再问“怎么修”,而是在需求评审、接口设计、编码、代码评审和发布前就明确“哪些写法不能进主干”。
2025 版风险重点给编码规范带来的变化
OWASP Top 10:2025 列表中明确出现了访问控制失效、安全配置错误、软件供应链失败、加密失败、注入、不安全设计、身份认证失败、软件或数据完整性失败等类别。对早期团队而言,这些变化传递出一个很直接的信号:安全编码不再只是“过滤输入、防 SQL 注入”这一类局部问题,还要覆盖依赖来源、默认配置、设计阶段的安全假设,以及数据和软件交付过程中的完整性。
| 2025 重点风险方向 | 编码前应落到规范里的要求 | 常见误区 |
|---|---|---|
| 访问控制失效 | 每个受保护资源都必须有服务端授权判断,不能只依赖前端隐藏入口 | “用户看不到按钮,就不能访问接口” |
| 安全配置错误 | 默认配置、调试信息、错误输出和环境差异必须纳入发布检查 | “配置是运维的事,代码不用管” |
| 软件供应链失败 | 引入依赖前要确认来源、用途、维护状态,并记录在项目中 | “能安装、能跑起来就可以用” |
| 加密失败 | 密钥、敏感数据、传输保护和存储方式要在设计时确定 | “用了加密函数就等于安全” |
| 注入 | 所有外部输入都要按上下文处理,不能拼接进解释器、查询或命令语义中 | “只要前端校验过,后端就不用再管” |
| 不安全设计 | 权限边界、业务限制、异常流程和滥用场景要在编码前讨论 | “设计先做功能,安全以后补” |
| 身份认证失败 | 登录、会话、凭证处理和认证状态变化要有统一规则 | “账号密码能登录就算认证完成” |
| 软件或数据完整性失败 | 关键数据变更、发布产物和信任边界要有完整性校验思路 | “只要接口调用成功,数据就是可信的” |
这张表可以直接作为项目规范的开头,但不要停在表格层面。真正有效的规范,必须继续落到代码写法和评审问题上。
可直接引用的 OWASP 安全编码实践清单
下面的清单按开发团队最常遇到的编码决策组织,不按漏洞名称堆砌。建议把每一项改成团队自己的“必须 / 禁止 / 例外审批”规则,放进代码评审模板。
输入校验与数据边界
- [ ] 所有来自用户、客户端、第三方服务、文件、消息队列、请求头、路径参数和查询参数的数据,都按不可信输入处理。
- [ ] 输入校验必须在服务端执行,前端校验只用于改善体验,不能作为安全边界。
- [ ] 对输入采用白名单思路:明确允许的类型、长度、格式、范围和业务状态,而不是只过滤少数危险字符。
- [ ] 同一字段在不同业务场景中要分别校验,不能因为字段名相同就复用过宽的规则。
- [ ] 对结构化输入要校验结构本身,不只校验其中几个字段。
- [ ] 文件上传要校验文件类型、大小、存储位置、访问方式和后续处理流程,不能仅依赖文件名或客户端声明。
- [ ] 对跨边界传入的数据,在进入核心业务逻辑前完成校验,避免校验逻辑分散在多个函数中。
常见误区是把“输入校验”理解成“过滤特殊字符”。这会让团队陷入无穷无尽的黑名单维护。更稳妥的做法是先定义业务允许什么,再拒绝不符合规则的输入。
输出编码与内容呈现
- [ ] 向页面、模板、日志、响应体或下游系统输出数据前,要根据输出上下文进行处理。
- [ ] 不同上下文不能混用同一种编码方式;页面内容、属性值、脚本上下文、样式上下文和 URL 上下文应分别考虑。
- [ ] 用户可控内容不得直接拼接进可执行上下文。
- [ ] 富文本、HTML 片段或可配置模板必须有明确的允许范围和清理规则。
- [ ] 错误页面、提示信息和调试信息中不得输出敏感数据、内部路径、堆栈细节或凭证线索。
这里的关键不是“把所有东西都转义一下”,而是判断数据最终会被谁解释。浏览器、数据库、命令解释环境和模板引擎的解释规则不同,安全处理方式也不能混为一谈。
认证、会话与凭证处理
- [ ] 认证逻辑应集中实现,避免每个接口各写一套登录判断。
- [ ] 密码、令牌、会话标识等凭证不得写入日志、错误信息、URL 或前端可长期保存的位置。
- [ ] 认证成功、退出登录、凭证更新、权限变化等状态切换要有明确处理规则。
- [ ] 会话标识应由服务端安全生成和管理,不能由客户端决定。
- [ ] 对敏感操作应重新确认当前用户状态,不能长期依赖旧的认证上下文。
- [ ] 登录失败提示应避免泄露账号是否存在、认证策略细节或内部判断条件。
- [ ] 临时凭证、重置链接和邀请链接必须有范围限制和失效机制。
初创团队常为了快速上线,把认证逻辑直接散落在业务代码里。短期看很快,后期一旦要增加角色、组织、租户或管理员能力,就很容易出现某些接口漏鉴权、某些状态未刷新、某些旧令牌仍可使用的问题。
访问控制
- [ ] 每个受保护接口都必须在服务端执行授权检查。
- [ ] 授权判断应基于当前用户、资源归属、角色、业务状态和操作类型,而不是只检查是否登录。
- [ ] 禁止把前端路由、菜单可见性、按钮隐藏作为访问控制措施。
- [ ] 对读取、创建、修改、删除、导出、审批等操作分别授权,不能因为用户能查看就默认能修改。
- [ ] 多租户、团队空间、项目空间或组织边界必须在查询和写入时同时校验。
- [ ] 批量操作要逐项校验权限,不能只校验请求发起者是否有某个总体权限。
- [ ] 代码评审时必须包含反向授权用例:用户不能访问的资源,是否真的被拒绝。
访问控制失效长期是 Web 应用中的高风险类别。对早期团队来说,最有效的改进不是写一大段权限说明,而是把“服务端逐资源授权”做成不可绕过的开发习惯。
注入防护
- [ ] 不得把未处理的外部输入拼接进查询语句、命令、表达式、模板或解释器上下文。
- [ ] 使用参数化、预编译或框架提供的安全接口处理查询类操作。
- [ ] 动态条件、排序字段、筛选字段等不能直接来自用户输入,应映射到服务端允许的固定集合。
- [ ] 对命令执行、脚本执行、表达式求值、模板渲染等高风险能力,默认禁止在普通业务代码中使用。
- [ ] 如果业务确实需要动态表达能力,必须限制语法范围、执行上下文和可访问资源。
- [ ] 日志、搜索、报表、导入导出等“非核心功能”同样要按注入风险处理。
注入问题的误区在于只盯着数据库。实际编码中,只要用户输入能影响某个解释器的语义,就存在同类风险。安全规范里应写“禁止拼接语义”,而不只是“防某一种注入”。
加密与敏感数据保护
- [ ] 敏感数据在采集前要先确认是否真的需要,能不收集就不收集。
- [ ] 敏感字段要明确存储位置、访问路径、日志处理方式和脱敏规则。
- [ ] 密钥、令牌、密码和连接凭证不得硬编码在代码仓库中。
- [ ] 加密方案应使用成熟、受维护的安全能力,不应自行设计加密算法或混淆方案。
- [ ] 密钥与数据应分开管理,避免拿到数据库备份就能直接还原全部敏感信息。
- [ ] 测试数据、演示环境和排查日志也要遵守敏感数据处理规则。
- [ ] 数据删除、导出、备份和恢复流程中同样要考虑敏感信息暴露。
“加密失败”不等于“完全没加密”。更常见的问题是加密对象选错、密钥放错位置、日志泄露明文,或者开发者把编码、哈希、混淆和加密混为一谈。
错误处理、日志与监控友好编码
- [ ] 面向用户的错误信息应简洁,不暴露内部实现、路径、查询细节或依赖信息。
- [ ] 面向排查的日志应记录必要上下文,但不得记录密码、令牌、密钥、完整敏感字段。
- [ ] 认证失败、授权失败、关键配置变更、敏感数据访问、关键业务状态变化应具备可追踪记录。
- [ ] 异常处理不能简单吞掉错误,必须保留足够排查线索。
- [ ] 日志内容要避免被用户输入污染,防止伪造日志或破坏日志结构。
- [ ] 安全相关事件的记录格式应尽量统一,便于后续排查和关联分析。
早期团队经常在两个极端之间摇摆:要么什么都不记,出事后无法还原;要么把所有请求和响应都打进日志,结果泄露更多敏感信息。安全编码的目标是“可排查但不过度暴露”。
安全配置与默认值
- [ ] 新项目应定义安全默认配置,不能依赖开发者每次手动记住。
- [ ] 调试开关、详细错误、测试账号、示例密钥和临时入口不得进入生产环境。
- [ ] 不同环境的配置差异要可见、可审查,不能靠口头约定。
- [ ] 配置项的默认值应偏向安全,功能放开需要显式配置。
- [ ] 对外暴露的管理入口、调试接口、健康检查和内部接口要有访问限制。
- [ ] 配置变更应纳入代码评审或发布检查,不能绕过正常流程。
安全配置错误在小团队里很常见,因为大家会默认“等上线前再统一整理”。但上线前通常最忙,最容易漏掉临时开关和测试配置。更可靠的方式是从项目第一天就使用安全默认值。
软件供应链与依赖使用
- [ ] 引入新依赖前,要确认它解决的是必要问题,而不是为了少写少量代码。
- [ ] 依赖来源、用途和维护责任要记录在项目中。
- [ ] 不再使用的依赖应及时移除,避免长期留在构建和运行环境中。
- [ ] 依赖升级要包含兼容性和安全影响评估,不能只看功能是否通过。
- [ ] 构建、发布和部署流程中的脚本、包、镜像或产物应有明确来源。
- [ ] 不应在安装或构建过程中执行来源不明、职责不清的脚本。
- [ ] 关键依赖发生变更时,应触发代码评审和发布风险确认。
OWASP Top 10:2025 将软件供应链失败列为重要风险类别,这对初创团队尤其现实。早期项目为了速度会大量依赖开源组件和外部包,一旦没有记录和边界,后续很难回答“这个依赖为什么存在、谁在维护、影响哪些服务”。
软件与数据完整性
- [ ] 关键业务数据写入前后要有一致性校验,不能只相信客户端提交内容。
- [ ] 重要状态变更应在服务端根据业务规则计算,不能完全由客户端传入最终状态。
- [ ] 回调、异步任务、导入文件、第三方返回数据都要验证来源和内容合理性。
- [ ] 发布产物、配置和脚本要避免被未授权修改。
- [ ] 自动化流程中的权限应最小化,避免一个流程拿到过大的写入能力。
- [ ] 对影响资金、权限、审批、资产归属或敏感数据的操作,要设计防篡改和可追溯机制。
完整性问题往往不像注入那样直观,却会直接破坏业务结果。对代码规范来说,最重要的是明确“客户端只提交请求,服务端负责判断结果”。
不安全设计的前置检查
- [ ] 新功能进入开发前,必须说明核心资产、信任边界、主要角色和高风险操作。
- [ ] 对权限、认证、数据流、异常流程和滥用场景进行简短评审。
- [ ] 安全限制应写进需求或接口约定,不能只留在开发者脑中。
- [ ] 对“以后再补”的安全控制,要记录风险和补齐条件,不能无期限拖延。
- [ ] 设计复用组件时,应优先提供安全默认行为,减少业务方重复实现。
- [ ] 对高风险功能,应在编码前确定测试思路,而不是上线后再补安全用例。
“不安全设计”提醒团队:有些漏洞不是某一行代码写错,而是需求和架构一开始就没有给安全留下位置。初创团队不需要把设计评审做得很重,但至少要在开发前问清楚:谁能做什么、不能做什么、失败时会怎样、被滥用时会怎样。
代码评审时优先问这 12 个问题
这部分适合直接复制到合并请求模板中。每次评审不一定逐字回答,但涉及认证、权限、敏感数据、外部输入或依赖变更时,应强制检查。
- 这个改动是否引入了新的外部输入?输入在哪里完成服务端校验?
- 是否有用户可控数据进入查询、命令、模板、表达式或文件路径?
- 这个接口是否只检查了登录,而没有检查资源级权限?
- 前端隐藏入口后,后端是否仍能拒绝未授权访问?
- 是否新增或修改了敏感数据的采集、存储、展示、导出或日志记录?
- 错误信息会不会暴露内部实现、路径、依赖或调试细节?
- 日志是否足够排查问题,同时避免记录凭证和敏感字段?
- 是否引入了新的第三方依赖?用途、来源和维护责任是否清楚?
- 是否修改了默认配置、调试配置、发布配置或访问控制配置?
- 关键状态是否由服务端根据规则计算,而不是完全信任客户端传值?
- 是否存在批量操作、跨租户访问或越权读取的可能?
- 这个功能被异常使用或恶意滥用时,当前设计是否仍能限制损害?
初创团队最容易踩的误区
把 OWASP 清单当成合规材料,是第一个误区。清单如果只存在于文档库里,不进入需求、编码、评审和发布流程,基本不会改变漏洞出现的概率。更有效的做法是把它拆成少量强制问题,嵌入每次合并请求和上线检查。
第二个误区是只关注注入类漏洞。注入当然重要,但 OWASP Top 10:2025 已经把访问控制、安全配置、供应链、完整性和不安全设计都放在很高的位置。早期团队如果只写“防注入规范”,会漏掉权限、依赖、配置和设计层面的系统性风险。
第三个误区是把安全责任交给某一个人。初创团队可以没有专职安全工程师,但不能没有安全编码约定。认证组件怎么用、权限在哪里判断、依赖如何引入、日志能不能记录敏感字段,这些都应成为开发团队共同遵守的工程规则。
第四个误区是过度追求一次性完美。早期项目更适合从高风险路径开始:登录、权限、支付或订单、后台管理、文件上传、敏感数据、依赖引入、发布配置。先让这些路径有明确规则,再逐步扩展到全项目。
建议放入项目规范的最小版本
如果团队现在没有任何安全编码规范,可以先从下面这段开始。它足够短,便于执行,也覆盖了 OWASP 安全编码实践中最容易影响结果的部分。
所有外部输入默认不可信,必须在服务端按业务允许范围校验;所有受保护资源必须执行服务端授权检查;禁止将用户输入直接拼接进查询、命令、模板或解释器上下文;敏感数据不得写入日志、URL、错误信息或代码仓库;认证、会话、权限和加密能力应使用统一组件;新增依赖、配置变更、文件上传、关键数据变更和高风险接口必须进入代码评审;默认配置应偏向安全,调试能力不得进入生产环境;安全限制应在设计和编码前确定,而不是上线后补救。
这段不是终点,而是团队安全编码的最低线。等项目进入稳定迭代后,再把输入校验、输出编码、访问控制、依赖治理、错误处理和完整性保护分别细化成团队自己的示例代码、评审问题和发布检查项。这样使用 OWASP,才不会停留在“知道风险名称”,而是能真正减少漏洞进入代码库的机会。

山东省烟台市 1F
这个清单对初创团队太实用了,直接能落地
上海市 B1
@ 无极剑主 清单落地性强,尤其适合资源有限的早期团队
江西省南昌市 2F
权限校验真该进评审模板
甘肃省 3F
我们公司就是先把权限校验散落在各个接口,后面改起来很痛苦
上海市南汇区 B1
@ 夜莺的挽歌 没有专职安全人员时,可以轮流负责代码安全审查
上海市嘉定区 4F
想问一下,如果没有专职安全,怎么保证代码评审时能覆盖这些问题
甘肃省 5F
把安全编码要求嵌入PR模板确实是个好办法,比单独文档有效
上海市崇明县 6F
供应链安全这块,小团队怎么平衡效率和依赖审查
上海市松江区 B1
@ 终末巫师 供应链安全确实是个难题,效率和安全很难兼顾
上海市奉贤区 7F
我们之前就因为日志里记录了token,差点出问题,后来才加上脱敏
山东省烟台市 8F
最小版本那段可以直接抄进项目规范,够简单
重庆市 B1
@ Social Butterfly 最小版本确实容易执行,我们先拿它做评审卡点
山东省烟台市 9F
安全配置错误真的是常犯,上线前才发现测试配置没关
广东省深圳市 B1
@ 风吟翠竹 配置开关遗漏太常见,现在我们用检查清单强制走查
重庆市 10F
好奇这个清单和实际开发流程结合,有没有推荐的落地工具
广东省深圳市 B1
@ 骨伞倩女 回复目标评论 39595:目前常用的有 Snyk 和 SonarQube
重庆市 11F
作为前端,现在更清楚哪些安全边界不能只靠前端了
日本 12F
依赖引入这块确实容易被忽略,等出问题就晚了
上海市青浦区 13F
访问控制必须服务端兜底,前端隐藏真不靠谱
山东省烟台市 14F
日志脱敏规则得提前定好,不然review时容易漏
甘肃省 15F
依赖审查可以先从高风险包开始,逐步覆盖
河北省石家庄市 16F
设计阶段就把安全前置检查做了,真能省不少事
重庆市 17F
PR模板加安全问题后,明显感觉漏洞少了
广东省深圳市 18F
统一认证组件能避免很多重复踩坑
上海市松江区 19F
敏感操作最好二次确认,不能光靠会话状态
山东省烟台市 20F
设计阶段就该考虑滥用场景,否则后期难补
广东省深圳市 21F
权限一旦散落在各处,重构成本真的很高
广东省深圳市 22F
小团队可以先用自动化工具扫一遍依赖漏洞
广东省深圳市 23F
有没有适合初创团队的轻量级代码扫描工具推荐
甘肃省 24F
我们也是后来才发现前端隐藏根本挡不住接口调用
上海市 25F
把清单里的检查项直接加进 CI 流程可能更实用
山东省烟台市 26F
统一认证组件能避免很多重复踩坑,这点很认同
甘肃省 27F
敏感数据脱敏规则最好写在开发规范里强制执行
广东省深圳市 28F
设计阶段如果不考虑滥用场景,后期修补太被动
山东省烟台市 29F
日志记录太多敏感信息,排查时反而容易出事
上海市浦东新区 30F
这个清单对刚起步的团队来说非常及时且必要
上海市嘉定区 31F
PR 模板加上安全问题后,大家写代码会更小心
上海市徐汇区 32F
把清单拆成合并请求里的几个必答问题,比单独一份文档管用多了。
重庆市 B1
@ 玉匠高二四 对,文档没人翻,但 MR 模板里几个必答项躲不掉。我们就留了三条,写不清楚的直接打回,比长清单好用😂
浙江省杭州市 33F
依赖来源和维护责任这块确实容易被忽略,得记下来。
北京市 B1
@ 黑曜预言家 对,依赖装上就没人管了,出问题才发现维护者早跑了😅 建议顺手记下引入原因,后面要不要换也好判断。