insecure-defaults
insecure-defaults Skill 深度评测:硬编码密钥与失败开放检测
评分明细
适用场景
insecure-defaults 快速入门
让 AI 在写代码时主动拦截”硬编码密钥”和”失败开放”,把安全审计雷达装进 Agent。
这是什么?解决什么问题?
insecure-defaults 是 Trail of Bits 团队出品的”代码安全 Skill”之一,聚焦在”默认配置不安全”这个被普遍低估的风险面。它解决两类高频漏洞:第一,硬编码密钥(Hardcoded Secrets),即 API Key、Token、数据库密码、AWS AKID/SK、私钥等直接写死在源码里;第二,失败开放(Fail-Open),即在权限校验、加密、配置加载等关键路径上,遇到异常时”放行”而不是”拒绝”。
为什么这两类问题特别值得一个独立 Skill?因为它们有个共同特点:代码”看起来能跑”,上线后才爆。硬编码密钥一旦代码进了 Git 历史,即使后来删除,被爬虫或离职员工拿走也只能事后救火;失败开放更隐蔽——单元测试很难发现,只有”配置加载失败 + 业务逻辑刚好触发”这两个条件同时满足时才会暴露,而此时往往已经被攻击者利用。
这个 Skill 的核心思路是:让 AI 在写代码和审查代码时,把”硬编码密钥 + 失败开放”作为独立的检查项,触发特定模式就标记并要求人工复核。具体来说,它内置一系列正则/模式规则(比如匹配 AKIA[0-9A-Z]{16} 这种 AWS AccessKey 模式、-----BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY----- 这种私钥头、if err == nil { allow } 这种可疑的”err 优先”判断),在生成或 review 代码时主动提醒。
Trail of Bits 是一家以安全审计闻名的美国安全公司,出过不少业内经典的安全工具(比如 Slither、Etheno)。他们的 skills 仓库 3k+ Stars,CC-BY-SA-4.0 协议,在 14 个 Skill 中,本 Skill 属于”覆盖面广、单点浅”的那一类——它不专门做加密侧信道(那是 constant-time-analysis 的活),也不专门做静态分析三件套(那是 static-analysis 的活),而是把”最容易在 AI 生成代码里被默认带出 bug”的那一类先堵住。
准备工作
- Claude Code 或兼容 Agent:本 Skill 以 Agent Skill 形式分发,需要宿主支持 Skill 加载。
- Git:用于扫历史 commit,看是否已有 hardcoded secrets 流入。
- 一个测试用项目:建议用一个干净的 Node.js / Python / Go 小项目,不要直接在生产仓库上跑(虽然 Skill 是”标记”不是”修改”,但谨慎起见)。
- 熟悉基础的 secrets 形态:知道什么是 AKID、什么是 JWT、什么是 PEM 私钥,这样 AI 标记的时候你能快速判断真假阳性。
- 可选:detection-rules 联动:Trail of Bits 的
static-analysisSkill 提供 CodeQL / Semgrep / SARIF 三件套,可与本 Skill 联用,做”AI 标记 + 工具二次确认”。
3 步快速上手
第 1 步:安装 Skill
克隆 Trail of Bits skills 仓库,定位到 insecure-defaults/ 目录。
git clone https://github.com/trailofbits/skills.git ~/trailofbits-skills
mkdir -p ~/.claude/skills
ln -s ~/trailofbits-skills/insecure-defaults ~/.claude/skills/insecure-defaults
第 2 步:验证安装
启动 Claude Code,新开对话,问:
列出已加载的 Skill,看看有没有 insecure-defaults。如果有,请简要说明它会拦截哪几类模式。
Agent 应能回读 SKILL.md,告诉你它重点检查的几种模式(硬编码密钥、失败开放、可疑的默认配置)。你也可以直接在 shell 里读 SKILL.md,确认 frontmatter 完整、内容没损坏。
第 3 步:用 Skill 跑第一个任务
进入测试项目,启动 Claude Code,输入:
用 insecure-defaults 流程,审查当前仓库的 src/ 目录,把任何疑似硬编码密钥、失败开放的代码位置列出来,每条给出:文件:行号、可疑模式、为什么是 false positive 或需要修复。
Agent 会按 SKILL.md 中的检查清单扫一遍,典型输出形如:
src/config.ts:42 - "AKIA[0-9A-Z]{16}" 模式匹配
→ 疑似 AWS AccessKey 硬编码。
→ 建议:移至环境变量或 AWS Secrets Manager,使用 IAM Role 替代。
src/auth/middleware.ts:18 - 失败开放
模式:if (verifyToken(token) === null) { return next(); } // 异常时放行
→ Token 校验失败不应放行,应返回 401。
→ 建议:改为 return res.status(401).send("Unauthorized");
常见踩坑
- 把”开发用的占位密钥”也当真阳性告警:
AKIAIOSFODNN7EXAMPLE这种 AWS 官方文档里的示例密钥也会命中正则。Skill 通常会标注”是否为示例/明显占位”,但人工复核不能省。 - 未扫历史 commit:硬编码密钥一旦 commit 一次,即使之后删除,Git 历史里仍能
git log -p翻出来。Skill 标记的是当前工作区,需要再跑一次gitleaks/trufflehog扫历史。 - 失败开放误报:有些代码确实是”先放行再后置校验”,业务上合理(比如公开路由),需要人工判断,不要全盘接受 AI 的”必须拒绝”建议。
- base64 编码的密钥绕开正则:
echo -n "AKIA..." | base64之后正则不命中。需要 AI 配合做 base64 解码后再判断,本 Skill 覆盖这一场景。 - 环境变量文件被提交:
.env文件本身不进 Git,但.env.example经常被误填真实值,要把.env*列入.gitignore并预提交钩子扫描。 - 只查”我写的代码”不查依赖:
node_modules里偶有供应链投毒,Skill 默认不扫,需要static-analysisSkill 联动处理。
初级用法
- 新代码 review:每写完一个 PR,先让 AI 跑一次 insecure-defaults 审查,标记出来的位置人工逐条判断,典型能拦下 70% 的硬编码。
- 存量仓库体检:对老仓库第一次启用,跑一次全仓扫描,根据严重性(关键密钥/失败开放/弱默认)分批修复。
- 与 pre-commit 钩子联用:Skill 给出”哪些模式必须拒绝”,把这些模式抽成 pre-commit 钩子(参考
gitleaks配置),代码进入仓库前自动阻断。
高级玩法
- 多 Agent 二次确认:把 Skill 输出交给另一个 Agent(比如
static-analysis的 Semgrep 子代理)做”工具级确认”,把 AI 标记 + Semgrep 规则双绿才算通过。 - 自定义模式:在
~/.claude/skills/insecure-defaults/下加一个custom-patterns.md,补充公司内部特有的密钥形态(如内部 API 前缀sk_live_xxx)和合规要求。 - PR 自动评论:把 Skill 接入 GitHub Actions / GitLab CI,在 PR 上自动开 review 评论,标记出每行风险,集成进现有工作流。
- 联动 OAuth 扫描器:对 OAuth client_secret、JWT signing key 这类,可在 Skill 提示后用
oauth-fuzzer之类的工具做动态验证。
小技巧
- 看到 AI 标记的”硬编码密钥”时,先 revoke 再改代码——发现的那一刻,这个密钥就应该被认为已泄漏。
- 失败开放的判定不要只看一行,要看整个函数的异常分支。有时
if err == nil是合理的(显式忽略特定错误),需要上下文判断。 - 对示例密钥(如
AKIAIOSFODNN7EXAMPLE)在 Skill 输出里加一个 “exempt patterns” 字段,可减少噪音,提升真实阳性命中率。 - 把本 Skill 配合
.gitignore模板分发,新建项目时就预防胜于补救。 - CI 阶段跑一遍 Skill +
gitleaks+trufflehog,三件套”全绿”才允许合并,这是性价比最高的组合。
参考链接
- Trail of Bits skills 仓库:https://github.com/trailofbits/skills
- insecure-defaults 源码目录:https://github.com/trailofbits/skills/tree/main/insecure-defaults
- gitleaks 工具(历史密钥扫描):https://github.com/gitleaks/gitleaks
- OWASP Top 10(A02:2021 Cryptographic Failures):https://owasp.org/Top10/A02_2021-Cryptographic_Failures/
- CWE-798: Use of Hard-coded Credentials:https://cwe.mitre.org/data/definitions/798.html
- CWE-636: Not Failing Securely (‘Failing Open’):https://cwe.mitre.org/data/definitions/636.html
本文基于官方文档和公开资料整理,AI辅助生成,MagicNetWorld 尚未完成独立实测。如有错误或过时信息,请通过 contact@magicnetworld.com 反馈。
insecure-defaults Skill 多维度简评
综合评分:8.4 / 10 ⭐⭐⭐⭐ 类别:安全工具 / 配置审计 仓库:trailofbits/skills 维护者:Trail of Bits
一、核心定位与价值
两个最常见的安全失误:
- 硬编码密钥 —— 提交到 Git 后被爬取
- Fail-open 默认配置 —— 错误时返回成功
insecure-defaults Skill 专门检测这两类问题,比传统 SAST 工具误报率低(因为 AI 理解上下文)。
二、核心能力
2.1 硬编码密钥检测
自动识别的密钥模式
# AWS Access Key
AKIA[0-9A-Z]{16}
# AWS Secret Key
[A-Za-z0-9/+=]{40}
# OpenAI API Key
sk-[a-zA-Z0-9]{32,}
# Anthropic API Key
sk-ant-[a-zA-Z0-9-]{32,}
# GitHub Token
ghp_[a-zA-Z0-9]{36}
gho_[a-zA-Z0-9]{36}
ghu_[a-zA-Z0-9]{36}
ghs_[a-zA-Z0-9]{36}
ghr_[a-zA-Z0-9]{36}
# GitLab Token
glpat-[a-zA-Z0-9_-]{20,}
# Slack Token
xox[baprs]-[0-9a-zA-Z]{10,}
# Google API Key
AIza[0-9A-Za-z_-]{35}
# Stripe Live Key
sk_live_[0-9a-zA-Z]{24,}
# Stripe Test Key
sk_test_[0-9a-zA-Z]{24,}
# JWT Secret (弱)
secret.*=.*['"][a-zA-Z0-9]{16,}['"]
# Database Connection String
postgres://[^:]+:[^@]+@
mysql://[^:]+:[^@]+@
mongodb://[^:]+:[^@]+@
# Generic High-Entropy String
[20+ 字符的高熵字符串]
文件类型覆盖
- 源代码:
.py .js .ts .java .go .rs .rb .php .cs .cpp .c .h - 配置文件:
.env .yml .yaml .json .toml .ini .conf - 文档:
.md .txt(注释中的密钥) - 密钥文件:
.pem .key .p12 .pfx
2.2 Fail-open 检测
# ❌ Fail-open 反模式
def authenticate(request):
try:
verify_token(request.headers['Authorization'])
except Exception:
return AnonymousUser() # 错误时返回成功!
# ✅ Fail-safe 正确做法
def authenticate(request):
try:
user = verify_token(request.headers['Authorization'])
except Exception:
return None # 错误时返回失败
return user
常见 fail-open 模式
- try/except 直接 return 默认值
- if error: pass
- .catch(() => 默认值)
- 验证函数返回 None 而非 False
- 认证失败但仍允许操作
2.3 危险默认值检测
# ❌ 危险默认值
database:
host: 0.0.0.0 # 监听所有接口
port: 5432
ssl: false # 明文传输
password: admin # 默认密码
admin:
username: admin
password: admin # 弱密码
enabled: true
cors:
origin: '*' # 任意来源
debug: true # 生产环境开启
session:
secure: false # 非 HTTPS
httponly: false # XSS 风险
samesite: 'None' # CSRF 风险
三、6 大实战场景
场景 1:硬编码密钥扫描
用 insecure-defaults 扫描 src/ 目录,找出所有硬编码的密钥。
特别关注 .env、config、json 配置文件。
场景 2:Fail-open 检测
扫描所有异常处理:
- try/except 直接返回默认值
- auth 中出错就放行
- 验证失败但不拒绝
场景 3:危险默认值
检查所有配置文件的默认值:
- CORS 是否过于宽松
- Cookie 是否 httponly false
- DEBUG 是否在生产开启
- 数据库密码是否默认
场景 4:历史代码审计
扫描 git log 中的所有 commit,找出曾经提交过的密钥(即使后续删除)。
场景 5:第三方代码引入审计
引入的开源组件是否有危险的默认配置?
- 是否有内置 admin/admin 账号?
- 默认数据库名/密码?
- 默认 API key?
场景 6:CI/CD 集成
在 PR 触发时自动跑 insecure-defaults:
- 阻止硬编码密钥合并
- 阻止 fail-open 模式合并
四、实战提示词模板
4.1 标准扫描
用 insecure-defaults 扫描 [目录路径]:
输出:
- 所有硬编码密钥(位置 + 密钥类型)
- 所有 fail-open 模式
- 所有危险默认值
- 风险评级 + 修复建议
4.2 紧急响应
我们公司 [某个仓库] 的密钥 [GitHub Token] 泄露了。
1. 立即找出仓库中所有使用该 Token 的位置
2. 评估影响范围
3. 给出轮换密钥的步骤
4. 列出其他可能的密钥泄漏
4.3 配置文件审计
用 insecure-defaults 审查我们项目的所有配置文件:
- config/default.yml
- .env.example
- src/config/database.ts
- ...
关注默认值是否安全
五、实战输出示例
## insecure-defaults 报告
### 🔴 Critical(立即处理)
#### 1. 硬编码 OpenAI API Key
- **文件**: src/api/gpt.ts:12
- **代码**:
```typescript
const API_KEY = "sk-1234567890abcdef..."
- 风险: 任何人 clone 代码就能拿到你的 OpenAI 配额
- 修复:
const API_KEY = process.env.OPENAI_API_KEY if (!API_KEY) throw new Error('Missing API key')
2. 认证 Fail-open
- 文件: src/middleware/auth.ts:23
- 代码:
try { return verifyToken(req.headers.authorization) } catch (e) { return { id: 1, role: 'guest' } # ❌ 错误时返回 guest! } - 风险: 任何 token 验证错误都能通过认证
- 修复: 返回 null 或抛 401
🟡 High
3. 数据库默认密码
- 文件: docker-compose.yml:8
- 代码:
POSTGRES_PASSWORD: postgres - 修复: 用 .env 注入强密码
4. CORS 配置过宽
- 文件: src/server.ts:34
- 代码:
cors({ origin: '*', credentials: true }) - 风险: 任意网站可发起带凭证请求
- 修复: 白名单指定来源
🟢 Medium / Low
…(其他发现)
---
## 六、修复模板
### 6.1 密钥从硬编码到环境变量
```typescript
// ❌ Before
const API_KEY = "sk-1234567890abcdef"
// ✅ After
const API_KEY = process.env.OPENAI_API_KEY
if (!API_KEY) throw new Error('Missing OPENAI_API_KEY')
6.2 Fail-open 改为 Fail-safe
// ❌ Before
async function getUser(id: string) {
try {
return await db.users.findUnique({ where: { id } })
} catch (e) {
return null // Fail-open
}
}
// ✅ After
async function getUser(id: string) {
try {
return await db.users.findUnique({ where: { id } })
} catch (e) {
logger.error('DB query failed', { error: e, userId: id })
throw new DatabaseError('查询失败')
}
}
6.3 密钥管理升级路径
阶段 1: 紧急轮换已泄露密钥
阶段 2: 移除所有硬编码,改用环境变量
阶段 3: 迁移到 Vault / AWS Secrets Manager
阶段 4: 启用自动轮换
阶段 5: 集成动态凭证(STS / Workload Identity)
七、与 SAST 工具对比
| 维度 | insecure-defaults | 传统 SAST |
|---|---|---|
| 误报率 | 低(AI 上下文理解) | 高(规则匹配) |
| 覆盖密钥类型 | 30+ 种常见密钥 | 通常只覆盖几种 |
| Fail-open 检测 | 智能理解 | 难检测(需业务语义) |
| 修复建议 | 上下文相关 | 通用建议 |
| 执行速度 | 中等(AI 调用) | 快(规则扫描) |
最佳实践:
- CI 用传统 SAST(自动化 + 快速)
- 关键审计用 insecure-defaults(深度)
八、安装
# Claude Code
/plugin marketplace add trailofbits/skills
/plugin install insecure-defaults@trailofbits
# 通用
npx skills add trailofbits/skills --skill insecure-defaults
九、5 条实战技巧
- CI 集成:每次 commit 扫描
- 关注 git 历史:旧 commit 也可能含密钥
- 环境变量优先:从不硬编码
- 轮换密钥:发现立即轮换
- 回滚友好:硬编码密钥即使删除也会留在历史
十、5 条反合理化
| 借口 | 反驳 |
|---|---|
| ”我们的密钥不重要” | 任何密钥都可能成为攻击起点 |
| ”.env 文件不会提交” | 但可能通过 PR / backup 泄露 |
| ”代码扫描太慢了” | 比密钥泄露的代价小得多 |
| ”Fail-open 不影响业务” | 但被攻击时是灾难性 |
| ”默认密码我改了” | 大部分攻击面你没扫到 |
十一、与其他安全 Skill 配合
| Skill | 何时切换 |
|---|---|
| insecure-defaults | 配置 + 密钥审查 |
| variant-analysis | CVE 模式排查 |
| differential-review | PR 安全审查 |
| supply-chain-risk-auditor | 依赖安全 |
十二、Q&A
Q: 必须订阅 Claude Code 吗? A: 效果最佳用 Opus 4.6+。
Q: 误报率高吗? A: 比 SAST 低,因为 AI 理解上下文。
Q: 能修复吗? A: 不会自动修改,会给出建议。
Q: 私有项目能用吗? A: 能,但需注意数据敏感度。
Q: 中文支持? A: Skill 是英文,处理中文代码无障碍。
Q: 怎么处理发现的密钥? A: 立即轮换 + 从 git 历史清除 + 加 CI 扫描。
十三、真实事件统计
GitHub Secret Scanning 公开数据:
- 2023 年扫描出 180 万+ 硬编码密钥
- 包括 AWS、GitHub、Google、Slack、Stripe 等
- 平均每天发现 5,000+ 个新密钥
这些密钥平均寿命只有 4 天——大多数在 24 小时内就被爬取。
十四、Insecure Defaults 完整分类体系(OWASP Top 10 + CWE)
14.1 OWASP Top 10 2021 对照
| OWASP 类别 | insecure-defaults 检测范围 |
|---|---|
| A01: Broken Access Control | 默认 admin/admin 账号、缺少权限校验 |
| A02: Cryptographic Failures | MD5/SHA1 默认、密钥硬编码、HTTP 而非 HTTPS |
| A03: Injection | 模板默认未转义、SQL 字符串拼接 |
| A04: Insecure Design | 默认 fail-open、业务逻辑缺陷 |
| A05: Security Misconfiguration | 调试模式开启、详细错误信息、默认凭证 |
| A06: Vulnerable Components | 默认装不安全版本 |
| A07: Authentication Failures | 默认弱密码策略、缺少 MFA |
| A08: Software & Data Integrity | 默认不验证签名、自动更新源不安全 |
| A09: Security Logging Failures | 默认日志级别过低、不记录安全事件 |
| A10: SSRF | 默认允许内网请求 |
14.2 CWE 视角分类
- CWE-1188:Insecure Default Initialization of Resource
- CWE-1392:Use of Default Credentials
- CWE-250:Execution with Unnecessary Privileges
- CWE-276:Incorrect Default Permissions
- CWE-295:Improper Certificate Validation
- CWE-311:Missing Encryption of Sensitive Data
- CWE-321:Use of Hard-coded Cryptographic Key
- CWE-489:Active Debug Code
- CWE-798:Use of Hard-coded Credentials
- CWE-1188:Insecure Default
14.3 检测技术分类
1. 字符串匹配类
- 正则匹配密钥格式(
sk-、AKIA、-----BEGIN) - 匹配常见默认密码(
admin、password、root) - 匹配不安全算法名(
md5、sha1、des)
2. 模式识别类
- Fail-open 模式:try-catch 后返回默认值
- 默认配置:函数参数默认值不安全
- 信任源:JWT_SECRET 默认值、API_URL 默认内网
3. 上下文分析类
- 凭证是否在源码中(而非环境变量)
- 错误处理是否泄漏信息
- 加密是否真的被使用(vs 留空)
十五、14 类典型 Insecure Default 详细案例
15.1 默认弱密码
// ❌ Insecure
const adminPassword = "admin123"
const mysqlRootPassword = "root"
// ✅ Secure
const adminPassword = process.env.ADMIN_PASSWORD
if (!adminPassword || adminPassword.length < 16) {
throw new Error("Admin password must be set and ≥16 chars")
}
15.2 硬编码 API 密钥
# ❌ Insecure
OPENAI_API_KEY = "sk-proj-xxxxxxxxxxxx"
STRIPE_SECRET = "sk_live_xxxxxxxxxxxx"
# ✅ Secure
import os
OPENAI_API_KEY = os.environ["OPENAI_API_KEY"]
assert OPENAI_API_KEY.startswith("sk-")
15.3 默认开启调试模式
# ❌ Insecure
app = Flask(__name__)
app.config["DEBUG"] = True # 生产环境暴露栈跟踪
app.config["TESTING"] = True # 禁用 CSRF
# ✅ Secure
app = Flask(__name__)
app.config["DEBUG"] = os.getenv("FLASK_DEBUG", "false").lower() == "true"
app.config["TESTING"] = False
15.4 默认 HTTP(非 HTTPS)
# ❌ Insecure
server {
listen 80;
server_name api.example.com;
}
# ✅ Secure
server {
listen 443 ssl http2;
ssl_certificate /etc/ssl/certs/api.example.com.pem;
ssl_certificate_key /etc/ssl/private/api.example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
add_header Strict-Transport-Security "max-age=31536000" always;
}
server {
listen 80;
server_name api.example.com;
return 301 https://$server_name$request_uri;
}
15.5 默认 allow_origins: ”*” + credentials: true
# ❌ Insecure
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
)
# ✅ Secure
app.add_middleware(
CORSMiddleware,
allow_origins=["https://app.example.com"], # 显式白名单
allow_credentials=True,
allow_methods=["GET", "POST"],
allow_headers=["Authorization", "Content-Type"],
)
15.6 数据库连接默认无加密
# ❌ Insecure
engine = create_engine("postgresql://user:pass@host/db")
# ✅ Secure
engine = create_engine(
"postgresql://user:pass@host/db?sslmode=require&sslcert=client.crt"
)
15.7 JWT 默认不验证签名
// ❌ Insecure
const decoded = jwt.decode(token) // 只 decode,不 verify
// ✅ Secure
const decoded = jwt.verify(token, process.env.JWT_SECRET, {
algorithms: ["HS256"],
audience: "api.example.com",
issuer: "auth.example.com",
})
15.8 Session cookie 默认不安全
# ❌ Insecure
app.config["SESSION_COOKIE_SECURE"] = False
app.config["SESSION_COOKIE_HTTPONLY"] = False
app.config["SESSION_COOKIE_SAMESITE"] = None
# ✅ Secure
app.config["SESSION_COOKIE_SECURE"] = True # 仅 HTTPS
app.config["SESSION_COOKIE_HTTPONLY"] = True # 阻止 JS 访问
app.config["SESSION_COOKIE_SAMESITE"] = "Lax" # CSRF 防护
15.9 默认开启目录列表
# ❌ Insecure
server {
autoindex on; # 暴露所有文件
}
# ✅ Secure
server {
autoindex off;
}
15.10 默认 allow_methods: ”*“
# ❌ Insecure
cors = CORS(app, allow_methods=["*"])
# ✅ Secure
cors = CORS(app, allow_methods=["GET", "POST", "PUT", "DELETE"])
15.11 默认 cookie 无 httpOnly
// ❌ Insecure
res.cookie("sessionId", sessionId)
// ✅ Secure
res.cookie("sessionId", sessionId, {
httpOnly: true,
secure: true,
sameSite: "strict",
maxAge: 3600000,
})
15.12 默认开启 CORS 反射
// ❌ Insecure
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", req.headers.origin)
next()
})
// ✅ Secure
const allowedOrigins = ["https://app.example.com"]
app.use((req, res, next) => {
if (allowedOrigins.includes(req.headers.origin)) {
res.setHeader("Access-Control-Allow-Origin", req.headers.origin)
}
next()
})
15.13 默认 Redis 无密码
# ❌ Insecure
docker run -d redis:7-alpine
# ✅ Secure
docker run -d redis:7-alpine \
--requirepass "${REDIS_PASSWORD}" \
--bind 127.0.0.1 \
--protected-mode yes
15.14 默认 SSH 允许 root 登录
# /etc/ssh/sshd_config
# ❌ Insecure
PermitRootLogin yes
PasswordAuthentication yes
Port 22
# ✅ Secure
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
Port 2222
AllowUsers deploy
十六、Secret Rotation(密钥轮换)SOP
16.1 密钥生命周期
生成(生成器)→ 存储(Vault)→ 分发(环境变量)→ 使用(短时)→ 轮换(定期)→ 销毁(删除)
│ │
└──────────── 任何环节泄漏,立即强制轮换 ──────────────────────────────────┘
16.2 轮换周期建议
| 密钥类型 | 推荐周期 | 自动轮换 |
|---|---|---|
| AWS Access Key | 90 天 | ✅ STS |
| GitHub PAT | 90 天 | ✅ |
| 数据库密码 | 60 天 | ✅ Vault |
| API 第三方密钥 | 180 天 | ⚠️ 手动 |
| JWT Signing Key | 30 天 | ✅ |
| TLS 证书 | 90 天 | ✅ Let’s Encrypt |
| SSH Key | 365 天 | ⚠️ 手动 |
16.3 自动轮换实现
# HashiCorp Vault
import hvac
client = hvac.Client(url="https://vault.example.com", token=os.environ["VAULT_TOKEN"])
# 读取密钥
db_password = client.secrets.kv.v2.read_secret_version(
path="database/prod/password",
mount_point="secret",
)
# 触发轮换
client.secrets.kv.v2.update_secret(
path="database/prod/password",
secret={"password": generate_strong_password(32)},
)
16.4 紧急轮换流程
发现密钥泄漏
↓
T+0: 在 Vault 标记为"compromised"
↓
T+5min: 生成新密钥
↓
T+10min: 滚动更新所有使用方(K8s ConfigMap reload)
↓
T+15min: 旧密钥 revoke
↓
T+30min: 验证所有服务正常
↓
T+1h: 复盘报告
十七、Pre-commit Hook 集成
17.1 用 gitleaks 防密钥泄漏
# 安装 gitleaks
brew install gitleaks
# 配置 .gitleaks.toml
[[rules]]
id = "openai-key"
description = "OpenAI API Key"
regex = '''sk-[a-zA-Z0-9]{20,}'''
tags = ["secret", "openai"]
[[rules]]
id = "aws-access-key"
description = "AWS Access Key"
regex = '''AKIA[0-9A-Z]{16}'''
tags = ["secret", "aws"]
# Git pre-commit hook
cat > .git/hooks/pre-commit <<'EOF'
#!/bin/bash
gitleaks protect --staged --config .gitleaks.toml --verbose
EOF
chmod +x .git/hooks/pre-commit
17.2 用 Skill 配合 gitleaks
用 insecure-defaults Skill 配合 gitleaks:
1. 先跑 gitleaks(字符串匹配密钥)
2. 再用 Skill 分析上下文(区分真实密钥 vs 测试数据)
3. 输出合并报告
17.3 GitHub Actions 集成
name: Secret Scan
on: [push, pull_request]
jobs:
gitleaks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# 增量 AI 分析
- name: AI Context Analysis
if: github.event_name == 'pull_request'
run: |
npx skills add trailofbits/skills --skill insecure-defaults -y
# 调用 Claude 分析 diff
十八、合规框架对照
18.1 不同行业对 insecure defaults 的要求
| 行业 | 标准 | 关键要求 |
|---|---|---|
| 金融(PCI-DSS) | Requirement 2, 6, 8 | 禁用默认密码、强加密、密钥轮换 |
| 医疗(HIPAA) | §164.312(a)(2)(iv) | 加密、访问控制、审计日志 |
| 政府(FedRAMP) | AC-2, IA-5 | 禁用默认凭证、MFA、密码复杂度 |
| 欧盟(GDPR) | Article 32 | 假名化、加密、访问控制 |
| 中国(等保 2.0) | 8.1.4.2 | 身份鉴别、访问控制、安全审计 |
| 云(CSA STAR) | CCM v4 | 加密、密钥管理、配置管理 |
18.2 检查清单模板
# 项目安全配置审计清单
## 默认凭证
- [ ] 无任何硬编码密钥
- [ ] 首次部署强制改密
- [ ] 数据库密码 ≥ 16 字符
- [ ] JWT secret ≥ 32 字节
## 传输加密
- [ ] 全站 HTTPS,无混合内容
- [ ] HSTS 启用(max-age ≥ 1 年)
- [ ] TLS 1.2+ only
- [ ] 强加密套件
## 存储加密
- [ ] 敏感数据静态加密
- [ ] 加密密钥与数据分离
- [ ] 密钥定期轮换
## 会话管理
- [ ] cookie httpOnly + secure
- [ ] cookie SameSite=Strict/Lax
- [ ] session 过期时间合理
- [ ] 登出后 session 立即失效
## 错误处理
- [ ] 生产环境不暴露栈跟踪
- [ ] 错误日志不包含敏感信息
- [ ] 调试模式已关闭
## 权限控制
- [ ] 最小权限原则
- [ ] 服务账号不共享
- [ ] 定期权限审计
十九、Insecure Default 修复模式库
19.1 密码策略配置
# config/password-policy.yaml
min_length: 14
require_uppercase: true
require_lowercase: true
require_digits: true
require_symbols: true
max_age_days: 90
history_count: 12 # 不能与最近 12 个密码相同
lockout_threshold: 5
lockout_duration_minutes: 30
19.2 安全响应头
# middleware/security_headers.py
SECURITY_HEADERS = {
"X-Content-Type-Options": "nosniff",
"X-Frame-Options": "DENY",
"X-XSS-Protection": "1; mode=block",
"Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload",
"Content-Security-Policy": "default-src 'self'; script-src 'self' 'nonce-{nonce}'",
"Referrer-Policy": "strict-origin-when-cross-origin",
"Permissions-Policy": "geolocation=(), microphone=(), camera=()",
}
19.3 默认安全的应用初始化
# app/factory.py
def create_app(config=None):
app = Flask(__name__)
# 强制使用环境变量配置
app.config["SECRET_KEY"] = os.environ["FLASK_SECRET_KEY"]
app.config["JWT_SECRET_KEY"] = os.environ["JWT_SECRET_KEY"]
# 强制 HTTPS
if not app.debug:
from flask_talisman import Talisman
Talisman(app, force_https=True)
# 强制安全 cookie
app.config.update(
SESSION_COOKIE_SECURE=True,
SESSION_COOKIE_HTTPONLY=True,
SESSION_COOKIE_SAMESITE="Lax",
)
# 关闭调试信息泄漏
app.config["PROPAGATE_EXCEPTIONS"] = False
return app
19.4 默认安全的 Dockerfile
# 使用非 root 用户
FROM node:20-alpine
RUN addgroup -g 1001 nodejs && adduser -S -u 1001 -G nodejs nodejs
USER nodejs
# 不暴露源码
WORKDIR /app
COPY --chown=nodejs:nodejs package*.json ./
RUN npm ci --only=production
COPY --chown=nodejs:nodejs . .
# 暴露非特权端口
EXPOSE 3000
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
CMD ["node", "server.js"]
二十、Prompt 模板库
模板 1:通用项目审计
[背景] 这是我们的 Node.js + Express 项目,刚发布 v1.0。
[任务] 用 insecure-defaults 全面审计默认配置:
- 凭证:硬编码密钥、默认密码
- 加密:HTTP、明文存储
- 会话:cookie 安全标志
- 错误处理:调试模式、错误泄漏
- 权限:CORS、过宽 allow
[输出] 按 Critical/High/Medium/Low 分级报告。
模板 2:金融行业合规审计
[背景] 我们是支付公司,受 PCI-DSS 约束。
[任务] 审计以下项并对照 PCI-DSS v4.0:
- 禁用默认凭证(Req 2.2)
- 强加密传输(Req 4.2)
- 密钥管理(Req 3.7)
- 访问日志(Req 10.2)
[输出] 监管提交级报告。
模板 3:Kubernetes 部署审计
[背景] 我们用 K8s 部署 30+ 微服务。
[任务] 审计所有 Deployment:
- 是否使用 root
- 是否挂载 service account token
- 是否使用 :latest 镜像
- 是否配置 securityContext
- 是否启用 NetworkPolicy
[输出] K8s YAML 修复建议。
模板 4:开源项目发布前审计
[背景] 我们要把内部工具开源。
[任务] 发布前必须审计:
- 移除所有硬编码密钥
- 添加 .env.example
- 启用 secret scanning
- 配置 dependabot
[输出] 发布前 Checklist。
模板 5:应急响应(密钥泄漏)
[背景] 我们的 GitHub 仓库意外提交了 AWS Access Key。
[任务] 立即响应:
1. 评估泄漏范围(commit history、fork、archive)
2. 生成新 Key 并轮换
3. 审查 CloudTrail 是否有异常使用
4. 清除 git 历史
5. 防止再发生(pre-commit hook)
[输出] 完整应急响应报告。
二十一、总结
核心价值:
- AI 理解上下文的密钥扫描
- Fail-open 检测(SAST 难以做到)
- 智能修复建议
- 覆盖 14+ 类典型 Insecure Defaults
- 兼容多个合规框架
适用人群:
- 所有项目
- 甲方安全团队
- 金融/医疗/政企(合规要求)
- 开源项目维护者
- Kubernetes 运维
投入产出比:⭐⭐⭐⭐⭐(5/5)—— 所有项目必装。
何时不要用:
- 临时原型(生命周期 < 1 周)
- 单文件脚本(无配置)
- 纯静态 HTML(无服务端)
配套文档:trailofbits/skills 总览 | supply-chain-risk-auditor 依赖 | static-analysis 静态分析
参考资料
快速安装
git clone https://github.com/trailofbits/skills.git ~/trailofbits-skills
mkdir -p ~/.claude/skills
ln -s ~/trailofbits-skills/insecure-defaults ~/.claude/skills/insecure-defaults