Precheck:在移动扫描运行数小时之前,先确认它能正常工作
Precheck 会在真机上验证移动应用能否安装、启动、登录并执行 UI 提示词。当凭据被拒绝、应用崩溃或构建版本无法安装等阻断问题导致无法覆盖应用时,扫描会被标记为错误,并附上原因以及显示该问题的界面。
一次没有任何发现的移动扫描,理应说明应用是安全的。但很多时候,它只说明应用从未越过登录界面。
Precheck 是 Ostorlab 移动扫描中新增的一个步骤。它在所有移动动态扫描中运行:在真机上安装应用、启动应用、使用您提供的凭据登录,并执行您的 UI 提示词。如果遇到阻断问题,例如构建版本无法安装、应用崩溃或卡死、凭据被拒绝,扫描会被标记为错误,您会得到原因以及能够证明该问题的界面截图。
扫描会在后台继续运行,因此您仍然可以获得静态分析结果,以及部分可用的应用所能提供的动态覆盖结果。
Precheck 做什么?(TL;DR)
Precheck 确认应用确实可以被测试。当阻断问题导致无法测试时,Precheck 会将扫描标记为错误,并添加指向 UI 调用图的 Learn more 链接;调用图中的每个界面都按状态着色。静态分析以及所有可达的动态覆盖仍会照常完成。
为什么空报告是最糟糕的报告
一次完整的移动扫描会并行运行多项分析:静态分析、动态分析、调用跟踪和流量拦截。这些分析加起来可能需要数小时。而动态覆盖取决于一件事:应用必须能在设备上真正运行并可用。
如果做不到,扫描仍然会“完成”:
- 构建版本面向设备不支持的架构,因此根本无法安装。
- 应用在启动画面崩溃,或者卡死。
- 预发布环境的密码上周已过期,因此所有需要身份验证的界面都无法到达。
- 未配置 2FA 步骤,因此应用一直在等待验证码。
- 预发布环境的后端宕机,因此应用显示“Unable to connect”,之后什么也做不了。
在上述每种情况下,动态分析只能探索它能到达的部分,报告的内容寥寥无几,甚至为空。一次失败运行产生的“安静”报告,与一个安全应用产生的“安静”报告看起来毫无区别。您要在数小时后才会发现问题,甚至根本发现不了。
在 CI/CD 流水线中,一条因错误原因而通过的流水线,比一条失败的流水线更糟糕。
Precheck 正是为消除这种不确定性而设计的。
Precheck 检查哪些内容
Precheck 按顺序执行两项检查。如果应用无法安装,则跳过 UI 检查。
1. 构建版本能否安装到设备上?
Precheck 获取一台真机,将其重置为干净状态,然后安装您的构建版本。它不会止步于“安装程序返回成功”,还会确认应用确实存在于设备上:
- Android(APK、AAB、XAPK):该应用包必须出现在设备的已安装包列表中。Precheck 还会从二进制文件中读取应用的启动 Activity。对于 XAPK 包,它会逐一搜索每个拆分 APK,直到找到基础 APK。
- iOS(IPA):该 bundle 必须出现在设备的已安装应用中。Precheck 会读取 bundle 的
Info.plist,并根据设备检查 bundle 标识符、最低 iOS 版本以及所需的设备能力。
无法安装的构建版本会被报告为错误:没有它,任何动态分析都无法进行,但静态分析仍会运行。
2. 应用能否启动、登录并执行您的提示词?
随后,Precheck 将应用交给 Monkey Tester,即 Ostorlab 用于操作移动应用界面的 AI 智能体。Precheck 会向它传递:
- 要使用的设备,
- 您配置的凭据(用户名和密码、自定义键值字段,以及 SMS、电子邮件、TOTP 或手动 2FA),
- 您的 UI 提示词,即您用自然语言给扫描下达的指令,例如“接受条款,跳过新手引导,打开转账页面”。
Monkey Tester 会启动应用、登录,并逐条执行每个提示词。它不只是截图:它会对到达的每个界面作出判定。
每个界面都有判定结果
对于每张截图,Monkey Tester 会返回四项信息:
| 字段 | 含义 |
|---|---|
prompt |
截图时正在执行的是您的哪条提示词(如有) |
status |
ONGOING、SUCCESS、ERROR 或 CRITICAL |
reason |
界面上的哪些内容导致了该状态 |
remediation |
针对 ERROR 和 CRITICAL,您可以采取的措施 |
- ONGOING:该步骤正在进行,目前尚无异常。
- SUCCESS:提示词已完成,且结果在界面上可见。
- ERROR:提示词执行失败(例如按钮被禁用,或转账未能完成),但应用仍可正常工作。
- CRITICAL:真正的阻断问题。您提供的凭据被拒绝,或者应用反复崩溃、卡死。
每个界面都会标记其状态,让您一眼看出哪些正常、哪些有问题,而且每个状态都附有具体的原因说明和修复方法。
下面以一次针对 Duolingo 的扫描为例,其中的 UI 提示词要求 Monkey Tester 先开始一门法语课程,再开始一门格鲁吉亚语课程。
SUCCESS:登录。Monkey Tester 到达了主界面,证明凭据有效。

SUCCESS:提示词已完成。法语课程设置界面已打开,因此该提示词被标记为已完成。

ERROR:无法完成的提示词。Duolingo 不提供格鲁吉亚语课程,因此该提示词执行失败。应用仍可正常工作,所以这是 ERROR,而不是阻断问题。

CRITICAL:凭据被拒绝。应用显示“Wrong username or password”,因此登录之后的任何内容都无法测试。

reason 描述的是您这一侧出现的问题,例如错误消息、被拒绝的密码或缺失的权限。一个真实示例的结尾就是修复方法本身:
输入所提供的凭据后,身份验证失败,并显示明确的“Wrong username or password”消息。修复建议:为测试账户提供有效的 Duolingo 凭据。
Precheck 失败时您会看到什么
当扫描被标记为错误时,扫描页面会显示原因,并提供一个 Learn more 按钮,点击后会在失败的界面处打开 UI 调用图。UI 调用图是 Monkey Tester 到达的所有界面及其之间跳转关系的地图,每个界面都按其 Precheck 状态着色。
深入原理:Precheck 是如何构建的
Precheck 作为一个独立的轻量级步骤运行:Monkey Tester 对每个界面做出判定,而是否将扫描标记为错误,则由 Precheck 做出最终决定。
一个独立的步骤,而不是给每项分析增加工作
最直接的捷径是在每项动态分析中加入健康检查。我们没有这样做,原因有两个。
- 尽快给出第一个答案。深度动态测试需要完整的设备准备,例如配置流量拦截。而回答“这个应用能否启动?”并不需要这些,因此 Precheck 跳过了它们。被测对象只有应用本身。
- 在同一个地方做出决定。如果每项分析各自检测失败,就会得到相互矛盾的判定。一个独立的步骤能给出一个明确的答案。
因此,Precheck 作为一个独立的轻量级步骤,与扫描的其余部分并行运行。
模型负责判定,代码负责决定
Monkey Tester 的模型原本就在决定下一步点击什么。我们对其进行了扩展,使它在每一步还会返回当前正在执行的提示词、状态、原因和修复建议。
模型被要求:
- 仅在出现明确的阻断问题时使用
CRITICAL, - 仅在确实提供了凭据时才报告登录失败,
- 将每条原因写成修复方法,例如写“设置 SMS 2FA 的号码”,而不是“需要 2FA”。
模型对每个界面给出判定。而将扫描标记为错误的决定,由 Precheck 综合所有这些判定后作出,因此单个被误判的界面不会导致一次明显在推进的扫描被标记为错误。
先有证据,后有判定
Monkey Tester 访问的每个界面,连同其截图、状态、原因和关联的 UI 提示词,都会在 Precheck 作出决定之前保存下来。因此,当扫描被标记为错误时,证据已经就位,“Learn more”链接打开的始终是一张完整的调用图。
这些判定结果也可以通过 Ostorlab 的 API 和 MCP 工具获取,因此接入 Ostorlab 的 AI 编程助手可以解释 Precheck 失败的原因。
充分发挥 Precheck 的作用
大多数 precheck 错误都源于扫描配置,因此最重要的有三项:凭据、以目标形式编写的 UI 提示词,以及 2FA 配置。
- 对于任何需要登录的应用,请提供凭据。这样,Precheck 就能在扫描的其余部分依赖这些凭据之前先对其进行检查。
- 以目标的形式编写 UI 提示词,例如“打开账户设置页面”,而不是坐标或精确的点击序列。当目标在界面上可见时,Precheck 会将该提示词标记为成功。
- 如果您的登录流程有此要求,请配置 2FA(TOTP 密钥、SMS 或电子邮件收件箱)。未被应答的 2FA 界面会被视为阻断问题。
- 在 CI/CD 中,请将 Precheck 错误视为流水线步骤失败。错误消息会告诉您在重新运行流水线之前需要修复什么。
只有真正运行过的扫描才值得信任
一次安全扫描的价值取决于它是否真正运行过。Precheck 会使用真机、应用的真实界面以及您自己的凭据和提示词,验证扫描能否运行。如果不能,扫描会被标记为错误,您会得到原因、建议的修复方法以及显示问题的界面,而不是在几个小时后收到一份“安静”的报告。
与此同时,扫描会继续进行,并交付它能得到的所有结果。
Precheck 在所有面向 Android 和 iOS 的 Ostorlab 移动动态扫描中运行。要使用它,只需使用您的构建版本、测试凭据和 UI 提示词启动一次移动扫描,Precheck 便会自动运行。有关配置,请参阅移动扫描前提条件。