
Dawarich 安全扫描实践从 CI 流水线到本地全量 Git 历史的完整指南【免费下载链接】dawarichYour favorite self-hostable alternative to Google Timeline (Google Location History)项目地址: https://gitcode.com/GitHub_Trending/da/dawarich导读Dawarich 是一个自托管的 Google TimelineGoogle 位置历史替代方案代码库以 RailsRuby为核心。为了保证自托管 ≠ 自担全部风险项目在 SECURITY-SCANNING.md 中沉淀了一套分层安全扫描体系CI 侧用 Brakeman、bundler-audit、Semgrep、gitleaks 与 Trivy 覆盖 SAST、依赖漏洞、密钥泄漏与容器镜像漏洞本地侧则提供全量 Git 历史密钥扫描与逐条可复现的扫描命令。读完本文你将掌握这套扫描矩阵的触发时机、门禁策略Report-only vs Blocking、CI 工作流实现细节以及如何在任意一台机器上复跑全部扫描器为自己的 Rails/Docker 项目搭建同样的防线。一、整体设计三层防线与三种触发时机Dawarich 的安全扫描由 GitHub Actions 自动驱动核心目标是在合入代码之前尽可能发现四类问题应用代码自身的安全缺陷SQL 注入、XSS、批量赋值、不安全跳转等 Rails 常见弱点——由 SAST 类工具负责依赖链中的已知漏洞Gemfile.lock中的易受攻击 gem——由 bundler-audit 负责密钥/凭据意外入库API Key、Token 等敏感信息出现在 diff 或历史提交中——由 gitleaks 负责容器产物与基础设施配置缺陷Docker 镜像内操作系统/库的 CVE、Dockerfile/IaC 配置不当——由 Trivy 负责。根据 SECURITY-SCANNING.md 的说明扫描在三种场景下自动触发每次 Pull Request变更进入主干前的第一道闸门每次 push 到master与dev分支主干/开发分支的持续守护每周定时任务周一即使本周没有代码变更也会用最新的漏洞库重新审视代码与镜像。这一设计意味着漏洞情报advisory 数据库、规则集每周都会刷新且不需要任何开发动作即可保持最新基线。最小权限原则工作流声明了permissions: contents: read除上传 SARIF 结果所需的security-events: write外不申请任何多余权限。除 GitHub 内置的GITHUB_TOKEN外不需要任何额外机密第三方 Action 全部以 commit SHA 固定版本避免供应链投毒详见下文 CI 实现。二、CI 扫描矩阵六项任务的角色与门禁文档用一张表明确了六个扫描任务的定位这里逐项展开说明其职责边界工作流任务工具捕获范围门禁级别security.ymlbrakemanBrakemanRails SASTSQL 注入、XSS、批量赋值、不安全跳转等仅报告security.ymlbundler-auditbundler-auditGemfile.lock中已知漏洞 gemadvisory 数据库在任务内刷新阻断security.ymlsemgrepSemgrepp/ruby、p/rails、p/secrets、p/owasp-top-ten四套规则SAST 密钥模式仅报告security.ymlgitleaksgitleaksPR/push 的 diff 中的密钥阻断trivy.ymlimageTrivy镜像扫描构建出的 Docker 镜像中的 OS/库 CVE有修复的 HIGH/CRITICAL仅报告trivy.ymlconfigTrivy配置扫描Dockerfile / IaC 配置错误仅报告2.1 为什么用两套 SASTBrakeman Semgrep 互补Brakeman是 Rails 生态事实标准的静态分析工具。Dawarich 将它与 bundler-audit 一起声明在 Gemfile 的开发/测试/staging 组中gem brakeman, require: false、gem bundler-audit, require: false专门针对 Rails 框架的惯用 API 做深度检查——例如params直接拼进 SQL、redirect_to使用外部输入、update_all/create_with类批量赋值路径等。Semgrep则作为广谱补充它不绑定 Rails 框架用p/ruby、p/rails、p/secrets、p/owasp-top-ten四套公开规则集同时覆盖通用 Ruby 代码质量、Rails 最佳实践、密钥模式如硬编码的 AWS Key、GitHub Token 等以及 OWASP Top Ten 常见漏洞。两套工具规则来源不同、视角互补同一类问题可以用不同模式交叉验证。2.2 唯一默认硬门禁bundler-audit 与 gitleaksbundler-audit直接读取Gemfile.lock与 RubyGems Advisory Database 比对。由于 Dawarich 是一个长期演进、依赖较多的 Rails 项目其 security.yml 中的实现是bundle exec bundle-audit update bundle exec bundle-audit check先更新本地 advisory 数据库再检查——这正是文档强调的advisory DB refreshed in-job每次运行都拉取最新漏洞情报而不是依赖某个缓存的旧库。一旦发现已知漏洞 gem任务直接失败阻断合并。gitleaks则守护密钥不落库这条红线。CI 中仅扫描本次变更的 diff详见下文第四节发现任何疑似密钥即以失败收场。2.3 镜像与基础设施Trivy 双任务trivy.yml的image任务针对构建产物本地docker build出来的镜像执行漏洞扫描trivy image \ --scanners vuln \ --severity HIGH,CRITICAL \ --ignore-unfixed \ --format sarif --output /work/trivy-image.sarif \ --exit-code 0 \ dawarich:scan三个关键参数的含义--severity HIGH,CRITICAL只关注高危与严重级别过滤掉大量低优先级噪声--ignore-unfixed只看有修复版本可用的 CVE——没有修复方案的漏洞无法通过升级解决先不阻塞交付--exit-code 0本轮不阻断Report-only但结果照常上传到 Security 标签页。config任务则用trivy config /work扫描仓库本身主要是 docker/Dockerfile 等 Docker/IaC 文件检查诸如基础镜像版本过旧、特权指令、危险环境变量等配置类问题。值得一提的细节Trivy 固定使用ghcr.io/aquasecurity/trivy:0.65.0容器镜像trivy.yml 的env.TRIVY_IMAGE并通过TRIVY_USERNAME/TRIVY_PASSWORD环境变量传递凭据拉取私有层Docker 守护进程通过挂载/var/run/docker.sock提供给容器内的 Trivy从而可以直接扫描宿主机构建出的本地镜像dawarich:scan。三、门禁分级策略先采集信号再收紧闸门文档明确指出当前阶段四分之三的任务都是 Report-onlyBrakeman、Semgrep、Trivy 的 image 与 config只有 bundler-audit 和 gitleaks 是阻断性的。这是有意为之的设计决策This is intentional for the first pass — gather signal before gating merges.原因很务实一个成熟代码库在第一次接入 SAST 时历史存量问题可能非常多如果直接全部设为阻断所有 PR 都会红掉团队会被迫在修历史债和合入新功能之间二选一反而阻碍扫描体系的落地。先以 Report-only 运行一段时间把真实告警量、误报率摸清楚再逐步升级为门禁。文档同时给出了从 Report-only 升级为 Blocking 的具体操作路径这对应到源码中Brakeman / Semgrep / Trivy config在 security.yml 与 trivy.yml 中删除对应 step 上的continue-on-error: trueTrivy image将--exit-code 0改为--exit-code 1让存在可修复的 HIGH/CRITICAL CVE直接导致任务失败。升级节奏可以按工具逐个推进先放开风险最高的如 Trivy image 的可修复高危 CVE再根据误报情况逐步覆盖其余任务。四、CI 实现细节从源码看安全实践如何落地4.1 第三方 Action 全部固定到 commit SHA打开 security.yml 可以看到每一个uses:都带上了完整 SHA 与版本注释例如uses: actions/checkout3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 uses: ruby/setup-rubyafeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.0 uses: github/codeql-action/upload-sarifdb488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8 uses: gitleaks/gitleaks-actione0c47f4f8be36e29cdc102c57e68cb5cbf0e8d1e # v3.0.0SHA 固定意味着即便上游仓库被恶意篡改或 Action 作者账号被盗CI 也只会执行当初审核过的那个 commit的代码。这是供应链安全的基础实践文档中All third-party actions are pinned to a commit SHA的承诺在源码层面得到了完整落实。4.2 SARIF 统一汇入 Security → Code scanningBrakeman、Semgrep、Trivyimage 与 config四个任务都会产出 SARIF 格式报告并通过github/codeql-action/upload-sarif上传if: always()保证即使扫描失败也会上传报告并且各自带独立category如brakeman、semgrep、trivy-image、trivy-config在仓库的Security → Code scanning标签页按类别分组展示。这样所有工具的告警集中在一个入口方便统一分类、指派与跟踪。4.3 gitleaks 在 CI 中只扫 diff 的取舍这是一个容易被忽视但很关键的设计。CI 中的 gitleaks 任务security.yml有两个值得注意的点触发范围if: github.event_name pull_request || github.event_name push——只有 PR 和 push 时运行定时任务不跑gitleaks扫描对象通过fetch-depth: 0拉取完整历史后gitleaks-action 默认仍以本次变更的 diff为扫描范围。原因写在任务注释里CI 只扫 diff是为了避免反复标记已知的历史提交。这个仓库是公开的如果每周定时全量扫历史每次都会命中多年前的历史密钥产生大量无法通过删掉提交解决的噪声。全量历史扫描被有意放到本地手动执行详见第六节因为那才是有意为之的排雷动作而不是 CI 的例行公事。4.4 并发与失败取消security.yml与trivy.yml都声明了concurrency: group: security-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true同一分支上连续多次 push 时旧的扫描会被新的一次取代避免排队积压和资源浪费。五、依赖与基础镜像的持续更新Dependabot安全扫描只负责发现修复依赖要靠 .github/dependabot.yml 的自动化更新。它覆盖三个维度生态目录频率说明bundlerRubyGems/每周一minor/patch 分组批量更新限制 10 个并发 PRdocker/docker每周一基础镜像更新限制 5 个 PRgithub-actions/每周一保持 SHA 固定版本不过期限制 5 个 PR三个更新目标都打在dev分支便于先在开发分支验证再合入主干。其中 docker 生态的ignore规则非常值得注意——它主动禁止Ubuntu 基础镜像的 major/minor 升级ignore: - dependency-name: ubuntu update-types: - version-update:semver-major - version-update:semver-minor原因注释写得很清楚Dockerfile 中的mbgl_libs阶段依赖 Ubuntu 24.04 预编译的maplibre/maplibre-gl-native二进制它链接的是libicuuc/libicudata/libicui18n的.so.74版本而更新的 Ubuntu 不再提供 ICU 74。也就是说基础镜像不能盲目升级Dependabot 的自动化必须在兼容性约束下运行——这本身也是依赖管理安全实践的一部分已知的破坏性升级比缓慢的 CVE 更危险。六、全量 Git 历史密钥扫描本地执行这是 SECURITY-SCANNING.md 中最重要的实操章节也是公开仓库必做的体检。6.1 为什么 CI 扫不到历史密钥CI 的 gitleaks 只扫 diff。而公开仓库的历史是不可磨灭的一个多年前提交的密钥即使后来从文件中删除只要曾出现在任一历史 commit 中就仍然暴露在互联网上。文档强调a secret committed years ago remains exposed even if later removed所以必须在本地对完整 git 历史执行一次扫描找出所有历史提交中残留的密钥。6.2 全量扫描命令docker run --rm -v $(pwd):/repo -w /repo \ ghcr.io/gitleaks/gitleaks:latest \ detect --source. --redact -v参数拆解-v $(pwd):/repo -w /repo把当前目录挂载进容器并设为工作目录detect --source.以当前目录为 git 仓库根扫描全部提交历史--redact输出中把密钥值打码避免终端日志二次泄露-vverbose显示每个命中的详情。6.3 输出 SARIF 报告便于分诊如果需要把结果沉淀成报告文件、导入缺陷跟踪系统或交给团队逐一处理使用docker run --rm -v $(pwd):/repo -w /repo \ ghcr.io/gitleaks/gitleaks:latest \ detect --source. --redact --report-format sarif --report-path gitleaks-history.sarif与 CI 上传到 Security 标签页的格式一致可以直接用同一套流程管理。6.4 命中后的处理流程文档给出了明确的处置链路轮换Rotate凡是历史中出现的密钥一律视为已泄露——即使看起来从未被使用。修改对应的 API Key、Token、密码使其立即失效抑制Suppress确认已轮换、且不需要再被报出的历史命中通过.gitleaks.toml的 allowlist 按finding fingerprint精确豁免避免每次全量扫描都重复报警。注意当前仓库根目录下并没有现成的.gitleaks.toml文件这是文档建议的可选动作需要时自行创建。七、在本地复跑全部扫描器SECURITY-SCANNING.md 提供了完整的本地复现命令适合在 CI 之外做提交前自查或CI 之外环境的巡检。逐条说明如下# 1) Rails SAST —— 与 CI 的 brakeman 任务一致 bundle exec brakeman --no-progress # 2) 依赖漏洞 —— 先更新 advisory 库再检查 Gemfile.lock bundle exec bundle-audit update bundle exec bundle-audit check # 3) Semgrep —— 四套规则集与 CI 完全一致 pip install semgrep semgrep scan \ --config p/ruby --config p/rails --config p/secrets --config p/owasp-top-ten # 4) 镜像漏洞 —— 先本地构建再扫 docker build -f docker/Dockerfile -t dawarich:scan . trivy image --ignore-unfixed --severity HIGH,CRITICAL dawarich:scan # 5) 基础设施配置 trivy config .几点补充说明brakeman与bundler-audit来自 Gemfile 的development, :test, :staging组本地开发环境bundle install后即可直接使用Semgrep 通过pip install安装参数与 CI 中 security.yml 的--config p/ruby --config p/rails --config p/secrets --config p/owasp-top-ten完全对齐保证本地结果与 CI 可比Trivy 命令需要本机已安装docker与trivy且镜像构建耗时较长Dawarich 的 Dockerfile 包含多阶段构建与资产预编译适合在发布前或 CI 环境外做增量巡检时使用trivy config .不依赖构建直接对仓库中的 Dockerfile 等 IaC 文件做静态检查速度最快。八、落地经验小结Dawarich 的安全扫描体系提供了一套可迁移的模板核心经验可以总结为四点分层而非单点SASTBrakeman Semgrep、依赖审计bundler-audit、密钥扫描gitleaks、容器扫描Trivy各司其职覆盖从源码到产物的完整链路渐进式门禁先用 Report-only 采集信号、摸清误报率再按工具逐个收紧为 Blocking——既保安全底线又不阻塞开发自动化与人工分工CI 例行扫 diff全量历史排雷放到本地按需执行避免定时任务制造噪声供应链安全贯穿始终Action 固定 SHA、最小权限、Dependabot 每周更新同时在兼容性约束下理性控制基础镜像升级。对于任何一个自托管、公开源码的 Rails 项目这套CI 例行扫描 本地全量排雷 自动化依赖更新的组合都是一份可以直接照搬的安全基线。【免费下载链接】dawarichYour favorite self-hostable alternative to Google Timeline (Google Location History)项目地址: https://gitcode.com/GitHub_Trending/da/dawarich创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考