secrets-audit
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSecrets Audit — Credential Exposure and Secrets-Management Review
秘密审计——凭证泄露与秘密管理审查
Two halves: (1) find secrets that have already leaked into source, history, or artifacts, and (2) audit the secrets-management posture that determines whether future leaks happen.
Most secret leaks aren't "we forgot to redact" — they're "we never had a system, so every developer made up their own approach." This skill covers both the cleanup and the prevention.
Cross-references: (CI-related secrets risk in build-time exposure), (workload identity federation as the alternative to long-lived keys), A02 (in-source secret patterns).
dependency-auditiam-auditowasp-audit分为两部分:(1) 查找已泄露到源代码、历史记录或产物中的秘密;(2) 审计决定未来是否会发生泄露的秘密管理态势。
大多数秘密泄露并非“我们忘记编辑”,而是“我们从未建立系统,因此每个开发者都自行摸索方案”。本技能涵盖清理和预防两方面。
交叉参考:(构建时暴露的CI相关秘密风险)、(作为长期密钥替代方案的工作负载身份联合)、 A02(源代码中的秘密模式)。
dependency-auditiam-auditowasp-auditPart 1 — Find leaked secrets
第一部分——查找泄露的秘密
Provider key prefixes (high-confidence patterns)
服务商密钥前缀(高置信度模式)
The most useful first sweep is grep against known provider key prefixes. False positives are low and matches are almost always real.
bash
undefined最有效的首次排查是针对已知服务商密钥前缀执行grep命令。误报率低,匹配结果几乎都是真实泄露。
bash
undefinedStripe
Stripe
grep -rE "(sk_live_|sk_test_|rk_live_|whsec_)[A-Za-z0-9]{20,}" .
--include="*.{js,ts,jsx,tsx,py,rb,go,java,php,sh,env,yml,yaml,json}"
--include="*.{js,ts,jsx,tsx,py,rb,go,java,php,sh,env,yml,yaml,json}"
grep -rE "(sk_live_|sk_test_|rk_live_|whsec_)[A-Za-z0-9]{20,}" .
--include="*.{js,ts,jsx,tsx,py,rb,go,java,php,sh,env,yml,yaml,json}"
--include="*.{js,ts,jsx,tsx,py,rb,go,java,php,sh,env,yml,yaml,json}"
AWS access keys
AWS access keys
grep -rE "(AKIA|ASIA)[A-Z0-9]{16}" .
grep -rE "(AKIA|ASIA)[A-Z0-9]{16}" .
AWS secret keys (40 chars, base64-y) — high FP rate, use with caution
AWS secret keys (40 chars, base64-y) — high FP rate, use with caution
grep -rE "[A-Za-z0-9/+=]{40}" . --include=".env" --include="*.json"
grep -rE "[A-Za-z0-9/+=]{40}" . --include=".env" --include="*.json"
GitHub
GitHub
grep -rE "gh[pousr]_[A-Za-z0-9]{36}" .
grep -rE "gh[pousr]_[A-Za-z0-9]{36}" .
Google Cloud API key + service-account JSON
Google Cloud API key + service-account JSON
grep -rE "AIza[A-Za-z0-9_-]{35}" .
grep -rln '"type": "service_account"' . --include="*.json"
grep -rE "AIza[A-Za-z0-9_-]{35}" .
grep -rln '"type": "service_account"' . --include="*.json"
Slack
Slack
grep -rE "xox[baprs]-[A-Za-z0-9-]+" .
grep -rE "xox[baprs]-[A-Za-z0-9-]+" .
OpenAI / Anthropic
OpenAI / Anthropic
grep -rE "sk-[A-Za-z0-9]{32,}" .
grep -rE "sk-ant-[A-Za-z0-9_-]{90,}" .
grep -rE "sk-[A-Za-z0-9]{32,}" .
grep -rE "sk-ant-[A-Za-z0-9_-]{90,}" .
Generic high-entropy strings in env files
Generic high-entropy strings in env files
grep -rE "^[A-Z_]+=[A-Za-z0-9/+=]{32,}$" . --include=".env"
For full repo coverage, use `git ls-files` to scope to tracked files and avoid `node_modules`:
```bash
git ls-files | xargs grep -lE 'sk_live_|ghp_|AKIA[A-Z0-9]{16}|sk-ant-|AIza[A-Za-z0-9_-]{35}' 2>/dev/nullgrep -rE "^[A-Z_]+=[A-Za-z0-9/+=]{32,}$" . --include=".env"
如需覆盖完整仓库,使用`git ls-files`限定追踪文件范围,避免`node_modules`:
```bash
git ls-files | xargs grep -lE 'sk_live_|ghp_|AKIA[A-Z0-9]{16}|sk-ant-|AIza[A-Za-z0-9_-]{35}' 2>/dev/nullTooling
工具推荐
| Tool | Use |
|---|---|
| Fast, low FP, run as pre-commit and in CI; supports custom rules |
| Verifies findings against the real API (high confidence) |
| Yelp's tool; good baseline file workflow |
| GitHub Secret Scanning | Free for public repos; covers most providers automatically; pushes get blocked at push time when enabled with push protection |
| GitLab Secret Detection | Similar, built-in to CI |
| GitGuardian / Doppler / Spectral | Commercial; add organizational dashboards and historical analysis |
| 工具 | 用途 |
|---|---|
| 快速、低误报,可作为预提交钩子和CI环节运行;支持自定义规则 |
| 针对真实API验证检测结果(高置信度) |
| Yelp开发的工具;适用于基础文件扫描流程 |
| GitHub Secret Scanning | 公共仓库免费使用;自动覆盖多数服务商;启用推送保护后会在推送时拦截违规内容 |
| GitLab Secret Detection | 类似功能,内置到CI中 |
| GitGuardian / Doppler / Spectral | 商业工具;提供组织级仪表盘和历史分析功能 |
Git history (the part people forget)
Git历史记录(容易被忽略的部分)
A secret deleted in the latest commit is still in history — , , and any fork or local clone all have it.
git log -pgit log -S<secret>bash
undefined在最新提交中删除的秘密仍存在于历史记录中——、以及任何分支或本地克隆版本都包含该秘密。
git log -pgit log -S<secret>bash
undefinedSearch every commit for a pattern
搜索所有提交中的指定模式
git log -p -S "sk_live_" --all
git log -p -S "sk_live_" --all
Search only deleted lines
仅搜索被删除的行
git log -p --all | grep -E "^-.*sk_live_"
git log -p --all | grep -E "^-.*sk_live_"
Trufflehog historical scan
Trufflehog历史扫描
trufflehog git file://. --since-commit=<first-commit>
trufflehog git file://. --since-commit=<first-commit>
Git history rewrite — destructive, coordinate first
Git历史重写——破坏性操作,需先协调
git filter-repo --invert-paths --path config/secrets.yml
git filter-repo --invert-paths --path config/secrets.yml
or
或
bfg --delete-files secrets.yml
**Critical caveat:** rewriting history requires every developer to re-clone, every fork is still exposed, and the secret should be considered compromised regardless. Always rotate first, history-rewrite second.bfg --delete-files secrets.yml
**重要警告:** 重写历史记录要求所有开发者重新克隆仓库,所有分支仍会暴露秘密,且无论如何该秘密都应视为已泄露。务必先轮换密钥,再进行历史重写。Build artifacts and other forgotten places
构建产物及其他易被遗忘的位置
Secrets leak in places that aren't files:
.env- Docker images — shows every
docker history <image>line;ENVends up in layers--build-arg SECRET=... - CI environment — secrets logged by ,
set -x, error stack traces, debug outputconsole.log(process.env) - Frontend bundles — /
NEXT_PUBLIC_*/VITE_*env vars are shipped to the browser; grep the bundled JSREACT_APP_* - Crash reports — Sentry / Datadog / Bugsnag capturing snapshots
process.env - Logs — application logs shipped to a SIEM that has weaker access controls than the app
- Backups — of a table that includes user-stored API keys
pg_dump - Public S3 / blob storage — accidentally uploaded
.env - Documentation — README.md examples with real keys instead of placeholders
- Slack / Notion / Linear — pasted in a DM "to test," never rotated
- Browser localStorage / cookies — captured in shared screenshots or session replays
秘密会泄露到非文件的位置:
.env- Docker镜像 — 会显示所有
docker history <image>行;ENV会被存入镜像层--build-arg SECRET=... - CI环境 — 、
set -x、错误堆栈跟踪、调试输出会记录秘密console.log(process.env) - 前端打包文件 — /
NEXT_PUBLIC_*/VITE_*环境变量会被打包到浏览器端;可通过grep扫描打包后的JS文件REACT_APP_* - 崩溃报告 — Sentry / Datadog / Bugsnag会捕获快照
process.env - 日志 — 应用日志被发送到访问控制弱于应用本身的SIEM系统
- 备份 — 导出的表中包含用户存储的API密钥
pg_dump - 公共S3 / 对象存储 — 文件被意外上传
.env - 文档 — README.md示例中使用真实密钥而非占位符
- Slack / Notion / Linear — 为测试粘贴的密钥从未轮换
- 浏览器localStorage / cookies — 被共享截图或会话录屏捕获
Triaging a found secret
泄露秘密的分类处理
When you find a leaked secret:
- Verify it's live — use the provider's verification (,
aws sts get-caller-identity,stripe balance retrieve) — don't assume; some leaked keys are already revoked or were sandbox-onlycurl -H "Authorization: Bearer $TOKEN" ... - Determine exposure window — first commit it appeared in, when the repo went public, when CI logs were retained from
- Determine blast radius — what does this key access? What can be done with it? IAM permissions, Stripe live vs test, GitHub vs
repoadmin:org - Rotate immediately — generate a new key, deploy it, then revoke the old one (revoke-first breaks prod)
- Audit for use — provider audit logs (CloudTrail, GitHub audit log, Stripe events) for any activity from the leaked credential
- Then clean — remove from current code, then optionally history-rewrite (low priority once rotated)
- Document — incident report, even if rotation was clean; recurrence patterns surface trends
发现泄露的秘密后:
- 验证是否有效 — 使用服务商的验证方法(、
aws sts get-caller-identity、stripe balance retrieve)——不要假设;有些泄露的密钥已被撤销或仅用于沙箱环境curl -H "Authorization: Bearer $TOKEN" ... - 确定暴露窗口期 — 首次出现的提交记录、仓库公开时间、CI日志保留时间
- 确定影响范围 — 该密钥可访问哪些资源?能执行哪些操作?IAM权限、Stripe生产/测试环境、GitHub /
repo权限admin:org - 立即轮换 — 生成新密钥并部署,然后撤销旧密钥(先撤销会导致生产环境故障)
- 审计使用情况 — 服务商审计日志(CloudTrail、GitHub审计日志、Stripe事件)中该泄露凭证的所有活动
- 清理 — 从当前代码中删除,然后可选进行历史重写(轮换完成后优先级较低)
- 记录 — 即使轮换顺利也要撰写事件报告;重复模式会暴露趋势
Part 2 — Audit secrets-management posture
第二部分——审计秘密管理态势
The hierarchy of secret storage (worst → best)
秘密存储层级(最差→最优)
| Tier | Pattern | When acceptable |
|---|---|---|
| ❌ | Hardcoded in source | Never |
| ❌ | Hardcoded in image / build artifact | Never |
| ❌ | Plaintext in shared docs / Slack | Never |
| ⚠️ | | Bootstrap only; flagged in audit |
| ⚠️ | Environment variables (only) | Acceptable for ephemeral dev; weak for prod (visible in /proc, crash dumps, logs) |
| 🟢 | Secrets manager pulled at deploy time | Standard for most apps |
| 🟢 | Workload identity federation (no stored secret at all) | Best where supported |
| 层级 | 模式 | 可接受场景 |
|---|---|---|
| ❌ | 硬编码到源代码中 | 绝不允许 |
| ❌ | 硬编码到镜像/构建产物中 | 绝不允许 |
| ❌ | 明文存储在共享文档/Slack中 | 绝不允许 |
| ⚠️ | 仓库中的 | 仅用于初始化;审计中会被标记 |
| ⚠️ | 仅使用环境变量 | 临时开发环境可接受;生产环境安全性弱(可在/proc、崩溃转储、日志中查看) |
| 🟢 | 部署时从密钥管理器拉取 | 多数应用的标准方案 |
| 🟢 | 工作负载身份联合(无需存储任何秘密) | 支持该方案的场景下最优 |
Cloud-provider secrets managers
云服务商密钥管理器
- AWS Secrets Manager / Parameter Store (SecureString) — integrate via IAM-scoped IRSA / task role / Lambda role
- GCP Secret Manager — bind via Workload Identity to GSA, GSA pulls secret
- Azure Key Vault — pull via managed identity
- Doppler / Infisical / 1Password Secrets Automation — cross-cloud, developer-friendly
- AWS Secrets Manager / Parameter Store (SecureString) — 通过IAM权限范围的IRSA/任务角色/Lambda角色集成
- GCP Secret Manager — 通过Workload Identity绑定到GSA,由GSA拉取秘密
- Azure Key Vault — 通过托管身份拉取
- Doppler / Infisical / 1Password Secrets Automation — 跨云平台,对开发者友好
Audit checklist
审计检查清单
- No secrets in Git history (run gitleaks --all)
- No committed —
.envcovers.gitignore(with care for.env*).env.example - Secrets fetched at runtime, not embedded at build — image rebuild is not required to rotate
- IAM scoped to the secret — service A can read secret A, not secret B
- Rotation cadence — defined per secret class (admin: 30d, service: 90d, customer-shared: per breach response)
- Rotation is automated — if a human runs a script every 90 days, rotation will eventually drift
- Access logged — every Get / Decrypt call is in an audit trail
- No long-lived cloud keys for workloads — workload identity federation everywhere it's supported (see )
iam-audit - Break-glass procedure — when the secrets manager is down, how do critical services come up? (Usually: cached on disk encrypted, with strict re-fetch on restart)
- Cross-environment isolation — staging cannot read prod secrets, ever (different KMS keys, different IAM)
- Git历史记录中无秘密(运行gitleaks --all)
- 无文件被提交 —
.env覆盖.gitignore(注意区分.env*).env.example - 秘密在运行时拉取,而非构建时嵌入 — 轮换密钥无需重新构建镜像
- IAM权限与秘密绑定 — 服务A仅能读取秘密A,无法读取秘密B
- 轮换周期 — 按秘密类别定义(管理员密钥:30天,服务密钥:90天,客户共享密钥:按泄露响应情况)
- 轮换自动化 — 如果需要人工每90天运行脚本,轮换最终会出现偏差
- 访问日志记录 — 所有Get/Decrypt调用都记录在审计日志中
- 工作负载无长期云密钥 — 所有支持的场景都使用工作负载身份联合(参见)
iam-audit - 应急流程 — 密钥管理器故障时,关键服务如何启动?(通常:加密缓存到磁盘,重启时严格重新拉取)
- 跨环境隔离 — staging环境绝不能读取生产环境秘密(使用不同KMS密钥、不同IAM)
Common findings
常见问题
- Rotation never tested — secret stores configured, never actually rotated; first attempt breaks prod
- shipped to staging — environment-specific dev secrets cross the boundary
.env.local - CI secrets accessible from PRs from forks — GitHub's default behavior was previously dangerous; verify and secret accessibility
pull_request_target - Build args used for secrets — ends up in image history (use
--build-arg AWS_SECRET=.../BuildKit instead)--secret - Logging frameworks dump on unhandled exception — Sentry / Datadog / Bugsnag scrub config required
process.env - Secret stored in K8s as plain Secret without etcd encryption — base64 is encoding, not encryption (see )
container-audit - OAuth client secrets in mobile apps — public clients can't hold secrets; PKCE is the answer
- 轮换从未测试 — 已配置密钥存储,但从未实际轮换;首次尝试会导致生产环境故障
- 被部署到staging环境 — 环境专属的开发秘密越界泄露
.env.local - 来自分支PR的CI秘密可访问 — GitHub默认行为曾存在风险;需验证和秘密访问权限
pull_request_target - 使用构建参数传递秘密 — 会被存入镜像历史(改用
--build-arg AWS_SECRET=.../BuildKit)--secret - 日志框架在未处理异常时输出— 需要配置Sentry/Datadog/Bugsnag进行信息清理
process.env - 秘密以明文Secret形式存储在K8s中且未启用etcd加密——base64是编码而非加密(参见)
container-audit - OAuth客户端密钥存储在移动应用中 — 公共客户端无法保存秘密;应使用PKCE方案
Output Format
输出格式
markdown
undefinedmarkdown
undefinedSecrets Audit Report
秘密审计报告
Scope: [repos / environments / managers covered]
范围:[覆盖的仓库/环境/管理器]
Date: [date]
日期:[日期]
Live leaked secrets found
发现的有效泄露秘密
| Provider | Location | First seen (commit / date) | Verified live? | Rotation status |
|---|
| 服务商 | 位置 | 首次出现时间(提交/日期) | 是否验证有效? | 轮换状态 |
|---|
Secrets-management posture
秘密管理态势
| Category | Status | Notes |
|---|
| 类别 | 状态 | 备注 |
|---|
Recommendations
建议
| Priority | Item | Owner | Deadline |
|---|
Disposition rule (Fixed / Deferred / Accepted Risk) per `owasp-audit`.| 优先级 | 事项 | 负责人 | 截止日期 |
|---|
按照`owasp-audit`的处置规则(已修复/延期/接受风险)处理。Boundaries
边界规则
- Only audit repositories, CI systems, and infrastructure the user has authorization for
- Never use a found secret to access the provider — verify it's live with a minimal API call (account info, not data extraction); do not pivot
- For history rewrite operations: never proceed without explicit confirmation and a coordinated developer-notification plan
- Refuse to help collect or weaponize leaked secrets found in other people's repos
- If the audit surfaces credentials belonging to a third party (vendor, employee personal accounts), notify and rotate; don't quietly fix
- 仅审计用户有权限访问的仓库、CI系统和基础设施
- 绝不能使用发现的秘密访问服务商——通过最小化API调用(账户信息,而非数据提取)验证其有效性;不得进一步操作
- 历史重写操作:未经明确确认和开发者协调通知计划,绝不能执行
- 拒绝协助收集或利用在他人仓库中发现的泄露秘密
- 如果审计发现第三方(供应商、员工个人账户)的凭证,需通知对方并轮换;不得私下修复
References
参考资料
- OWASP Cheat Sheet: Secrets Management
- NIST SP 800-57 (Recommendation for Key Management)
- GitGuardian "State of Secrets Sprawl" annual reports — useful for industry context
- ,
gitleaks,trufflehogdocumentationdetect-secrets - GitHub Secret Scanning + Push Protection documentation
- HashiCorp Vault Architecture / Best Practices
- AWS Secrets Manager Best Practices
- "Twelve-Factor App" — Config principles
- OWASP Cheat Sheet: Secrets Management
- NIST SP 800-57(密钥管理建议)
- GitGuardian年度《秘密扩散现状报告》——有助于了解行业背景
- 、
gitleaks、trufflehog文档detect-secrets - GitHub Secret Scanning + Push Protection文档
- HashiCorp Vault架构/最佳实践
- AWS Secrets Manager最佳实践
- 《十二因素应用》——配置原则