mcpField
C
cloud-audit

cloud-audit

github.com/briiirussell安全478364 次安装1 天前更新
代码仓库

关于 cloud-audit

cloud-audit 是面向云平台负责人与安全团队的基础设施配置审查技能,覆盖 AWS、GCP、Azure 及多种 PaaS。它检查身份权限、网络、存储、计算、监控和部署配置,并以共享格式记录发现。

主要功能

  1. 01审查 AWS、GCP 和 Azure 配置
  2. 02检查多种 PaaS 项目与部署
  3. 03评估身份权限和网络暴露
  4. 04检查存储、计算及日志监控
  5. 05按共享格式记录安全发现

适用场景

  1. 01审计云账户的权限与公开访问
  2. 02排查 PaaS 上的陈旧或异常部署
  3. 03检查仓库安全默认设置与 Supabase 配置

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/briiirussell/cybersecurity-skills --skill cloud-audit

安装后在 Claude Code 中输入/cloud-audit确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
findings-format.md
findings.schema.json
paas.md
severity-calibration.md
to-sarif.mjs
validate-findings.mjs
verification.md

详细介绍

云审计 — 云基础设施安全审查

审计云基础设施配置中的错误配置、权限过高、公开暴露和合规性缺口。涵盖 AWS、GCP 和 Azure,以及许多小团队用来运行所有服务的 PaaS 部署平台(Vercel、Netlify、Heroku、Render、Railway、Fly)。

交叉参考:iam-audit 用于深入审查 IAM(咨询顾问式,涵盖身份提供商和联合模式的设计、审计与迁移)——本技能包含 IAM 部分,但侧重云安全态势;如需角色设计、JIT 访问、工作负载身份联合和迁移计划,请调用 iam-audit。container-audit 用于审查建立在云之上的 Kubernetes 专属安全态势。secrets-audit 用于检查密钥管理器的卫生状况和轮换。patch-sweep 用于响应一批 PaaS 应用中的 CVE(本技能的 PaaS 部分是其中的安全态势审查部分)。scanner-pipeline 用于定期运行 Supabase 的安全顾问和其他扫描器。

调查结果记录在共享的 findings.json 格式中(参见验证后记录)。处置方式通常由 finding-triage 后续设置:已修复 / 已延期 / 已接受风险 / 已缓解(平台/配置)/ 需要重大迁移。

授权

仅审计用户拥有或获准审查的云账户、项目、订阅和 PaaS 团队,并使用为此提供的凭据。预先批准的命令仅用于读取和描述信息。审计过程中绝不可更改策略、轮换密钥、删除资源或重新部署:提出建议,由所有者执行。如果审计凭据拥有超出只读范围的权限,请将此项本身报告为调查结果。

确定审计范围

确定:

  1. 云服务提供商和账户
  2. 使用中的区域
  3. 是否可用 CLI 工具(aws、gcloud、az、vercel、heroku、netlify、fly、railway、gh),或是否正在审查 IaC 文件(Terraform、CloudFormation、Pulumi)
  4. 对于 PaaS:范围内的每个团队/账户和 GitHub 所有者/组织,以及其中哪些属于客户或其他维护者

审计类别

身份与访问管理

AWS:

aws iam get-account-summary
aws iam list-users
aws iam generate-credential-report && aws iam get-credential-report --output text --query Content | base64 -d

检查:根账户未启用 MFA、超过 90 天的访问密钥、未使用的凭据、通配符权限("Action": "*")、权限过高的角色。

GCP:

gcloud projects get-iam-policy $PROJECT_ID
gcloud iam service-accounts list

检查:过多主体拥有基本角色(Owner/Editor)、未使用的服务账户、使用服务账户密钥而非工作负载身份。

Azure:

az role assignment list --all
az ad user list

检查:过多的 Owner/Contributor 分配、拥有高权限的访客用户。

IaC 审查: 在 Terraform/CloudFormation 文件中搜索 "Action": "*"、"Resource": "*"、硬编码密钥和范围过宽的信任策略。

网络安全

检查:

  • 允许从 0.0.0.0/0 入站的安全组或防火墙规则
  • 从互联网无限制开放 SSH(端口 22)或 RDP(端口 3389)
  • 已禁用 VPC 流日志
  • 数据库位于公有子网
  • 缺少各层之间的网络隔离
存储

AWS S3:

aws s3api list-buckets
aws s3api get-public-access-block --bucket <name>
aws s3api get-bucket-policy --bucket <name>
aws s3api get-bucket-encryption --bucket <name>

检查:公开存储桶、未启用加密、未启用版本控制、缺少生命周期策略、权限过于宽松的存储桶策略。

GCP/Azure: 对 Cloud Storage 和 Blob Storage 执行同类检查——查找 allUsers/allAuthenticatedUsers 访问权限或匿名 Blob 访问权限。

计算
  • 是否强制启用 IMDSv2?(AWS:HttpTokens = required)
  • 未加密的 EBS 卷或磁盘
  • 不需要公网 IP 的实例却配置了公网 IP
  • 过时的 AMI 或镜像(检查补丁时效)
  • 特权容器、Kubernetes 中缺少安全上下文
日志与监控
  • 是否在所有区域启用 CloudTrail / Cloud Audit Logs / Activity Log
  • 日志存储是否已加密、不可变且保留时间充足
  • 是否启用 GuardDuty / Security Command Center / Defender for Cloud
  • 是否为以下事件配置告警:根账户登录、IAM 变更、安全组变更、大规模数据传输
  • 是否启用 VPC 流日志和 DNS 查询日志
密钥管理
  • 在源代码、环境变量或 IaC 文件中硬编码密钥
  • 使用 Secrets Manager / Key Vault 管理敏感值
  • 已配置 KMS 密钥轮换
PaaS(Vercel / Netlify / Heroku / Render / Railway / Fly)

许多小团队根本没有 AWS 账户;他们的生产环境可能是一个 Vercel 团队、几个 Heroku 应用和一个 Render 服务。此类平台上的风险不会出现在 AWS 风格的检查清单中:生产环境不会被任何合并替换、Git 部署已失败数月,以及旧项目仍在平台 URL 上提供未打补丁的代码。以下各项检查均来自 2026 年 10 月的一次真实平台集群巡查。

先盘点:列出每个团队的所有项目 / 应用、用于构建的仓库和分支,以及每个项目提供服务的所有域名(patch-sweep 的步骤 1 中有完整的映射命令)。除非标明,否则以下命令均为只读。Netlify、Railway 和 Fly 的对应做法见 references/paas.md。

1. 过时的手动生产部署。 某客户网站的生产环境运行的是开发者笔记本上执行的 vercel deploy --prod,部署已过去 96 天,仍在提供存在漏洞的 Next.js。仓库的 main 分支里只有一个 README,因此无论怎么合并都不会替换该部署。

vercel ls <project> --prod --scope <team>                    # latest production deployments, age
vercel inspect <production-url> --scope <team>               # target, created, url
vercel api "/v6/deployments?projectId=<id>&target=production&limit=5" --scope <team> \
  | jq '.deployments[] | {url, created, source, sha: .meta.githubCommitSha, ref: .meta.githubCommitRef, creator: .creator.username}'
git ls-remote origin refs/heads/<production-branch>          # compare with the deployed sha
heroku releases -a <app> -n 20                               # who deployed, and how

检查:源代码来自 Git(而非 cli),已部署的提交与生产分支 HEAD 相同(或是其祖先),且部署时间晚于最近一次合并。若不匹配,则属于下文所述的发现类型。

2. Git 部署悄然失效。 有两种情况:一种是忽略构建步骤运行 git diff HEAD^ HEAD,但 .vercelignore 排除了 .git——.vercelignore 同样适用于 Git 构建——因此每次 Git 部署都会报错,生产环境只能通过 CLI 更新;另一种是某个项目仍关联到旧组织的仓库,因此每个 PR 都会显示失败的检查,人们已经习惯忽略它。

vercel ls <project> --status ERROR --scope <team>            # recent failures
vercel api /v9/projects/<project> --scope <team> | jq '{link: .link, productionBranch: .link.productionBranch, ignore: .commandForIgnoringBuildStep, rootDirectory}'
grep -n '\.git' .vercelignore 2>/dev/null
gh api repos/<o>/<r>/commits/<branch>/check-runs --jq '.check_runs[] | {name, app: .app.slug, conclusion}'   # duplicate/failing Vercel checks

检查:最近 10–20 次由 Git 触发的部署的失败率、忽略命令所需的内容(Git 历史记录、.vercelignore 排除的文件),以及 link.org / link.repo 是否与仓库当前所有者一致。

3. 仍在提供旧代码的旧项目。 域名迁移到新的单体仓库后,旧项目仍通过未打补丁代码提供 *.vercel.app 地址。

vercel project ls --format json --scope <team>
vercel api /v9/projects/<project>/domains --scope <team> | jq -r '.domains[].name'
heroku apps --all --json | jq -r '.[] | "\(.name)\t\(.updated_at)"'; heroku domains -a <app>

检查:域名只有平台默认域名(*.vercel.app、*.herokuapp.com、*.onrender.com、*.netlify.app、*.fly.dev、*.up.railway.app)的项目,以及它们最近一次部署的日期。建议删除;如果所有者希望保留,则启用保护(部署保护 / 维护模式)。

4. 每个仓库对应多个重复项目。 一个仓库会在两个 Vercel 团队中触发构建。虽然只有一个项目提供域名服务,但两个项目都保存了环境变量和密钥。 检查:按 link.org/link.repo 对每个团队的项目分组;除非所有者能说明原因,否则每个仓库 + 根目录对应多个项目都应记录为发现。比较环境变量名称(vercel env ls --scope <team>),查看额外副本保存了哪些变量。

5. 预览和生产环境暴露风险。

vercel project protection <project> --format json --scope <team>   # SSO / password / bypass settings
curl -s -o /dev/null -w '%{http_code}\n' https://<project>.vercel.app/   # 200 = generated production URL is public
vercel env ls preview --scope <team>                                   # names only

检查:预览环境是否启用了部署保护;当自定义域名位于 Cloudflare 或其他 WAF 后方时,生成的 *.vercel.app 生产 URL 是否无法访问(该 URL 会绕过 WAF——Vercel 的 Standard Protection 会保护生成的 URL);预览环境变量是否未指向生产数据库。若要比较数据库主机而不暴露密钥,可拉取到临时文件,只打印主机名,然后删除文件:vercel env pull /tmp/p.env --environment=preview && sed -nE 's/^DATABASE_URL="?[^@]*@([^/:]+).*/\1/p' /tmp/p.env; rm /tmp/p.env。

6. 构建队列构成可用性风险。 对于一次只能运行一个构建的团队,紧急补丁曾因无关构建排队而等待 30–60 分钟。

vercel ls --status QUEUED,BUILDING --scope <team>

检查:团队的并发构建数限制。在事件应急手册中记录如何发布紧急补丁:按需提高并发数、取消排队中的非紧急构建,或采用所有者批准的 CLI 部署流程(随后需与 Git 状态核对——见检查 1)。 7. Heroku 特定事项。

heroku stack -a <app>                                   # heroku-22 / heroku-24
heroku run --no-tty "vips --version" -a <app>           # libvips on the running dyno
heroku run --no-tty "ruby -v" -a <app>                  # compare with .ruby-version / Gemfile ruby
heroku pg:backups:schedules -a <app>
heroku pg:backups -a <app>                              # lists backups AND restores
heroku config -a <app> --json | jq -r 'keys[]'          # names only, never values
heroku --version

检查:

  • Stack 和 libvips 版本。VIPS_BLOCK_UNTRUSTED=1(用于缓解 CVE-2026-66066)需要 libvips ≥ 8.13;Heroku-24 随附 8.15.1。
  • .ruby-version 中指定的运行时才是实际运行的版本。
  • 是否设置了 pg:backups 备份计划,以及是否至少执行过一次恢复(从未恢复过的备份未经测试)。
  • Heroku CLI 8.x 无法在 Essential 计划上运行 pg:backups;在断定缺少备份之前,请先升级 CLI。
  • Review 应用不会继承线上密钥:检查流水线的 Review 应用配置变量,以及 app.json env 中的生产环境 Stripe/电子邮件/数据库凭据。

8. 仓库级安全默认设置。 某个账户和组织中的 142 个仓库关闭了 Dependabot 警报。

gh api repos/<o>/<r>/vulnerability-alerts --silent && echo on || echo off   # 204 = on, 404 = off
gh api repos/<o>/<r> --jq '.security_and_analysis'                          # secret scanning, push protection
gh api repos/<o>/<r>/branches/<production-branch>/protection                # 404 = no classic protection
gh api repos/<o>/<r>/rules/branches/<production-branch>                     # rulesets that apply

检查生产分支上的漏洞警报、密钥扫描、推送保护和分支保护(或规则集)——该分支可能不是默认分支。启用警报的命令是 gh api -X PUT repos/<o>/<r>/vulnerability-alerts;这是写操作,因此会提示确认。

后端即服务(Supabase)。 如果应用使用 Supabase,请运行其安全顾问——rls_disabled_in_public 会标记使用 anon 密钥即可读取和写入的公开表。在 2026 年 10 月的扫描中,共发现 10 个此类表,其中包括包含 472k 封入电子邮件正文的表。使用 supabase db advisors 或 Management API GET /v1/projects/{ref}/advisors/security;scanner-pipeline 涵盖了按计划运行该检查,以及用于检测 x.col = x.col 等恒真策略的 semgrep 规则。

发现类型:无法从源代码重现生产环境(手动部署/分支不匹配)

当生产环境中运行的内容无法从生产分支重新构建时,请报告此问题:

  • 当前生产部署来自 CLI/手动部署,而非 git;
  • 已部署的提交不在生产分支上;
  • git 部署失败,导致分支与生产环境不一致;
  • 平台的生产分支不是人们合并代码的分支(例如,main 中只有一个 README,而应用位于 development)。

重要性:合并到分支的补丁永远不会进入生产环境,无人能确定线上运行的代码是什么,回滚也会回到未知状态。严重程度取决于线上运行的内容:如果手动部署中有易受攻击的框架,严重程度就与该漏洞一样高;如果没有已知易受攻击的内容,则为中等。修复方案由负责人决定——修复构建问题后从 git 重新部署、将已部署的代码纳入分支,或停用项目——绝不能悄悄使用 vercel deploy --prod 覆盖他人的部署。对于一批此类项目,请运行 patch-sweep。

验证并记录

根据 references/findings-format.md 中的定义,为上述类别中的每个候选项给出一个结论,然后写入 findings.json。

1. 先保存证据。 这些发现大多与已部署的资源有关,而非文件。对每项发现,将只读命令的输出脱敏后保存到 <audit dir>/evidence/<name>.json(或 .txt),并进行美化格式化(| jq .),以便行号保持不变。文件名应包含命令和资源名称:evidence/aws-s3api-get-bucket-policy-prod-uploads.json、evidence/vercel-deployments-acme-web.json。让 location、trace[] 和 evidence[] 指向该文件以及包含决定性字段("Principal": "*"、"CidrIp": "0.0.0.0/0"、"source": "cli")的行,路径应像其他位置一样相对于仓库(security-audit/evidence/...)。对于没有仓库的纯账户审计,路径相对于审计目录,并在报告标题中说明这一点。对于纯 IaC 发现,则改为指向 .tf/CloudFormation/Pulumi 文件及其行号。

绝不要保存秘密值。写入文件前,删除环境变量和配置变量的值、令牌、预签名 URL、连接字符串中的密码以及密钥材料。保留查找资源所需的标识符(账户 ID、ARN、存储桶名称、项目 ID);访问密钥 ID 仅保留末尾 4 位(AKIA…7QXZ)。 2. 在确认每个候选项之前,先按照 references/verification.md 运行反证流程。 对于云环境发现项,“路径”是指:谁能访问它(互联网、提供商中的任意已认证主体、另一个租户、CI 作业)→ 允许其访问的规则 → 资源及其所含内容。查找位于它之前的最强控制措施:账户级 Block Public Access、SCP 或组织策略、VPC 端点策略、没有通往互联网网关路由的私有子网、部署保护、IdP 条件。根据证据文件,将路径写成 trace[]:entrypoint = 允许主体进入的规则或设置,propagation = 将其与资源关联的内容(附加到实例 ENI 的组、路由表),sink = 资源及其所含内容。

3. 选择判定结果。

判定结果此处的判断依据
confirmed保存的输出显示了暴露情况以及其后的内容。示例:get-bucket-policy 授予 "Principal": "*" s3:GetObject 权限,get-public-access-block 显示存储桶和账户级别的 RestrictPublicBuckets: false,且存储桶中存有客户上传的文件。安全组允许 0.0.0.0/0 通过 5432 端口访问,并附加到 PubliclyAccessible: true 的 RDS 实例。Vercel 上的生产环境是 96 天前的一次 source: cli 部署,其提交不在生产分支上,且运行的 Next.js 版本存在已知 CVE。
needs_validation配置支持这一说法,但有一项事实无法读取或未能读取。示例:Terraform 将 22 端口开放给 0.0.0.0/0,但没有状态文件或账户访问权限来证明该配置已应用并附加到资源(阻碍因素:该模块是否已部署;计划:aws ec2 describe-security-groups --group-ids <id> 和 aws ec2 describe-network-interfaces --filters Name=group-id,Values=<id>)。预览环境的 DATABASE_URL 主机看起来像生产环境,但只有所有者才能提取该环境变量(计划:执行检查 5 中仅提取主机名的 vercel env pull 命令)。你描述但未运行的任何检查,若原因是未经授权,都应标记为 needs_validation,并在 validation_plan 中写明确切命令。
rejected位于明确位置的具名控制措施会阻止所有路径。示例:存储桶策略授予 "Principal": "*" 权限,但账户级公开访问阻止措施(运行 aws s3control get-public-access-block 并将结果保存为证据)中的 RestrictPublicBuckets: true,因此 ruled_out_by.location 应指向该证据文件和行号。宽松开放的安全组未附加到任何资源(describe-network-interfaces 返回 []),且 ruled_out_by 指向该已保存的输出。

你收到的 IaC 模块中存在不安全的默认配置(例如,除非传入 block_public = true,否则会创建公开存储桶的模块),应判定为 confirmed,并设置 system_configuration 条件(“未覆盖 block_public 的部署”),置信度为 medium。

没有追踪到影响的缺口属于安全加固建议,而非记录项:关闭了 VPC 流日志、关闭了 KMS 轮换、没有 S3 生命周期策略、存储桶关闭了版本控制但未追踪到任何数据丢失场景、GuardDuty 关闭但没有其他问题。将这些内容放入报告的安全加固部分,不标注严重性。

4. 仅针对 confirmed 记录,按照 references/severity-calibration.md 校准严重性;根据暴露资源所含内容及其允许的操作评级,而非根据基准 ID。 公开的营销图片存储桶属于 Low 或安全加固建议;公开的客户文档存储桶属于 High。overall 不得高于已证实的影响。

置信度:从实时 API 读取的配置是证据,并不代表复现。只有通过经授权的非破坏性请求证明了暴露情况,才设置 "reproduced": true(并允许使用 high 置信度):例如,匿名执行 curl -sI 请求对象并收到 200 响应;或者生成的 *.vercel.app URL 返回 200,而自定义域名位于 WAF 后方。仅有 IaC 的发现项,置信度最高为 medium。 5. 按资源而非行进行指纹标识。 格式:cloud-audit/<class>/<provider>/<account>/<resource>;IaC 使用 cloud-audit/<class>/<IaC file>/<resource address>。ARN 和 host:port 请用斜杠表示;验证器会拒绝 :<digits> 片段。

cloud-audit/public-bucket/aws/123456789012/prod-uploads
cloud-audit/open-ingress/aws/123456789012/sg-0a1b2c3d/5432
cloud-audit/iam-wildcard/aws/123456789012/role/deploy        # arn:aws:iam::123456789012:role/deploy
cloud-audit/manual-prod-deploy/vercel/acme-team/acme-web
cloud-audit/iam-wildcard/infra/iam.tf/aws_iam_policy.deploy

使用中的类别:public-bucket、open-ingress、public-database、iam-wildcard、root-no-mfa、stale-access-key、imdsv1、logging-disabled、manual-prod-deploy、git-deploy-broken、legacy-project、duplicate-project、preview-exposure、review-app-live-keys、rls-disabled、repo-security-defaults。如果没有合适的类别,请新增一个。

6. 域字段放在 ext 下:

键值
provideraws、gcp、azure、vercel、netlify、heroku、render、railway、fly、supabase、github
account账户 ID、项目 ID、订阅 ID,或 PaaS 团队/组织 slug
regionus-east-1、europe-west1、global(对于没有区域的 PaaS,省略此项)
resource提供商显示的资源名称(ARN、存储桶名称、sg-…、项目名称、部署 URL)

7. 编写并验证。 设置 skill: "cloud-audit",按指纹排序,写入 findings.json,并持续修复,直到验证通过:

node references/validate-findings.mjs findings.json
node references/to-sarif.mjs findings.json -o findings.sarif   # optional

重新运行时,加载之前的 findings.json 并按指纹匹配。除非记录所指的控制项发生变化,否则 rejected 记录应继续保持拒绝状态(先重新读取相关证据)。

输出格式

先写入 findings.json。报告由该文件生成,不会更改 JSON 中未说明的判定结果、严重程度、阻断项或影响。不要使用“潜在”或“可能”等标签:条目必须是已确认的问题、待验证的问题、被拒绝的记录或加固说明。

# Cloud Security Audit Report
## Provider(s): [AWS / GCP / Azure / Vercel / Heroku / Render / ...]
## Account(s) / team(s): [IDs or slugs]   ## Regions: [audited regions]   ## Date: [date]
## Scope: [full | partial — what was left out and why]   ## Access: [read-only role / CLI identity used]
## findings.json: [path] — validated: [yes]   ## Evidence: [audit dir]/evidence/

### Summary
- Confirmed: [N] (Critical [n] | High [n] | Medium [n] | Low [n])
- Needs validation: [N]   Rejected: [N]   Hardening notes: [N]

### Confirmed findings
#### [SEVERITY] [Category]: [Title]  `fingerprint`
**Provider / account / region:** [ext.provider / ext.account / ext.region]
**Resource:** [ext.resource]
**Evidence:** `evidence/<file>:<line>` — [the decisive lines, redacted]
**Confidence:** [medium | high (reproduced)]   **Conditions:** [from conditions[]]
**What and why it matters:** [who can reach it → the rule that lets them in → what the resource holds]
**Fix:** [specific command or IaC change; note availability impact]
**Verify the fix:** [the read-only command that shows it's closed]

### Needs validation
| Finding | Blocker | Check for the owner to run |
|---|---|---|

### Hardening notes (not findings)
- [gap] — [why it isn't a finding] — [effort]

### Rejected (do not re-raise)
| Fingerprint | Ruled out by | Location |
|---|---|---|

### Coverage
| Category | Accounts / teams checked | Not checked (and why) |
|---|---|---|
| IAM / Network / Storage / Compute / Logging / Secrets / PaaS / Supabase / Repo defaults | | |

### PaaS deployment inventory
| Team | Project / app | Repo + production branch | Source of live deploy (git / cli) | Deployed sha = branch HEAD? | Domains |
|---|---|---|---|---|---|

### Prioritized remediation plan
1. [Critical — immediate]
2. [High — this week]
3. [Medium — this month]
4. [Low — next quarter]

边界

  • 仅审计用户有权访问的账户或项目
  • 对于 PaaS:审计期间不要删除项目、覆盖他人的生产部署或禁用保护措施;记录负责人的决定
  • 切勿打印环境变量或配置变量的值;仅列出名称
  • 不要尝试访问其他账户或租户
  • 为每项发现提供修复建议
  • 如果修复可能影响可用性,请注明(例如,收紧安全组可能会中断连接)
  • 标记审计期间发现的任何活动入侵迹象
  • 拒绝利用他人基础设施中发现的错误配置的请求

参考资料

评论

支持 Markdown