secrets-audit

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Secrets 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:
dependency-audit
(CI-related secrets risk in build-time exposure),
iam-audit
(workload identity federation as the alternative to long-lived keys),
owasp-audit
A02 (in-source secret patterns).
分为两部分:(1) 查找已泄露到源代码、历史记录或产物中的秘密;(2) 审计决定未来是否会发生泄露的秘密管理态势。
大多数秘密泄露并非“我们忘记编辑”,而是“我们从未建立系统,因此每个开发者都自行摸索方案”。本技能涵盖清理和预防两方面。
交叉参考:
dependency-audit
(构建时暴露的CI相关秘密风险)、
iam-audit
(作为长期密钥替代方案的工作负载身份联合)、
owasp-audit
A02(源代码中的秘密模式)。

Part 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
undefined

Stripe

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}"
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}"

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/null
grep -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/null

Tooling

工具推荐

ToolUse
gitleaks detect
Fast, low FP, run as pre-commit and in CI; supports custom rules
trufflehog git file://.
Verifies findings against the real API (high confidence)
detect-secrets scan
Yelp's tool; good baseline file workflow
GitHub Secret ScanningFree for public repos; covers most providers automatically; pushes get blocked at push time when enabled with push protection
GitLab Secret DetectionSimilar, built-in to CI
GitGuardian / Doppler / SpectralCommercial; add organizational dashboards and historical analysis
工具用途
gitleaks detect
快速、低误报,可作为预提交钩子和CI环节运行;支持自定义规则
trufflehog git file://.
针对真实API验证检测结果(高置信度)
detect-secrets scan
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 —
git log -p
,
git log -S<secret>
, and any fork or local clone all have it.
bash
undefined
在最新提交中删除的秘密仍存在于历史记录中——
git log -p
git log -S<secret>
以及任何分支或本地克隆版本都包含该秘密。
bash
undefined

Search 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
.env
files:
  • Docker images
    docker history <image>
    shows every
    ENV
    line;
    --build-arg SECRET=...
    ends up in layers
  • CI environment — secrets logged by
    set -x
    ,
    console.log(process.env)
    , error stack traces, debug output
  • Frontend bundles
    NEXT_PUBLIC_*
    /
    VITE_*
    /
    REACT_APP_*
    env vars are shipped to the browser; grep the bundled JS
  • Crash reports — Sentry / Datadog / Bugsnag capturing
    process.env
    snapshots
  • Logs — application logs shipped to a SIEM that has weaker access controls than the app
  • Backups
    pg_dump
    of a table that includes user-stored API keys
  • Public S3 / blob storage
    .env
    accidentally uploaded
  • 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_*
    /
    REACT_APP_*
    环境变量会被打包到浏览器端;可通过grep扫描打包后的JS文件
  • 崩溃报告 — Sentry / Datadog / Bugsnag会捕获
    process.env
    快照
  • 日志 — 应用日志被发送到访问控制弱于应用本身的SIEM系统
  • 备份
    pg_dump
    导出的表中包含用户存储的API密钥
  • 公共S3 / 对象存储
    .env
    文件被意外上传
  • 文档 — README.md示例中使用真实密钥而非占位符
  • Slack / Notion / Linear — 为测试粘贴的密钥从未轮换
  • 浏览器localStorage / cookies — 被共享截图或会话录屏捕获

Triaging a found secret

泄露秘密的分类处理

When you find a leaked secret:
  1. Verify it's live — use the provider's verification (
    aws sts get-caller-identity
    ,
    stripe balance retrieve
    ,
    curl -H "Authorization: Bearer $TOKEN" ...
    ) — don't assume; some leaked keys are already revoked or were sandbox-only
  2. Determine exposure window — first commit it appeared in, when the repo went public, when CI logs were retained from
  3. Determine blast radius — what does this key access? What can be done with it? IAM permissions, Stripe live vs test, GitHub
    repo
    vs
    admin:org
  4. Rotate immediately — generate a new key, deploy it, then revoke the old one (revoke-first breaks prod)
  5. Audit for use — provider audit logs (CloudTrail, GitHub audit log, Stripe events) for any activity from the leaked credential
  6. Then clean — remove from current code, then optionally history-rewrite (low priority once rotated)
  7. Document — incident report, even if rotation was clean; recurrence patterns surface trends
发现泄露的秘密后:
  1. 验证是否有效 — 使用服务商的验证方法(
    aws sts get-caller-identity
    stripe balance retrieve
    curl -H "Authorization: Bearer $TOKEN" ...
    )——不要假设;有些泄露的密钥已被撤销或仅用于沙箱环境
  2. 确定暴露窗口期 — 首次出现的提交记录、仓库公开时间、CI日志保留时间
  3. 确定影响范围 — 该密钥可访问哪些资源?能执行哪些操作?IAM权限、Stripe生产/测试环境、GitHub
    repo
    /
    admin:org
    权限
  4. 立即轮换 — 生成新密钥并部署,然后撤销旧密钥(先撤销会导致生产环境故障)
  5. 审计使用情况 — 服务商审计日志(CloudTrail、GitHub审计日志、Stripe事件)中该泄露凭证的所有活动
  6. 清理 — 从当前代码中删除,然后可选进行历史重写(轮换完成后优先级较低)
  7. 记录 — 即使轮换顺利也要撰写事件报告;重复模式会暴露趋势

Part 2 — Audit secrets-management posture

第二部分——审计秘密管理态势

The hierarchy of secret storage (worst → best)

秘密存储层级(最差→最优)

TierPatternWhen acceptable
Hardcoded in sourceNever
Hardcoded in image / build artifactNever
Plaintext in shared docs / SlackNever
⚠️
.env
file in repo (even with .gitignore — easy to leak via push, backup, archive)
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 timeStandard for most apps
🟢Workload identity federation (no stored secret at all)Best where supported
层级模式可接受场景
硬编码到源代码中绝不允许
硬编码到镜像/构建产物中绝不允许
明文存储在共享文档/Slack中绝不允许
⚠️仓库中的
.env
文件(即使已加入.gitignore——仍易通过推送、备份、归档泄露)
仅用于初始化;审计中会被标记
⚠️仅使用环境变量临时开发环境可接受;生产环境安全性弱(可在/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
    .env
    committed
    .gitignore
    covers
    .env*
    (with care for
    .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
  • .env.local
    shipped to staging
    — environment-specific dev secrets cross the boundary
  • CI secrets accessible from PRs from forks — GitHub's default behavior was previously dangerous; verify
    pull_request_target
    and secret accessibility
  • Build args used for secrets
    --build-arg AWS_SECRET=...
    ends up in image history (use
    --secret
    /BuildKit instead)
  • Logging frameworks dump
    process.env
    on unhandled exception — Sentry / Datadog / Bugsnag scrub config required
  • 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
  • 轮换从未测试 — 已配置密钥存储,但从未实际轮换;首次尝试会导致生产环境故障
  • .env.local
    被部署到staging环境
    — 环境专属的开发秘密越界泄露
  • 来自分支PR的CI秘密可访问 — GitHub默认行为曾存在风险;需验证
    pull_request_target
    和秘密访问权限
  • 使用构建参数传递秘密
    --build-arg AWS_SECRET=...
    会被存入镜像历史(改用
    --secret
    /BuildKit)
  • 日志框架在未处理异常时输出
    process.env
    — 需要配置Sentry/Datadog/Bugsnag进行信息清理
  • 秘密以明文Secret形式存储在K8s中且未启用etcd加密——base64是编码而非加密(参见
    container-audit
  • OAuth客户端密钥存储在移动应用中 — 公共客户端无法保存秘密;应使用PKCE方案

Output Format

输出格式

markdown
undefined
markdown
undefined

Secrets Audit Report

秘密审计报告

Scope: [repos / environments / managers covered]

范围:[覆盖的仓库/环境/管理器]

Date: [date]

日期:[日期]

Live leaked secrets found

发现的有效泄露秘密

ProviderLocationFirst seen (commit / date)Verified live?Rotation status
服务商位置首次出现时间(提交/日期)是否验证有效?轮换状态

Secrets-management posture

秘密管理态势

CategoryStatusNotes
类别状态备注

Recommendations

建议

PriorityItemOwnerDeadline

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
    ,
    trufflehog
    ,
    detect-secrets
    documentation
  • 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最佳实践
  • 《十二因素应用》——配置原则