关于 orca-sec-scans
orca-sec-scans 是面向开发者和 CI 的只读安全扫描技能,结合 Trivy 静态检查、真实请求验证和可选的域名仿冒监测。它分别报告代码与运行环境中的风险,并要求对扫描结果进行复查,而不把静态扫描无发现等同于安全。
主要功能
- 01扫描依赖漏洞、配置错误和文件密钥
- 02生成 JSON 与 HTML 报告
- 03通过真实 HTTP 与 DNS 请求验证假设
- 04修复后重新扫描确认
- 05可选检测仿冒域名与证书
适用场景
- 01发布或合并部署分支前检查风险
- 02在 CI 中定期扫描代码库
- 03验证 API 身份验证与域名暴露情况
- 04检查品牌相似域名及其证书
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ rheinmir/ setup --skill orca-sec-scans安装后在 Claude Code 中输入/orca-sec-scans确认已加载。
详细介绍
技能:orca-sec-scans
内容
用途和背景
- **用途:**一个静态、只读的安全扫描流程(Trivy 扫描时不会修改代码),可在本地和 CI/Jenkins 中使用。覆盖:依赖项 CVE(Go/Node/Python 锁文件)、错误配置(Dockerfile/compose/nginx)以及文件中泄露的 secret。 除了这层静态扫描,还有两层:动态扫描通过真实请求验证开发者的默认假设;外部扫描(供应链/品牌、keyless)。
- 触发条件(何时使用):
- 用户提到“安全扫描”“scan”“trivy”“检查 CVE”“security scan”“有没有漏洞”
- 发布前 / 合并部署分支前
- 在 CI 中定期运行(
trivy fs . --config trivy.yaml --exit-code 1) - Diff 涉及 Trigger-conditions 表中的内容(身份验证、用户输入、secret、新 endpoint、支付/敏感数据、将应用部署到 public domain)→ 必须扫描;用户提到“有没有漏洞”“安全吗”→ 始终触发。
- **非目标:**当子模块有尚未提交的更改时,不自动批量升级;不从报告中删除 finding(接受后记录到
.trivyignore);不将报告提交到部署服务器;不进行 cti-expert 类型的大范围外部威胁调查(仅包含 supply-watch keyless 检查)。
心智模型
Trivy 是否已安装?→ 范围(锁文件)→ 静态扫描 HIGH/CRITICAL → JSON+HTML 报告 → 总结 + 修复建议 → 重新扫描 NONE,并行执行 开发者假设 → 真实请求(curl/dig/git diff)→ 确认或发现漏洞,可选执行 品牌名称 → 确定性变体 → 实时 DNS + CT 日志。静态扫描干净并不意味着安全。
输入和输出约定
| 字段 | 必填? | 含义 | |
|---|---|---|---|
| 输入 | 源代码目录(be、fe 或 .) | 是 | 扫描目标;如果仓库中有 trivy.yaml,则使用 |
| 输入 | 正在运行的 HOST / domain | 动态扫描时需要 | 用于通过 curl/dig 进行实际验证 |
| 输入 | 品牌名称 | 否 | 用于 supply-watch.py |
| 输出 | security/trivy-report.json + security/trivy-report.html | 是 | 完整报告,仅作为审查 artifact |
| 输出 | 按目标分类的 HIGH/CRITICAL 表格 + 修复建议 | 是 | 升级 deps、使用非 root 的 USER、轮换 secret |
| 输出 | 动态扫描结果 | 是 | 逐项列出假设:成立/不成立,并附命令 + 实际 HTTP/DNS 代码 |
| 输出 | 重新扫描结果 | 有修复时 | remaining = NONE |
| 输出 | supply-watch 报告 | 可选 | rc 0 表示干净,2 表示有发现;crt.sh 出错 → 跳过 |
规则和能力
- RULE-01(必须):**静态(Trivy)和动态(上述检查清单)是两个不同的层面——两者都要运行。**Trivy 能发现 CVE/错误配置/文件中的 secret,但无法发现身份验证绕过、公开暴露、CORS/CSRF 逻辑问题、分支不一致。不要把 Trivy 报告干净视为安全。
- RULE-02(必须):不要相信开发者的默认假设——所有“已经有登录”“内部使用所以安全”“已经能运行”等说法,都必须先通过真实请求验证,才能下结论。
- RULE-03(必须):Trivy 扫描时不会修改代码——可随时安全运行。
- RULE-04(必须):已审查并接受的 finding → 记录到
.trivyignore(每行 1 个 ID + 原因注释 + 日期),不要从报告中删除。 - RULE-05(必须):不要将
security/*.json|html提交到部署服务器——它们仅作为审查 artifact。 - RULE-06(必须):部署 bonbon-ai 时:只将
be和fe(2 个子模块)推送到服务器;工具文件(trivy.yaml、security/、skill)不推送到服务器。 - RULE-07(必须):所有修复更改都必须在提交前通过构建/验证(
go build ./...、pnpm i等)。 - 能力:缺少本地扫描工具时可安装;以只读方式扫描源代码;向项目自身的 host 发送真实 HTTP/DNS 请求;在获准应用修复时修改 manifest/Dockerfile;读取公开 CT 日志/DNS(keyless)。
失败边界
- 无法安装 Trivy → 阻塞,告知用户。
- 子模块有尚未提交的更改 → 仅提出修复建议,不自动升级。
- 修复后无法构建(
go build ./...、pnpm i)→ 失败,不提交。 - 没有可用于动态扫描的 HOST → 部分完成:仅进行静态扫描,明确说明动态层尚未运行,不要得出“安全”的结论。
- secret 被标记 → 立即轮换 key(不能只从文件中删除)。
- supply-watch 无法调用 crt.sh → 跳过,不要断言扫描干净。
操作
主工作流
| 步骤 | 类型 | 输入 | 操作 | 输出/退出 | 失败/后续 |
|---|---|---|---|---|---|
| W01 | effect | 机器 | 步骤 0 — 检查并安装 Trivy(必须先运行) | 输出 trivy --version | 安装失败 → blocked |
| W02 | deterministic | 仓库 | 步骤 1 — 通过 lockfile 检测语言,排除 build/vendor 目录 | scope | — |
| W03 | deterministic | scope | 步骤 2 — 扫描漏洞、错误配置和机密,优先处理 HIGH/CRITICAL | findings | — |
| W04 | deterministic | findings | 步骤 3 — 将 JSON + HTML 报告输出到 security/ | 2 个报告文件 | — |
| W05 | judgment | findings | 步骤 4 — 按 target 汇总 HIGH/CRITICAL 并提出修复建议 | 表格 + 建议 | 子模块有未提交更改 → 仅提出建议 |
| W06 | deterministic | 已修复的 target | 步骤 5 — 重新扫描以确认 | remaining = NONE | 仍有问题 → 返回 W05 |
| W07 | effect | HOST、diff | 动态扫描:使用真实请求运行 8 项开发假设检查清单 | 每项假设均有证据 | 没有 HOST → partial |
| W08 | deterministic | 品牌名称 | 使用 supply-watch.py(B03)进行外部扫描 | rc 0 或 2 | crt.sh 出错 → 跳过 |
各步骤详情(W01–W08 的事实来源):
工作流
步骤 0 — 检查并安装 Trivy(必须先运行)
if ! command -v trivy >/dev/null 2>&1; then
echo "Trivy chưa có → cài…"
if [[ "$(uname)" == "Darwin" ]]; then
brew install trivy
else
# Linux: dùng script chính thức Aqua (không cần root nếu set BINDIR)
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh \
| sh -s -- -b /usr/local/bin
fi
fi
trivy --version # xác nhận; DB vuln tự cập nhật lần chạy đầu
步骤 1 — 检测语言(扫描范围)
查找 lockfile 以确定生态系统:go.sum/go.mod(Go)、package-lock.json/pnpm-lock.yaml(Node)、requirements.txt/poetry.lock(Python)。排除 node_modules、.next、.contentlayer、_archives、.git。
步骤 2 — 扫描(优先处理 HIGH+CRITICAL,以加快速度)
trivy fs <dir> \
--scanners vuln,misconfig,secret \
--severity HIGH,CRITICAL \
--skip-dirs '**/node_modules' --skip-dirs '**/.next' \
--skip-dirs '**/.contentlayer' --skip-dirs '_archives' \
--no-progress
bonbon-ai 仓库:分别扫描 be 和 fe(各自都是子模块)。如果仓库已有 trivy.yaml,优先使用 --config trivy.yaml。
步骤 3 — 输出完整报告
mkdir -p security
TPL=$(find $(brew --prefix trivy 2>/dev/null || echo /opt/homebrew) -name html.tpl 2>/dev/null | head -1)
trivy fs . <cờ skip-dirs như trên> --no-progress -f json -o security/trivy-report.json
trivy fs . <cờ skip-dirs như trên> --no-progress -f template --template "@$TPL" -o security/trivy-report.html
步骤 4 — 汇总并提出修复建议
按 target 统计 HIGH/CRITICAL,并打印表格。随后提出建议(如果子模块有未提交的更改,不要批量自动升级依赖):
- 容易升级的依赖(直接依赖,直接修改 manifest):例如
requirements.txt中的python-multipart。 - 间接依赖:运行
go get <pkg>@<ver>,然后运行go build ./...验证。注意,go get可能会提高go指令的版本;如果超过 Dockerfile 中的基础镜像版本,也要相应升级FROM golang:X-alpine。 - 错误配置 DS-0002(root 用户):在 Dockerfile 中添加非 root 用户
USER(Alpine 使用adduser -D,Debian 使用useradd -m,或者对 node-alpine 镜像使用USER node;记得对 volume/data 等可写目录执行chown)。 - 机密:如果 Trivy 报出机密,立即轮换密钥,不要只从文件中删除。
步骤 5 — 重新扫描以确认
在已修复的 target 上重新运行步骤 2,确认 remaining = NONE。
外部扫描 — 供应链与品牌(第三条路径,无需密钥)
上面两部分都是从项目内部向外看,没有任何部分从外部向内看:是否有人搭建了与你的名称相似的域名或 package 来欺骗用户,或将虚假依赖插入你自己的安装命令中。
python3 fdk/tools/supply-watch.py <tên-thương-hiệu> # sweep mặc định 7 TLD
python3 fdk/tools/supply-watch.py <tên> --tld com,dev --json # cho CI
python3 fdk/tools/supply-watch.py --self-test
按六种模式生成确定性、离线变体——删字、重复字母、倒序、误按相邻按键(QWERTY 键盘)、形似字符替换(o→0、l→1)、添加连字符——然后查询 DNS,检查哪些仍在运行。同时使用 CT monitor 读取 Certificate Transparency(crt.sh),查看是否有证书刚刚签发给相似域名。
无需 API key,也无需 .venv。退出码:0 表示干净,2 表示有发现。如果无法连接 crt.sh,会提示跳过,不会断言结果干净。
从
7onez/cti-expert(工作流 08)中少量吸收功能。有意只取这一小部分:cti-expert 有 121 个 op 和 78 个 MCP 工具,用于调查外部威胁,需要.venv、API key 和出站网络。整体合并会把密钥和网络依赖引入一个原本无需密钥且可离线运行的入口。
动态扫描 — 验证开发者假设(补充 Trivy)
原则:Trivy(静态扫描)无法发现架构、逻辑或运行时配置错误。 最严重的漏洞往往藏在开发者的默认假设中——必须通过真实请求验证,不能轻信。“能运行”≠“安全”。
源自 2026/06/22 的事故复盘:薪资 ETL API 没有身份验证(身份验证只在 Web 层,/etl 路径经 nginx 绕过)→ 任何人都能通过 curl 获取薪资和 3,637 名员工的 PII;以为是“内部服务”,但它有公共域名 devtingting.coteccons.vn(公共 IP),可桥接到整个互联网。Trivy 没有发现问题——只有实际执行 curl/dig 才能查出。
“别轻信——必须验证”清单(开发者假设 → 实际情况 → 验证方法)
-
“反向代理后的 API 有保护,因为 Web/UI 有登录。” → 错:身份验证通常只在 Web 层;代理路径(
/etl、/api等)可由浏览器直接调用,因此会绕过登录。 → 验证:对每个 API 路由直接执行curl,不附带 cookie/token → 必须返回401。如果返回200+数据,就是漏洞。身份验证必须在 API/代理层实现(例如 nginxauth_request),不能只在 UI 实现。for p in data/stats/all report/export sync/status; do curl -k -o /dev/null -w "$p -> %{http_code}\n" https://HOST/etl/$p; done # mong đợi 401 -
“服务器是内部服务器 / 私有 IP(192.168.x),所以外部无法访问。” → 错:公共域名、
tailscale funnel或端口转发都可能搭建通路。 → 验证:dig +short <所有可能的子域名>→ 是否有公共 IP?尝试从外部网络执行 curl。不要轻信“内部”这一说法——检查实际 DNS。 -
“开放 CORS 就是漏洞 / 关闭 CORS 就足够安全。” → 方向错:CORS 只会阻止跨域浏览器读取。它不会阻止
curl/脚本,也不会阻止 CSRF 写入(POST 查询参数 / 无请求体属于 简单请求 → 不会预检 → 无论 CORS 配置如何,服务器都会执行)。真正的漏洞通常是没有身份验证 + 端口开放。主入口(身份验证)还没锁好之前,别浪费时间折腾 CORS。 -
“保留默认配置没问题。” → 检查默认值是否进入生产环境:
CORS_ORIGINS还留着localhost:3000吗?secret/flag 还用着示例值吗?BIND_HOST是否意外设成了0.0.0.0?curl -k -D- -o /dev/null -H "Origin: http://localhost:3000" https://HOST/etl/health | grep -i access-control -
“部署哪个分支都一样。” → 错:CI(Jenkins)克隆分支 X,但服务器运行分支 Y → 两者不一致。合并冲突可能导致整个代码块丢失(例如 compose 中的
networks:→undefined network,部署失败)。 → 验证:CI 克隆的分支是否与正在运行的分支一致?git diff <ci-branch> <running-branch> -- docker-compose.yml .env* deploy/。 -
“paramiko/SSH 能连接就行。” →
Transport(...)/AutoAddPolicy不会验证主机密钥 → 中间人攻击(MITM)可窃取密码和文件。验证:必须固定 known_hosts 并使用RejectPolicy。 -
“Token/secret 怎么传都行。” → Token 放在 URL
?token=中 → 会进入 nginx/uvicorn 访问日志、Referer 和历史记录。验证:secret 必须通过请求头/cookie传递,不能放在查询字符串中。 -
“用
SELECT *比较方便。” → 会返回包含 PII 的所有列(CCCD/MST/BHXH/薪资);全列搜索还会成为探测数值的预言机。验证:对返回列使用白名单;搜索时不要扫描敏感列。
触发条件 — 哪些代码行为必须扫描
不必等人记得调用技能——diff 命中表中任一项,就必须触发扫描(根据 WorldFlowAI/everything-claude-code security-review 提炼):
| 刚完成的更改 | 必须执行 | 原因 |
|---|---|---|
| 添加/修改身份验证、会话、权限 | Trivy + 动态扫描 | Token 存在 localStorage 中会受到 XSS 影响,敏感操作前缺少角色检查——授权层的错误是 Trivy 无法发现的。 |
| 接收用户输入(表单、参数、上传) | Trivy + 动态扫描 | 输入未通过 schema 验证 + 文件上传未限制 size/type/extension,都是 SQLi/XSS/RCE 的入口。 |
| 涉及 secret / credential / API key | Trivy(secret scan) | Key 硬编码在 source 中或进入 git history——必须放在 env var 和平台 secret 中,.env 必须加入 gitignore。 |
| 新增 API endpoint | Trivy + 动态扫描 | 新 endpoint 默认缺少 rate-limit + CSRF + 权限检查;错误消息容易泄露内部详情/stack trace。 |
| 支付 / 敏感数据 | Trivy + 动态扫描 + 人工审查 | PII/资金不得写入 log,错误信息必须通用;一个漏洞就可能危及整个平台——宁可谨慎行事。 |
| 将 app 发布到 public domain / 更改 reverse proxy | 动态扫描 | “内部”免认证漏洞会在此刻暴露到互联网(上面的 checklist 假设开发环境)。 |
不符合表中任一项 → 按发布节奏扫描即可。自检问题:“这个 diff 是否涉及上述 6 项中的任何一项?”——不到一分钟就能回答。用户说“有没有漏洞”“安全吗”→ 一律视为触发条件。
分支
| ID | 类型 | 条件 | 行为 | 跳过 / 失败 | 汇合 |
|---|---|---|---|---|---|
| B01 | conditional_required | repo bonbon-ai | 分别扫描 be 和 fe(二者都是 submodule);部署时只推送这 2 个 submodule | 其他 repo → 扫描 . | W04 |
| B02 | conditional_required | repo 已有 trivy.yaml | 优先使用 --config trivy.yaml | 没有 → 默认使用 skip-dirs 标记 | W04 |
| B03 | user_optional | 用户想检查供应链 / 品牌 | supply-watch.py <名称> 扫描 7 个 TLD + CT 监控 | 无此要求 → 跳过 | 结束 |
| B04 | conditional_required | finding 已审查并接受 | 写入 .trivyignore(每行 1 个 ID + 原因 + 日期),不得从报告中删除 | — | W06 |
| B05 | conditional_required | Trivy 标记了 secret | 立即轮换 key,不能只从文件中删除 | — | W06 |
验证与停止条件
必须验证:Trivy 的 rc/output(重新扫描后 remaining = NONE)、curl 的真实 HTTP 状态码(API route 不带 token 时必须返回 401)、真实的 dig 结果、分支的 git diff、supply-watch.py 的 rc。只有 build/verify 成功后才能提交修复。需要人工处理:决定是否在 .trivyignore 中接受 finding,人工审查支付/敏感数据流程。重新扫描干净且 checklist 中的所有假设都有证据后即可停止;不能仅凭 Trivy 就得出“安全”的结论。
示例
- 正例:“扫描 bonbon-ai repo 的安全性”→ 已有 Trivy → 分别扫描
be、fe→ 发现 2 个 HIGH:requirements.txt中的python-multipart+ DS-0002 root 用户 → 升级依赖 + 添加USER node→ build 成功 → 重新扫描后remaining = NONE;动态扫描时 curl/etl/data/stats/all不带 token,返回401。 - **边界/失败:**Trivy 扫描干净,但直接 curl
/etl/report/export不带 cookie 却返回200+ 工资数据 → 这是 auth-bypass 漏洞,即使静态扫描报告干净也要严重上报(RULE-01);dig +short子域名得到 public IP → “内部”这一说法不成立。 - **边界:**运行
supply-watch.py acme时,如果 crt.sh 无响应 → CT 监控打印跳过,不得报告扫描干净。
来源
- **2026-07-17 吸收(adapt_mode: dissolve,T-260717-02):**触发条件表根据
WorldFlowAI/everything-claude-code提炼(skills/security-review/SKILL.md— When to Activate + 10 类 checklist)。在 scratchpad/ 中以 depth-1 克隆,未 vendoring 字节内容。