您的应用通过 QA 检查,部署到生产环境,似乎一切正常。但是,依赖项问题在野外出现了,或者不小心更改了配置,暴露了您认为是内部的端点,或者实时更新推送了一个坏的 JavaScript 包到设备上,这些设备将永远不会看到您的预发布检查。 这是组织通常如何学习到应用漏洞扫描不是一个扫描器问题。 而是一个生命周期问题。
购买工具和点击“扫描”并不是困难的部分。 构建一个能够捕捉早期错误、在部署后继续运行并将发现转化为修复的系统才是困难的部分。 这在 CapacitorJS 和 Electron 堆栈中更为复杂,因为您的应用在发布后可以通过 web 层更新、内容更改和远程配置而改变。
A robust setup must cover code, dependencies, containers, running services, and the bundles you deliver after the binary is already on a user’s device. It also needs to fit how engineers work. If scans are slow, noisy, or detached from pull requests and release workflows, the pipeline will be bypassed. If you’re working through a broader app risk assessment process, app vulnerability scanning becomes one control in a bigger operating model, not a compliance box to tick.
目录
为什么主动性漏洞扫描很重要
周五下午是弱扫描程序暴露的时间。 一个新依赖CVE出现,安全人员会问哪些应用程序受影响,答案取决于谁仍然保留了上个月的报告。 移动和桌面团队有一个额外的问题。 即使后端已经修复,部署的客户端也可以继续运行脆弱的code,直到用户更新,或者直到团队有一个控制的方式来修补生产中的内容。
这就是为什么主动扫描很重要。 它给团队提供了当前的清单,清晰的负责人,每个发现的明确责任,以及从发现到验证修复的更快路径。 它还填补了许多指南忽略的缺口。 对于Capacitor和Electron应用程序,风险不仅仅是发布日。 您需要在部署后继续扫描和分级,特别是如果应用程序可以通过Web资产、远程配置、插件或实时更新改变行为。 做正式的 对混合和实时更新应用程序的应用风险评估 通常发现,难点不是运行扫描器。 难点是证明生产中当前暴露的内容。
只有当修复措施被内置时,扫描才有意义
将发现结果dump到PDF文件中只会创建一个后续工作清单,而不是保护。 一个工作程序将发现结果与服务负责人关联,打开包含足够上下文的票据,并记录修复后重新测试。 如果没有这种交接,团队要么忽略报告,要么花费几天时间争论是否存在问题。
使用简单的规则。
实用规则: 如果发现的问题无法分配、修复和验证,则是安全监测,而不是风险减少。
工作流程必须覆盖整个生命周期。范围内的资产。扫描code,依赖项、构建工件和运行服务。根据易受攻击性和暴露程度进行分类。使用正常的交付路径进行修复,时间允许。使用发布后路径进行修复,尤其是那些可以在商店发布外更新Webcode的应用程序。然后重新扫描以确认暴露已消失。
等待很快就会变得昂贵
被动清理会在可预测的方式中耗费工程时间。开发人员会跳回陈旧的code。安全团队会在多个工具上重新检查相同的问题。发布经理会开始批准例外,因为发布窗口已经延迟。结果是噪音、延迟和几乎没有信心。
主动扫描改变了经济学。发现的问题会在引入它们的提交附近出现。所有权清晰。生产暴露更容易回答。并且,当需要快速的后部署修复时,团队已经知道受影响的层次和补丁是否需要商店提交、服务器端更改或受控的实时更新。
应用程序漏洞扫描的四大支柱
有效的应用程序漏洞扫描通常涉及四个类别的协同工作。不是因为供应商喜欢缩写,而是因为每种方法都看到不同的风险片段。如果您依赖一种扫描器类型,您将获得一种真相和几个盲点。

每种扫描器实际上都擅长什么
SAST reads source code, bytecode, or compiled artifacts without running the app. It’s best when developers are still changing code and need quick feedback close to the commit. SonarQube and Semgrep are common choices here because they fit well into pull requests and CI.
DAST 从外部击中正在运行的应用程序。它对于认证错误、错误的头部、损坏的服务器行为、暴露的路由和只在请求通过整个堆栈时才显示的问题很有用。OWASP ZAP和Burp Suite是熟悉的选项。
IAST 位于运行时更靠近,通常通过instrumentation或agent,结合内部可见性与实时执行。它更具操作性,但可以填补“这个模式看起来风险很大”和“这个请求路径是可利用的”之间的差距。
SCA 跟踪第三方包和已知问题在您的依赖树中。对于大多数现代团队来说,这比源代码扫描更能立即行动,因为应用程序code依赖于外部包。Snyk、Dependabot和类似工具是常见的入口点。
如果您还要处理需要满足商店和平台要求的API,应用程序管道中的安全检查应该与应用商店遵守的安全标准保持一致,而不是仅仅遵守一般的安全规则。 APIcode
漏洞扫描类型比较
| 类型 | 运行时 | 发现的内容 | 主要优势 |
|---|---|---|---|
| SAST | 编码、拉取请求和构建时 | 有风险的code模式和不安全的数据流 | 在部署之前快速获得反馈 |
| DAST | 针对开发或运行应用 | 应用程序的运行时漏洞、暴露的行为、配置错误 | 像攻击者一样看到应用 |
| IAST | 在执行过程中进行装饰 | Code级别和运行时问题 | 在执行过程中更精确的识别 |
| SCA | 在依赖安装、构建和更新事件中 | 易受攻击的第三方包和传递依赖 | 快速暴露供应链风险 |
如何不浪费时间地将它们层叠起来
很多团队都早早地过度构建。他们将每个扫描器都连接到每个阶段,产生重复的警报,然后就奇怪为什么开发人员会静音通知。更清洁的方法是阶段覆盖。
- 使用 SAST 进行快速 code feedback: 在 pull 请求上运行它,并将规则保持在您使用的语言和框架的模式上。
- 在每个依赖项变化时使用 SCA: 不要等待预定的扫描才能了解一个包更新引入了风险。
- 在现实环境中使用 DAST: 将其运行在具有身份验证的阶段或审阅应用上,以便它看到真实的流程。
- 选择性地使用 IAST: 将其保留用于高风险服务,额外的上下文值得承担运营开销。
正确的问题不是“我们应该购买哪个扫描器?”而是“我们现在对什么类别的弱点视而不见?”
这种框架使程序保持实用。每个柱子都有其位置,因为它捕捉了其他不会捕捉的东西。
扫描现代应用架构
一支团队发布了一个干净的移动版本,通过了常规扫描,发布上线。三天后,它推送了一个JavaScript包更新来修复一个UIbug。这个包改变了客户端验证,暴露了一个桥接方法,shell不应该调用,且从未经过同样的安全检查和app store版本。最初发布的版本被扫描过了。现在code用户正在运行的版本并没有被扫描到。

传统程序的缺陷
很多扫描程序仍然集中在两个目标:仓库中的源code和正在运行的服务暴露的端点。那样对一个正常的web应用来说是比较合理的。然而,它并不能覆盖那些在部署后,发生有意义变化的架构,跨多个工件,或者在客户端shell中可以加载更新内容的架构。
CapacitorJS和Electron暴露了这个缺陷。可安装的二进制文件只是攻击面的一部分。JavaScript包,CSS,配置文件,特性标志,远程内容,预加载脚本,原生桥接,更新通道都影响到人们正在使用的应用的安全态势。
Wiz在其 应用程序漏洞扫描分析中指出更广泛的问题:很多团队在发布前对检查进行了大量关注,而对发布后变化进行了低水平扫描。对于实时更新应用来说,这是一个过程缺陷,而不是一个边缘案例。
The practical mistake is treating “the app” as one unit. Modern delivery stacks are layered, and each layer fails differently:
- 客户端包风险: 更新的 Web 资产可能引入不安全的 DOM 处理、弱化认证流程或改变 API 目标而无需新二进制审查
- 容器风险: 服务镜像可能携带陈旧的 OS 包、暴露的工具或一个坏的基准镜像,即使应用 code 看起来干净
- 运行时漂移: 生产环境可能与 staging 环境通过环境变量、侧车、密钥注入、入场规则和特性标志分离
- Shell 风险: Electron 和 Capacitor wrapper 添加了权限模型、IPC 或桥接表面、本地存储问题和标准 Web 扫描无法看到的更新机制
现代交付路径中的添加项
容器化服务需要比仓库扫描更多。扫描镜像期间、扫描最终的 artifact 之前、将正在集群中运行的内容与批准的内容进行比较。Trivy 是一个常见的起点,因为它在同一工作流中涵盖了文件系统包和容器镜像。然而,这仍然不足以解决问题。仅凭镜像发现而无运行时上下文的发现往往会导致 code 路径中长长的修复队列, nobody 可以访问
实时更新应用需要更严格的模型。将每个包视为一个 release artifact,拥有自己的安全门控、版本记录和回滚路径
That usually means four controls:
- 发布包前扫描网络层
- 记录每个设备安装的包版本
- 签名更新并验证传输完整性
- 逐步发布以确保坏的更新被限制在小规模中
这也改变了所有权。安全审查不能再仅限于商店提交或桌面打包。必须有人拥有更新通道、签名过程、包清单和回滚杀switch。如果没有人拥有这些部分,扫描程序就有一个盲点。
架构也改变了扫描器的范围。一个服务和一个分布式舰队不会产生相同的审查负担、凭证模型或警报路由。通过 单体架构和微服务架构 通常发现漏洞所有权变得更加困难,而扫描器覆盖度却没有。
预发布扫描只回答一个狭窄的问题:发布时这个 artifact 是否接受?它对包、镜像、配置或 shell 变更推送后没有任何信息,除非这些 artifact 经过自己的检查。
That is the part many guides skip. Modern app vulnerability scanning has to follow the code that is running in production, including code delivered after the original deploy.
正在生产中运行的__CAPGO_KEEP_0__,包括__CAPGO_KEEP_1__在原始部署后传递的__。
A团队在周五发布了一个干净的移动版本,然后在周二推送了一个修复收货错误的实时Web包。应用商店构建通过了每个安全检查。周二的包并没有经过同样的路径,现在生产正在运行code您的管道从未审查过。这个缺口就是扫描程序失败的地方。

管道必须与应用程序的交付方式相匹配。对于Web应用程序,这通常意味着code、依赖项、容器和部署环境。对于Capacitor和Electron应用程序,它还意味着post-deployment更新路径。如果您的扫描器在合并或商店提交时停止,它们就会错过发布周期中的一个最高风险点。
实践中有效的模式是分阶段扫描。尽早运行便宜的检查,后续进行更深入的检查,并在定期的时间间隔内进行post-deployment扫描。那些想要更快安全反馈的团队通常会采用相同的习惯,描述在 如何CI/CD工作流程改善应用程序安全:短反馈循环、清晰的门槛和可重复的政策。
从管道形状开始
一个可行的基准线看起来像这样:
- Pull Request阶段: SAST、SCA、机密扫描和基础设施-code和构建配置的策略检查。
- 合并到主分支: 全依赖项解析、容器扫描、SBOM生成和签名艺术品创建。
- 预发布阶段: 对一个模拟环境进行认证的DAST扫描,检查暴露的管理员路由、弱头和风险的默认配置。
- 发布后阶段: 预定外部验证、运行时可见性和扫描任何实时更新包前它到达用户。
最后阶段经常被跳过。对于实时更新应用程序,推送的包应被视为发布,而不是静态资产上传。
实践GitHub Actions示例
基本工作流可能结合SonarScanner进行静态分析、Snyk进行依赖项和Trivy进行容器图像的分析。
name: security-pipeline
on:
pull_request:
push:
branches: [main]
jobs:
sast-and-sca:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test, --ci
- name: Sonar scan
run: npx sonarqube-scanner
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
- name: Snyk dependency scan
run: npx snyk test
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
container-scan:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build image
run: docker build -t app:${{ github.sha }} .
- name: Trivy image scan
run: trivy image --exit-code 1 app:${{ github.sha }}
这足以开始,但不足以管理发布。生产管道通常需要四个附加功能。将结果上传到SARIF,以便发现问题可以在开发人员已经工作的位置。将SBOM保留在构建工件中。为拉取请求和发布候选人定义单独的失败规则。添加一个发布清单,连接提交、工件哈希、依赖项快照和实时更新应用程序的包版本。
几个实现细节决定了管道是否被使用或绕过:
- 根据政策而不是发现量进行门控: 阻止构建的定义条件,如严重级别、已知利用或可达的脆弱code。
- 保持扫描速度以保留信任: 缓存依赖项,重用扫描器数据库,并将长时间运行的作业从 pull 请求路径中分离出来。
- 使用身份验证运行 DAST: 匿名爬行很少能够到达处理钱、权限或账户变更的 code。
- 从发布阻塞器中分离建议检查: 如果每个警告都会阻止交付,开发人员会忽略整个系统。
- 在发布之前扫描更新包: 对于 Capacitor 或 Electron 的实时更新,检查更改的 Web 资产,附加扫描结果到包记录,并将回滚元数据保留在发布中。
以下是一个与您自己的实现工作配对的良好教程:
什么需要 gate 什么需要报告
硬 gate 应该狭窄且易于辩护。宽泛的阻塞规则看起来很严格,但通常会训练团队绕过安全而不是使用它。
成熟管道中的一个有效政策是简单的:
构建 gate 规则: 阻止新引入的关键问题,阻止可利用的依赖性发现在可到达的路径中,并将较低风险的发现发送到拥有者和截止日期的正常修复队列中。
发布后需要自己的门槛。 在发布一个实时包之前,扫描更改的文件,验证签名,记录谁批准了发布,并将包ID附加到部署记录中。 当一个问题在两周后出现时,那种可追溯性让你快速回答那些困难的问题:哪些用户接收了它,哪个code包含在它中,是否回滚足够还是需要强制更新。
解释结果和优先修复
扫描报告一旦团队停止信任它,就会变得很昂贵。这通常发生在几轮噪音发现、重复票和不通过手动审查的阻塞器之后。 好的分级修复在它成为一个文化问题之前就解决了它。
切除假阳性之前,它们会耗尽注意力
噪音有熟悉的原因。 规则保持启用状态,用于应用程序不使用的框架。 DAST在没有登录上下文的情况下运行,因此它会错过重要的流程并仍然产生弱猜测。 SAST、SCA、容器和运行时工具都以不同的方式描述相同的底层问题,然后将其分发到单独的队列中。
首要任务是使发现可信。
团队通过调整检查到栈、使用身份验证扫描(在需要时深入)以及在结果到达开发人员之前去重来获得结果。基于证据的验证和相关性有所帮助,但它们并不能替代策略调整。如果扫描器无法区分支付路径中的可达问题和废弃模块中的死code,则输出需要在到达回滚列表之前再进行一次层次的审查。
实践中有效的分级流程如下:
- 移除无法应用的发现: 如果应用程序不使用规则目标的运行时、包、端点类或功能,禁用或限制该规则。
- 将重复项折叠为一个修复项: 每个弱点应该有一个负责人、一个截止日期和一个讨论线索。
- 使用身份验证重新扫描风险集中: 管理员面板、角色受限的流程、内部API和账户恢复路径通常看起来很干净,直到扫描器可以登录。
- 尽早添加业务背景: 反射型XSS在公共账单屏幕上是一个不同的问题,而在内部支持工具上出现相同的漏洞。
根据利用性和爆炸半径进行优先排序
扫描器严重性是起始点。它不是工作队列。
I首先考虑四个问题。问题是否可以在运行中的应用程序中访问。受影响的路径是否暴露给用户或互联网。是否有证据表明存在主动利用或成熟的利用路径。团队是否可以快速降低风险通过补丁、配置更改、功能标志或临时控制来解决问题。
这种方法可以快速做出决定。暴露在认证流中的中等严重性bug可以优先于被管理员访问和WAF规则保护的更严重的发现。没有可达code路径的依赖性CVE通常会低于直接位于支付或会话边界的小问题。
每日筛查时使用简单的过滤器:
| 问题 | 是 | 否 |
|---|---|---|
| 生产环境中是否可达受害路径? | 提高紧急程度 | 直到可达性发生变化时才延后 |
| 是否暴露给未受信任的用户或互联网? | 作为前线修复处理 | 排在暴露问题之后 |
| 是否存在活跃的攻击行为、公开的漏洞利用或强烈的攻击者兴趣? | 立即修复 | 继续风险评估 |
| 是否可以通过补丁、配置更改或杀死switch来减少风险? | 优先发布风险减少 | 计划code修复和测试覆盖 |
按实际攻击机会排序,而不是报告量
修复与发布路径绑定
优先级应该以可由交付系统强制执行的行动结束。否则,团队在Slack上同意风险,但仍会在下周发布包含漏洞的code
对于标准的Web和移动后端,意味着将高置信度的发现转换为跟踪修复,拥有所有者、截止日期和验证标准。对于Capacitor和Electron应用程序,添加一个额外的步骤。询问问题是否位于实时更新层中,并且是否可以在等待商店审查之前进行修复。这种在部署后做出的决定是许多程序的弱点。他们可以检测问题,但无法快速关闭code已经在用户设备上的问题
如果您的团队支持热修复发布,请定义交接手续:哪些发现适合发布热修复包,谁批准它,如何分阶段发布,以及什么回滚信号可以停止发布。这 使用Capgo发布热修复的五步流程 对于修复路径而言,了解它的每个组成部分至关重要,避免在事故发生时才开始摸索。
实时修复:快速修复
发现问题只是解决方案的一半。关键问题是你是否能快速推送安全的修复方案给受影响的用户,以至于能对他们产生影响。
对于服务器端应用程序,修复通常意味着重新部署服务。对于CapacitorJS和Electron应用程序,许多紧急修复方案都存在于web层:JavaScript逻辑、渲染路径、内容规则、特性标志、复制内容或配置等。等待应用商店的审核来修复这些情况通常对于实际的事件响应流程来说太慢了。
当商店审核太慢时
部署后差距是实时更新从便利转变为安全模型的一部分。如果用户已经持有易受攻击的包、不安全的配置或破坏性规则,需要一种受控的方式来快速替换它们。

对于这种类型的问题,团队通常需要在一个工作流程中具备四种能力:
- 针对性发布渠道: 先修复内部用户,然后修复小规模的生产用户群,然后进行更广泛的发布。
- 包签名和版本历史: 知道发生了什么变化,并防止未经控制的艺术品发布。
- 每设备可观察性: 通过设备和捆绑包版本验证采用和调查失败。
- 自动回滚: 如果修复创建了新的故障模式,快速回滚。
在这个领域的一种选择是 Capgo的热修复部署工作流程,该工作流程将签名的Web捆绑包更改应用到Capacitor和Electron应用程序
而无需等待商店审查。
如何安全地修补
快速修补会产生自己的风险,如果更新路径不当。
- 不要通过即兴修订另一个部署通道来回应一个安全问题。 安全的运营模式如下:
- Patch 只有必要的文件 以保持发布面板小.
- 扫描更改的捆绑包 发布前.
- 首先在狭窄的渠道中推广 并监测采用率和错误日志.
- 逐渐推广 一旦修复稳定.
- 保持回滚一步之遥 直到推广完成.
一个实时更新过程应该像在紧迫时间下进行有条不紊的发布工程一样感觉,而不是一个手动工作-around.
尤其是在受管制环境中。这尤其重要。如果您的移动或桌面外壳可以接收动态内容,那么交付路径需要拥有相同的所有权、可追溯性和批准逻辑,如原始二进制发布一样。否则,您已经创建了一个足以通过驱动事件的盲点。
从检查清单到文化
团队通常将应用程序漏洞扫描作为检查项开始。 安装扫描器。 在 CI 中运行它。 为审计导出报告。 这是一个起点,但是一旦您的架构变得更加分布式,一旦您的发布频率加快,就会出现问题。
持续的模型是文化和运营的。 开发人员期望在拉取请求中进行静态和依赖项检查。 平台团队维护已验证的扫描目标和容器覆盖。 安全团队调整策略、关联发现并将重要的发现与商业背景一起路由。 发布团队将实时包和发布后更改视为首类艺术品,而不是不正式的修补程序。
这种转变是将扫描转变为真正的风险减少的关键。 您停止测量活动,开始测量管道是否捕获了重要的内容、是否将其路由到正确的所有者,并在暴露之前修复它,避免了应急响应。
成熟的程序仍然有自己的意见。 它阻止狭隘的。 它持续扫描。 它优先考虑可利用性而不是噪音。 并且它不假装发布日是安全故事的结尾。
如果您部署 CapacitorJS 或 Electron 应用程序并需要实用的方法来关闭发布后漏洞差距, Capgo 为团队提供了一个控制的实时更新路径,用于 JavaScript、CSS、配置和资产修复,具有签名包、滚动频道、回滚保护和设备级观察性,自然融入现代漏洞管理工作流中。