TomTonic/grype_me
GitHub: TomTonic/grype_me
基于 Anchore Grype 的 GitHub Action,可对仓库、容器镜像和 SBOM 进行漏洞扫描,自动生成安全徽章和详细报告。
Stars: 1 | Forks: 1
# ✊ grype_me
[](https://gist.github.com/TomTonic/e0a34e0c03120db2400fc0480169498c#file-grype_me-action_release-md)
[](https://gist.github.com/TomTonic/e0a34e0c03120db2400fc0480169498c#file-grype_me-docker_image-md)
一个易于使用的 GitHub Action,利用 [Anchore Grype](https://github.com/anchore/grype) 扫描您项目的供应链是否存在已知漏洞,并生成包含详细报告的徽章。
## 快速开始
```
- uses: actions/checkout@v4
with: { fetch-depth: 0, fetch-tags: true }
- uses: TomTonic/grype_me@v1
with:
scan: 'latest_release'
description: |
Nightly vulnerability scan of latest stable release.
Includes application dependencies from source manifests.
fail-build: false
gist-token: ${{ secrets.GIST_TOKEN }}
gist-id: ${{ vars.GRYPE_BADGE_GIST_ID }}
```
这将扫描您的最新 release,将 shields.io 徽章 JSON 和详细的 Markdown 报告上传到 GitHub Gist,并使徽章 URL 作为步骤输出可用。点击上方的徽章查看实时示例报告。
有关完整示例,请参阅本项目如何[运行每日扫描](./.github/workflows/security-badge.yml)以更新此 README 中的两个徽章。
## 功能特性
- 🔍 使用最新版本的 Grype 及每日更新的漏洞数据库(捆绑在 action 镜像中)
- ⚡ 比 workflow 运行期间安装 Grype **快约 2 倍**(无需下载约 200 MB 的数据库)
- 📦 **多种扫描目标**:repositories、container images、目录或 SBOMs
- 🎯 **最新 release 扫描**:非常适合对已发布的 release 进行夜间扫描
- 📊 按严重程度(Critical, High, Medium, Low)详细统计漏洞数量
- 🚨 当漏洞达到或超过配置的阈值时让构建失败
- 🔧 选项:仅显示有可用修复方案的漏洞
- 🏷️ **动态徽章生成**,附带链接的 Markdown 报告——无需额外的 action
## 工作原理
此 action 在 Docker 容器内运行 Grype,并使用预先下载的漏洞数据库。它支持两种模式:
| 模式 | 输入 | 描述 |
|------|-------|-------------|
| **Repository** | `scan` | 通过依赖清单(`go.mod`, `package.json`, `requirements.txt` 等)扫描源代码 |
| **Artifact** | `image` / `path` / `sbom` | 扫描 container images、目录或 SBOM 文件 |
### Repository 模式
Grype 直接从 repo 读取依赖清单——无需构建。这对 **Go 项目**特别有效。
- ✅ 无需编译即可检测源码声明的依赖
- ✅ 非常适合对带标签的 release 进行夜间扫描
- ❌ 仅运行时存在或动态下载的依赖需要使用 artifact 模式
**扫描模式:**
- `latest_release` – 扫描最高的稳定 semver 标签(默认)
- `head` – 扫描当前工作目录
- `` – 扫描特定的 ref
### Artifact 模式
使用 `image`、`path` 或 `sbom` 扫描构建产物。这些输入与 `scan` 互斥。
## 用法
### 带徽章的夜间 Release 扫描
请参阅 [`.github/workflows/security-badge.yml`](./.github/workflows/security-badge.yml),了解生成此 README 中所示徽章的 workflow。以下是基本模式:
```
name: Security Badge
on:
schedule:
- cron: '0 2 * * *'
workflow_dispatch:
jobs:
update-badge:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0, fetch-tags: true }
- uses: TomTonic/grype_me@v1
with:
scan: 'latest_release'
description: |
Nightly release scan for the public badge report.
Scans the latest semver tag in this repository.
fail-build: false
gist-token: ${{ secrets.GIST_TOKEN }}
gist-id: ${{ vars.GRYPE_BADGE_GIST_ID }}
gist-filename: 'my-project'
```
这会将三个文件写入 gist:
- `my-project.json` — shields.io endpoint badge JSON
- `my-project.md` — 包含 CVE 表格的详细 Markdown 报告
- `my-project-grype.json` — 原始 Grype 扫描输出
### Container Image 扫描
```
- name: Build image
run: docker build -t myapp:${{ github.sha }} .
- uses: TomTonic/grype_me@v1
with:
image: 'myapp:${{ github.sha }}'
image-source: 'registry'
description: |
PR build image scan for commit `${{ github.sha }}`.
Used as release gate for container publishing.
fail-build: true
severity-cutoff: 'high'
```
`image-source: registry` 直接从 registry 拉取,避免访问 Docker daemon。
### 在 README 中使用徽章
首次 workflow 运行后,将徽章添加到您的 README:
```
[](https://gist.github.com/YOUR_USER/YOUR_GIST_ID#file-my-project-md)
```
徽章链接到渲染后的 gist 报告(而非原始文件视图)。点击它会显示完整的 CVE 明细。
GitHub gist 文件锚点基于渲染后的 DOM ID(例如,`my_file.md` → `#file-my_file-md`;下划线保持不变)。
#### 设置
1. 在 [gist.github.com](https://gist.github.com) **创建一个 GitHub Gist**,包含任意初始文件(例如内容为 `{}` 的 `init.txt`)。从 URL 复制 Gist ID。
2. 在 [GitHub Settings → Developer settings → Personal access tokens](https://github.com/settings/tokens) **创建一个 Personal Access Token**,需具有 `gist` scope。
3. 向您的 repository **添加 secrets/variables**:
- Secret `GIST_TOKEN` — 步骤 2 中的 PAT
- Variable `GRYPE_BADGE_GIST_ID` — 步骤 1 中的 gist ID
## 输入
### 扫描目标(互斥)
| 输入 | 描述 | 默认值 |
|-------|-------------|---------|
| `scan` | Repository 扫描:`latest_release`、`head` 或标签/分支 | `latest_release` |
| `image` | 要扫描的 Container image(例如 `alpine:latest`) | – |
| `image-source` | `image` 扫描的来源:`auto`, `registry`, `docker`, `podman`, `containerd` | `auto` |
| `path` | 要扫描的目录或文件 | – |
| `sbom` | SBOM 文件 (Syft, CycloneDX, SPDX) | – |
### 选项
| 输入 | 描述 | 默认值 |
|-------|-------------|---------|
| `fail-build` | 如果漏洞 ≥ `severity-cutoff` 则失败 | `false` |
| `severity-cutoff` | 阈值:`negligible`, `low`, `medium`, `high`, `critical` | `medium` |
| `output-file` | 将结果保存到 JSON 文件 | – |
| `only-fixed` | 仅报告有可用修复方案的漏洞 | `false` |
| `db-update` | 扫描前更新数据库(参见[性能](#performance)) | `false` |
| `strict-privilege-drop` | 如果在 UID/GID 丢弃之前无法预打开 `GITHUB_OUTPUT`,则失败而不是回退到 root | `false` |
| `description` | 可选的自由文本(支持 Markdown/换行),逐字复制到报告 `.md` 的 `Description:` 下 | – |
### Gist 集成
| 输入 | 描述 | 默认值 |
|-------|-------------|---------|
| `gist-token` | 具有 `gist` scope 的 GitHub PAT(存储为 secret) | – |
| `gist-id` | 要更新的 gist 的 ID | – |
| `gist-filename` | gist 文件的基础文件名(例如 `my-project`) | 根据扫描模式自动生成 |
## 输出
| 输出 | 描述 |
|--------|-------------|
| `cve-count` | 发现的漏洞总数 |
| `critical` / `high` / `medium` / `low` | 按严重程度统计的数量 |
| `grype-version` | 使用的 Grype 版本 |
| `db-version` | 漏洞数据库版本 |
| `json-output` | 输出文件的路径(如果设置了 `output-file`) |
| `badge-url` | shields.io 徽章 URL(配置 gist 时为动态 endpoint,否则为静态) |
| `report-url` | 渲染后的 gist 报告部分的 URL(`gist.github.com/...#file-...`;保留下划线) |
| `runtime-privilege` | 有效的权限模式:`already-non-root`, `dropped` 或 `root-fallback` |
| `runtime-privilege-detail` | 当权限降级无法执行时的回退/严格失败原因诊断 |
### 权限降级故障排除
容器以 root 身份启动,并在降级到 UID 10001 之前预打开 `GITHUB_OUTPUT`。继承的文件描述符在 `setuid`/`setgid` 之后仍然有效(标准 Unix 行为),因此可以在不修改挂载所有权的情况下写入步骤输出。如果预打开失败,action 将:
- 回退到 root(默认,`strict-privilege-drop: false`)并报告 `runtime-privilege=root-fallback`
- 快速失败(`strict-privilege-drop: true`)
使用 `runtime-privilege` 和 `runtime-privilege-detail` 输出以及警告日志来检测这种情况。
## 性能
Action 镜像每天使用最新的 Grype 和漏洞数据库**重建**。这消除了约 200 MB 的数据库下载,使扫描速度比在 GitHub Actions workflow 中手动运行 Grype **快约 2 倍**。
| 场景 | 建议 |
|----------|----------------|
| 夜间扫描 | 使用预置数据库(默认)——快速且足够新 |
| 发布前的安全门 | 考虑使用 `db-update: true` 以确保绝对最新 |
```
- uses: TomTonic/grype_me@v1
with:
scan: 'latest_release'
db-update: true # Download latest DB before scanning
```
### 每日标签更新
发布的 container image 每天重建,以始终包含最新的 Grype release 和最新的漏洞数据库。因此,移动标签每天都会转移到新镜像:`latest`、`v1`、`v1.2` 和 `v1.2.3`。根据设计,补丁级别仅指此 action 的补丁级别,不包括漏洞数据库。
只有以下标签保持不可变且稳定:
- `v1.2.3-release`
- `v1.2.3_grype-0.xyz.0_db-YYYY-MM-DDThh-mm-ssZ`
此行为是有意为之,但如果您尝试在 CI 或其他自动化中固定到补丁级别标签,可能会令人惊讶。如果您需要不变的镜像,请固定到其中一个不可变标签(例如特定数据库的 `..._grype-..._db-...` 标签或 `-release` 标签)。
## 徽章
此 action 生成一个动态的 [shields.io](https://shields.io) 徽章,通过颜色编码显示漏洞数量:
| 颜色 | 含义 |
|-------|---------|
|  | 无漏洞 |
|  | 仅低严重性 |
|  | 中严重性 |
|  | 高严重性 |
|  | 严重 严重性 |
配置 gist 集成后,徽章是一个会自动更新的 [shields.io endpoint badge](https://shields.io/badges/endpoint-badge)。点击徽章会打开详细的 Markdown 报告,显示每个 CVE 的 package、version、fix status 和 description。
如果没有 gist 集成,`badge-url` 输出将包含一个静态的 shields.io URL,可以显示在 workflow 摘要中:
```
- uses: TomTonic/grype_me@v1
id: grype
with: { scan: 'latest_release' }
- run: |
echo "" >> $GITHUB_STEP_SUMMARY
```
## 告警示例
### 创建 GitHub Issue
```
- uses: TomTonic/grype_me@v1
id: grype
with: { scan: 'latest_release' }
- if: steps.grype.outputs.critical > 0
uses: actions/github-script@v7
with:
script: |
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: '🚨 Critical vulnerabilities detected',
body: `Found ${{ steps.grype.outputs.critical }} critical CVEs.\n\n[View report](${{ steps.grype.outputs.report-url }})`,
labels: ['security', 'critical']
});
```
### Slack 通知
```
- uses: TomTonic/grype_me@v1
id: grype
with: { scan: 'latest_release' }
- if: steps.grype.outputs.cve-count > 0
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "🔒 Scan: ${{ steps.grype.outputs.critical }} critical, ${{ steps.grype.outputs.high }} high CVEs"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
```
## 许可证
BSD 3-Clause License – 详见 [LICENSE](LICENSE)。
高级输入
| 输入 | 描述 | 默认值 | |-------|-------------|---------| | `debug` | 打印环境变量(可能会暴露 secrets) | `false` |标签:AI应用开发, Anchore, Angular, Claude, CVE检测, DevSecOps, Docker, EVTX分析, Gist, GitHub Action, Grype, Markdown报告, SBOM, Web截图, 上游代理, 云安全监控, 代码安全, 安全徽章, 安全防御评估, 容器安全, 工作流, 测试覆盖率, 漏洞枚举, 硬件无关, 结构化查询, 自动化安全, 请求拦截, 静态分析