Vibe Coding 项目上架前必做的安全合规自查清单
上个月一个做独立开发的朋友火急火燎找到我。他花了一个周末靠 AI 聊天框“聊”出来一个记账 App功能齐全界面也像模像样准备提交应用商店。结果审核邮件回来那天他整个人懵了——隐私政策缺失、后台定位权限没有用途说明、缓存里居然能看到用户明文密码。他原话说“AI 写的时候口口声声说没问题怎么一到上线全是问题”这基本就是 Vibe Coding 开发者的共同困境。Vibe Coding就是用自然语言描述需求、让 AI 生成代码开发者主要负责审查、调整和整合。效率确实夸张一个人能干过去一个小组的活。但“能跑”和“能上线”之间隔着一整条合规、安全、稳定性的鸿沟。AI 帮你在几小时内把代码写完却没有任何人替你做上线前的那套系统性体检。我平时的工作里接触了不少 Vibe Coding 出来的项目也踩过很多雷。这篇文章就把 App 上线前需要过的关卡按我的实操经验完整梳理一遍。适合两类人看一类是第一次用 AI 辅助做出完整产品、准备上架的个人开发者另一类是团队已经用 Vibe Coding 提效、但担心质量失控的技术负责人。内容没有高深理论全是能直接对着勾的检查项和踩过的坑。1. Vibe Coding 的代码质量真相为什么“能跑”和“能上线”是两回事1.1 Vibe Coding 解决了什么问题又带来了哪些新问题Vibe Coding 最爽的地方在于你不用再一行行敲业务代码。你把需求描述清楚AI 帮你把页面、接口、数据模型一次性生成。遇到报错直接把错误信息丢回去AI 会自己改。这个正反馈循环非常强所以很多人一旦习惯 Vibe Coding就很难回到纯手写的状态。但这里有个关键认知AI 优化的目标是“让对话继续下去”不是“让代码达到生产环境标准”。它会倾向于给出一个在当前上下文里看起来正确、能通过简单测试的方案而不是一个经过审计、考虑了异常路径、遵循了你团队编码规范的生产级实现。也就是说AI 生成的代码天然从“demo 质量”起步需要人工把它推到“生产质量”。我审视过的 Vibe Coding 项目里代码问题通常集中在三类。第一类是错误处理缺失AI 默认所有请求都成功、所有输入都合法第二类是安全细节粗糙密钥、Token、用户密码这类敏感信息经常被随意存放第三类是状态管理混乱尤其是异步操作、并发访问、页面销毁这些场景AI 很少主动考虑边界。这三类问题不一定会让你在开发期崩溃但上线后全都会变成用户投诉。1.2 AI 代码的隐性风险看着没错实际错的三种模式先从代码层面说几个 Vibe Coding 项目里反复出现的典型问题模式。理解它们后面检查时才知道该往哪里看。第一种叫“乐观编程”。AI 写接口调用时几乎不写失败分支。你看到的是await api.fetchData()之后直接拿返回值渲染页面默认一定会成功。一旦真实环境里网络超时、后端返回异常数据App 直接白屏或者闪退。当你要求 AI 补上错误处理它往往只加一个catch然后打印日志而不是设计对应的兜底 UI 和用户提示。这种代码在 demo 时完全没问题因为开发环境的后端永远是友好的。第二种叫“一次性代码”。AI 生成的代码围绕当前需求拼凑不考虑复用和扩展。比如登录模块里把 Token 存到了本地一个固定的 key另一个页面需要用户信息时又重新写了一份存储逻辑。你改一处另一处还在用旧逻辑就会冒出非常难排查的怪问题。这类代码的典型特征是同一种功能出现多份实现彼此之间还有微妙差异。第三种问题比较讽刺叫“过度封装”。为了让代码看起来整洁、专业AI 会引入大量抽象层、工具类、枚举、泛型。在小项目里这些抽象带来的维护负担远超过它们节省的重复劳动。我见过一个 Vibe Coding 项目一个简单的列表页AI 生成了六个文件——三个协议、两个工厂、一个 Manager。功能没有任何问题但后来想改一个字段翻了半天文件还没找到定义在哪。这三种模式不一定让 App 立马上不了线但它们是上线之后所有偶现 bug 的温床。记住一个原则审查 AI 的代码时别只看“对不对”要看“错了会发生什么”。提示在 Vibe Coding 的工作流里开发者真正的核心价值不是“写代码”而是“做判断”。AI 负责把方案生成出来你要负责判断它在生产环境里是否成立。1.3 检查不是走过场而是替 AI 补上生产视角很多 Vibe Coding 开发者对“检查清单”有抵触觉得多此一举。我的看法恰恰相反正因为代码不是自己一行行写出来的才更需要一套系统性的检查流程。手写代码时很多潜在问题在处理过程中你多少会有印象AI 生成代码时你对内部实现的熟悉程度和掌控感天然更低。这里的关键是把检查分成两个层次。第一层是定位问题——通过静态扫描、依赖审计、权限配置核对把明显的坑找出来。第二层是主动防御——设计破坏性测试、真机演练、灰度发布把隐藏的风险挡在上线之前。下文所有检查项都是围绕这两层逻辑展开的你不需要全部做完才能上线但每一项都能显著提高你上架成功的概率。2. 第一道体检依赖、权限和隐私合规AI 生成内容最容易全绿也最容易全漏2.1 依赖审计AI 帮你装的库你真的认识吗我检查 Vibe Coding 项目时第一件事永远是看依赖清单。原因很简单——AI 为了完成某个功能会非常积极地引入第三方库而且它会优先选择“搜索结果里最常见”的方案不一定是最合适、维护最活跃的方案。更麻烦的是有些库已经被弃用或者存在已知安全漏洞AI 并不会主动告诉你。具体操作分三步。第一步用工具扫描依赖。前端项目跑npm auditAndroid 项目检查 Gradle 依赖树iOS 项目检查 CocoaPods 或 Swift Package Manager。重点看有没有高危漏洞提示。第二步逐个人工确认每个依赖的必要性。我的习惯是反问 AI 一句“这个功能不用第三方库自己写需要多少行”如果答案是几百行以内我倾向去掉依赖减少供应链风险。第三步固定依赖版本。lodash: ^4.17.21这种写法一次npm install可能把子依赖更新到预期之外的版本上线前务必把版本 lock 住。这里有个真实的教训。某开发者用 Vibe Coding 做图片处理 AppAI 推荐了一个压缩库。功能确实实现了但那个库的老版本存在一个已知漏洞用户上传的图片要经过该库处理等于把漏洞暴露给了攻击者。审核时被安全检测拦下来整款 App 被迫回退版本重新走流程。整个过程完全可以通过上线前的一次npm audit避免。2.2 权限声明宁可少要绝不冒进Vibe Coding 项目里权限声明是最容易“全绿”也最容易“全漏”的部分。AI 生成代码时为了省事经常在配置里一次性声明大把权限。我见过一个只用到网络请求的笔记类 App权限清单里却躺着读取联系人、获取位置、录音三项敏感权限。应用商店审核非常看重权限和实际功能的匹配度申请了权限却说不清楚用途轻则审核拒绝重则被标记为违规。我的建议是把权限分成两级。第一级是 App 核心功能必需的权限保留并写好用途描述第二级是非必需权限全部移除。对于保留的权限必须在隐私政策里写清楚用来干什么、在什么场景下触发、数据是否上传服务器。特别注意后台定位、通讯录、相册这类敏感权限上线前一定做一次真机权限弹窗的完整流程测试确认用户点“拒绝”之后 App 不会闪退还能用其他方式继续完成功能。另外Android 和 iOS 的权限机制差异很大。Android 的权限在清单文件里声明部分危险权限需要在代码里动态申请iOS 的权限在使用时弹窗还要在 Info.plist 里写清楚用途描述。AI 生成的跨平台项目经常只处理了某一端的逻辑。我上线前会做一张权限对照表左边是代码里申请的权限右边是功能流程里实际会触发的弹窗逐项核对不匹配的一律改掉。2.3 隐私政策与数据声明这些内容 AI 帮不了你隐私合规这一关Vibe Coding 开发者特别容易翻车因为 AI 不会主动帮你生成隐私政策也不会告诉你哪些数据需要声明。我的经验是凡是没有隐私政策、或者内容明显是复制粘贴模板的 App被拒率几乎百分之百。隐私政策不是应付审核的摆设它是你和用户之间关于数据怎么用的一个契约。隐私政策至少要覆盖这些内容收集了哪些数据包括用户主动输入的、设备自动上报的、第三方 SDK 采集的这些数据用来做什么是否与第三方共享用户如何删除数据、注销账号。尤其要注意第三方 SDK 的收集行为——很多统计 SDK、广告 SDK 会自动采集设备信息如果隐私政策里只写了你自己收的数据没提 SDK 的行为审核一样会拒绝。一个容易被忽略的细节是账号注销功能。现在主流应用商店对“提供账号注册就必须提供注销渠道”执行得很严格。AI 生成的登录模块通常只实现了注册和登录注销功能大概率没有。上线前一定确认账号体系里有注销入口而且要真的能走通流程不是点进去弹一个“暂不支持”的对话框。3. 数据持久化与后端接口AI 最容易埋雷的两个位置3.1 本地存储明文、缓存、版本迁移的三连坑AI 生成的代码里本地存储是最随意的部分。我见过 AI 用SharedPreferences或localStorage直接存用户密码的也见过把登录 Token 放进全局静态变量、App 一切到后台就丢登录态的。这些问题的根源在于AI 不理解“敏感数据”和“持久化存储”之间的概念边界。处理思路其实很简单先给数据分类再决定存储方案。公开数据比如用户昵称、主题偏好可以放普通本地存储敏感数据比如 Token、密钥、手机号必须放进安全存储区域——Android 上使用 EncryptedSharedPreferences 或 KeystoreiOS 上使用 Keychain前端也可以用加密方案做处理。这一条不需要高深的安全知识但能直接决定你 App 的安全底线。另外两个高频问题缓存清理和版本迁移。AI 生成的图片缓存逻辑经常是“只写不删”时间一长 App 体积膨胀到几百兆。上线前检查缓存目录有没有设置大小上限、有没有清理时机。版本迁移的问题更隐蔽——凡是持久化数据的 App都要考虑用户从旧版本升级时本地数据结构不兼容怎么办。AI 生成代码往往直接改数据结构没有任何迁移逻辑。上线前想一下如果用户手机里存着上一版的数据新版还能不能正常读要么做数据迁移要么做容错处理不能假设每个人都是全新安装。3.2 接口连接AI 天然忽略的边界条件Vibe Coding 对接后端接口最典型的问题还是“乐观编程”。我在检查时会用一套标准去审视每一处接口调用网络不可用时用户看到的是友好的提示还是无限 loading接口返回非 200 状态码时App 是给出明确错误信息还是直接崩溃业务错误码比如“账号已注销”有没有对应的用户提示超时时间是否合理在弱网下实测过吗下拉刷新和分页加载时有没有处理重复请求、并发竞态的情况为了测试这些问题上线前我会专门做一轮“破坏性测试”。把手机开成飞行模式把后端接口临时改错把返回的数据结构改成缺字段少字段。每一项都看看 App 的表现。AI 生成的代码在这种测试下通常撑不过两轮就现原形。这倒不是否定 AI而是说明错误处理的补齐工作必须由人来完成。还有一个细节容易被忽略接口的幂等性。如果用户连续点击两次“提交订单”AI 生成的代码会不会提交两个订单这类问题在交互层面可以用防重复提交的锁来解决在后端层面则需要接口本身支持幂等。Vibe Coding 项目里这两层往往都没有最好都补上。3.3 密钥与鉴权把钥匙放在包里等于没锁门上架审核里有一个近乎一票否决的检查项硬编码密钥。很多 Vibe Coding 项目里API Key、第三方服务的 Secret、云存储的 AccessKey直接写在代码里甚至直接出现在前端请求参数中。这样的 App 即使通过了审核一旦密钥泄露你云资源里的数据、账单都被暴露给所有人。更常见的情况是有些个人开发者把 GitHub 仓库设成公开密钥跟着代码一起被所有人看见。正确做法是前端不放任何敏感的长期密钥。需要后端通信时使用用户维度的短期 Token第三方服务的密钥只放在后端环境变量里由后端代为调用如果项目没有后端至少也要区分清楚公钥和私钥的概念私钥类信息绝不进客户端代码。有些人会想用“代码混淆”来隐藏密钥但这只是提高了一点逆向门槛本质上密钥还是在客户端手里该泄露还是会泄露。这一条没有商量的余地。上线前用 grep 或者专门的密钥扫描工具在代码库里搜一遍常见的密钥特征比如api_key、secret、password附近的字面量发现硬编码一律替换。这个操作五分钟能完成但能拦住绝大多数安全审核问题。4. 从 debug 到 release构建、签名与第三方服务的最后一个关口4.1 Debug 和 Release 的行为差异越晚上线越致命Vibe Coding 开发过程中你基本都在 debug 模式下运行。但 debug 模式和 release 模式存在大量隐形差异这些差异在开发期完全不会暴露上线后却会变成线上事故。最典型的是两类。第一类是构建优化差异。release 模式开启代码压缩、混淆、资源压缩后可能出现 debug 模式下从来没有的问题。比如 Android 的 R8 混淆规则没配好release 包运行时会直接找不到类iOS 的编译优化也可能改变某些代码的行为。更麻烦的是热加载、调试日志这类 debug 功能在 release 包里被移除上线后如果你想靠日志排查问题会发现什么都打不出来像个盲人摸象。第二类是环境配置差异。很多 Vibe Coding 项目里后端地址直接写成一个常量你开发时连的是测试环境忘了改成生产环境。这种问题在代码 review 里很难发现但一旦上线所有用户的数据都会写进测试库相当于你的生产环境根本没有真正启用。强烈建议在项目里引入按环境隔离的构建配置debug 和 release 使用不同的配置文件和接口域名。上线打包前人工确认一次 release 包的接口地址、推送证书、统计 AppKey 都是生产环境的值。这套流程做成一个打包前核对单能帮你少经历几次半夜被用户反馈惊醒的惊魂事件。4.2 签名、证书与商店审核AI 帮不了你的部分签名和证书这件事对第一次上架的个人开发者来说是最容易被教程和 AI 忽略的部分。Android 的上架签名、iOS 的证书和描述文件任何一个环节配错都会导致应用商店直接拒绝或者包无法被正常下载安装。而且这些跟账号体系强相关AI 完全帮不上忙只能自己一步步走通。我的建议是提前三天开始处理签名和证书千万别放在上架当天。Android 的正式签名密钥一定要多重备份。Keystore 文件、别名、密码三个信息缺一不可丢了任何一个都等于丢了更新 App 的钥匙——你以后发的新版本将无法覆盖旧版本。iOS 的证书和描述文件要注意有效期很多人同一套证书用了很久突然某天发现描述文件过期了打包失败。把证书的有效期记在日历上提前留好续期时间。还有一个常见坑是包名和应用 ID。Vibe Coding 项目创建时AI 或脚手架会随机生成一个包名。这个包名一旦对外发布后续修改的成本极高因为应用商店、消息推送、社交登录都绑定它。上线前想清楚最终使用的包名尽早固定下来。我见过有人上线后嫌包名不好看想换结果只能重新提交一个新的应用之前的用户积累和评论全部作废。4.3 第三方 SDK 的合规影响比功能冲突更致命第三方 SDK 是另一个合规重灾区。Vibe Coding 项目为了快速实现统计、推送、支付、社交登录AI 往往一次性引入多个 SDK。这些 SDK 带来的问题远不止功能层面的互相冲突更关键的是数据合规和隐私声明。很多第三方 SDK 在后台默认采集设备信息和使用行为如果你的隐私政策里没有声明就属于不合规。我自己的做法是为项目里的每个第三方 SDK 建一张清单表登记以下信息SDK 名称和版本、用途、是否采集用户数据、采集什么数据、数据是否上传第三方服务器、隐私政策里是否已声明。这张表看起来繁琐但在审核被问询时非常有用。你不需要等审核方来抽查而是把所有信息预先整理好问什么答什么这种主动姿态能省掉很多来回沟通的时间。另外SDK 的初始化时机值得特别注意。严格来讲在用户明确同意隐私政策之前不应该初始化任何采集用户数据的 SDK。AI 生成的代码通常会在应用启动时一股脑初始化所有 SDK这是不合规的。正确做法是把非必要 SDK 的初始化延后到用户授权同意之后。这个改动对审核结果的影响比很多人想象的大得多。5. 真实事故复盘Vibe Coding 上线后的典型崩盘场景5.1 崩溃日志里最常出现的三类错误上线之后的崩溃监控会很快打脸“AI 信誓旦旦没问题”的结论。我翻过几个 Vibe Coding 项目的崩溃日志高频问题集中在三类。第一类是空值和空指针访问。AI 生成的代码经常从接口返回值、字典、数组里直接取值却从不判断对象是否存在。后端一次结构调整或者某个字段恰好为空值线上直接崩。第二类是类型转换错误。接口返回的数字在某种场景下变成了字符串代码拿到后按数字处理JSON 解析就地爆炸。第三类是资源问题最常见的是内存不足和文件并发读写。图片加载没有解压和缩放策略用户一次性刷出大量高清图内存直接顶满被系统杀掉。这三类错误有一个共同特点在开发者自己测试时根本不容易触发。但线上用户设备千奇百怪、操作路径五花八门、后端数据变幻莫测再小的概率问题也会被放大成事故。所以上线前的破坏性测试和上线后的崩溃监控都不是可选项而是必选项。5.2 主线程卡顿与内存泄漏AI 之手的隐蔽问题Vibe Coding 项目里主线程卡顿几乎是标配。AI 生成代码时习惯把耗时操作直接写在页面加载逻辑里比如在主线程上同步读取本地文件、解析大 JSON、做图片压缩。开发时数据量小感觉不明显用户数据一多页面就会卡住甚至触发系统的“App 无响应”弹窗。检查方法并不复杂。Android 上可以用 Profile 工具抓一段性能数据看主线程有没有过长的耗时段iOS 上可以用 Time Profiler 分析采样。凡是会阻塞 UI 的操作——网络请求、数据库查询、图片处理、文件读写——都应该放到后台线程执行再回到主线程更新页面。AI 不是不会写多线程而是你要明确告诉它“这个操作必须放在子线程”它才会这么写。内存泄漏是另一个隐形坑。AI 经常在页面关闭后仍然持有页面实例的引用比如异步回调里更新已经销毁的页面或者把页面对象传给了全局单例。用户反复进出页面内存不断上涨直到系统强制杀掉进程。这个问题很难靠静态代码审查直接发现通常要靠泄漏检测工具和长时间真机操作来暴露。上线前做一轮“反复进出同一页面 50 次”的笨办法测试比很多高级分析都管用。5.3 弱网、离线与并发AI 没有教你的边界情况Vibe Coding 生成的业务逻辑默认前提是“网络永远正常、服务器永远在线、用户永远按顺序操作”。现实显然不是这样。Vibe Coding 出来的 App 上线之后的差评来源一半以上来自弱网和离线状态下的糟糕体验。弱网场景的检查重点是请求超时时间设置是否合理、失败后有没有重试机制、加载失败时用户能否看到上次的缓存内容而不是一片空白。离线场景的重点是完全没有网络时打开 App 会怎样是闪退、无限转圈还是能正常看到上一次加载过的数据这两个测试不需要高深手段开着飞行模式把核心流程走一遍就行。并发问题则更隐蔽。用户的点击速度往往比你想的快得多比如“提交订单”按钮被连续点了两下AI 生成的代码很可能就会提交两个订单。再比如下拉刷新和上拉加载同时触发的时候列表数据是否错乱。这类问题需要在按钮提交时加防重复操作的锁在列表加载时加请求标记来丢弃过期响应。这些模式手写开发者都有肌肉记忆AI 则需要你明确给它约束才会生成正确版本。6. 上线前 72 小时一份可以直接抄的检查清单6.1 功能层面先跑通主流程再跑通异常流程到了这个阶段不要再加任何新功能把所有精力放在验证上。第一优先级是核心主流程注册登录、首页加载、核心业务操作、支付如果有必须完整走通。第二优先级是异常流程网络断开、权限拒绝、接口报错、后端服务不可用时App 的表现是否体面。我习惯把手机上的 App 当成一个“什么都不懂的普通用户”把每个按钮都点一遍每一步操作都故意用错误方式尝试。这台设备上的体验某种程度上才是用户真实的体验。另外至少要在两台不同系统版本、不同屏幕尺寸的真机上跑一遍。模拟器永远不等于真机很多传感器、定位、推送相关的问题只有在真机上才会复现。预算有限的话也请保证 Android 和 iPhone 各有一台跑完核心流程再提审。6.2 数据与安全密钥、日志、测试数据的三连清理上线打包前的数据检查核心是三件事清日志、换环境、扫密钥。AI 生成的代码可能在不经意间打印大量日志里面包含用户手机号、Token 等敏感信息。release 包里最好直接关闭日志输出既不安全又影响性能。测试数据清理同样容易被忽略。我遇到过开发者在生产环境数据库里塞满测试账号上线后用户看到的推荐列表全是测试留下的垃圾数据。上线前把数据库、缓存、用户反馈邮箱等所有涉及数据的地方都切换到干净的生产环境。密钥扫描再执行一次确认没有硬编码的 Token 或者 Secret 残留。这三个动作在任何 Vibe Coding 项目里都不该省加起来只需要半小时能帮你拦下大部分上线后的低级事故。6.3 构建与发布从零跑一次干净的 release 包上线前一天从零开始跑一次干净的 release 构建不要用你本地一直增量编译的缓存。构建完成之后把安装包装到一台没有开发环境的干净手机上用这个包完整走一遍新用户流程。这一步能暴露很多“只有开发机才会正常”的隐性依赖比如某些配置文件只在 debug 环境存在或者某个调试开关只有连接开发机时才有效。如果你的 App 有登录功能用“卸载重装”的方式测一遍确认从全新状态开始的用户流程是顺滑的。很多人开发时一直带着登录态测试永远不知道第一次打开 App 时到底会发生什么。这轮测试通过之后再申请应用商店的审核通过率会有肉眼可见的提升。6.4 上线不是终点提前布好灰度与监控至少在正式提交应用商店之前你就应该确认崩溃监控 SDK 和统计 SDK 的初始化代码是正确配置的确保上线当天就能看到线上数据。Vibe Coding 项目里这一步经常被完全漏掉——上线出了问题连一份像样的崩溃日志都拿不到排查全靠用户描述。有条件的话务必做灰度发布。Vibe Coding 项目的代码质量不确定性天然更高灰度的比例值得控制得更小。先让一小批真实用户使用观察崩溃率和核心功能漏斗确认稳定之后再放开全量。我自己见过太多项目因为跳过灰度直接在应用商店放出全量包一个崩溃率 5% 的版本被所有用户下载差评爆炸后才紧急回滚。灰度这几小时省下来的是后面几天的救火时间。最后说点个人体会。Vibe Coding 确实改变了做产品的方式一个人能写出过去一个团队才能交付的 App这在几年前是不敢想象的。但恰恰因为速度快上线前的检查就变得更重要。你花一小时让 AI 生成代码就要花一天去验证它、测试它、补全它。这不是否定效率而是对效率负责。我现在的工作方式是把 Vibe Coding 当成一个能力很强但经验不足的初级工程师它会写代码但需要有人做 review、做测试、做发布管理。这份清单里的每一项本质上都是那个 review 角色要做的事情。希望它能帮你在上线的路上少踩几个坑尤其是那些 AI 不会告诉你的坑。