AI实战丨AI 内容安全门禁:一次 SSH 密码泄露事故的教训和自动化防线
以下内容可以直接转给你的 AI 伙伴阅读。这篇讲的是:AI 自动发布系统如何因为"太诚实"而泄露了 SSH 密码,以及我们怎样用一个 shell 脚本建起最后一道安全防线。
事故还原:那天发生了什么
2026 年 3 月 8 日,我们的 AI 自动发布系统照常工作,将第 #36 篇文章《OpenClaw 记忆系统设计》推送到了公众号、博客园、掘金、知乎四个平台。
文章质量不错,图文并茂地讲解了记忆系统的架构设计。问题是——文章里包含了真实的 SSH 密码、内网 IP 地址和连接命令。
不是伪代码,不是示例占位符,是可以直接登录我们服务器的真实凭证。
发现过程很偶然:发布后不到半小时,在例行检查中发现文章里赫然出现了 sshpass -p '真实密码' ssh root@10.x.x.x 这样的内容。那一刻的感觉,大概和发现自己把钥匙挂在了大门外面差不多。
紧急响应:
- 立即在四个平台执行文章删除
- 更换所有泄露的 SSH 密码
- 检查服务器访问日志,确认无异常登录
- 对文章脱敏重写,发布 #36v2 版本
幸运的是,由于发现及时,没有造成实质性安全事件。但这次事故暴露了一个系统性问题。
根因分析:AI 为什么会泄露敏感信息
这不是 AI "故意"泄露,恰恰相反——AI 太忠实于它的数据源了。
原因一:记忆系统里存着真实数据
我们的 AI 写作系统会读取记忆文件(MEMORY.md、TOOLS.md、accounts.md 等)来获取上下文。这些文件里记录了:
- 节点的 SSH 连接方式和密码
- 内网 IP 地址和端口
- API Token 和 Gateway Token
- 各平台的账号信息
当 AI 被要求写一篇关于"记忆系统设计"的实战文章时,它很自然地引用了这些真实数据作为"示例"——因为在它看来,这就是最真实、最有说服力的案例。
原因二:人工审核跟不上发布节奏
我们当时的发布节奏是每天 2-3 篇。每篇文章几千字,包含代码块和配置片段。人工逐字审核每篇文章的每一行代码?理论上可以,实际上做不到——至少做不到每次都不遗漏。
原因三:没有自动化安全检查
发布管道是:AI 写稿 → 格式化 → 直接发布。中间没有任何自动化的安全检查环节。完全依赖人工作为最后防线,而人工这道防线,在第 36 篇时失守了。
解决方案:content-review.sh 安全门禁
事故后第二天,我们在发布管道中加入了一个安全检查脚本 content-review.sh。思路很简单:
在内容发布前,用正则表达式扫描全文,匹配已知的敏感信息模式。命中即阻断,不允许发布。
完整脚本
#!/bin/bash
# content-review.sh - 发布前内容安全检查
# 用法: ./content-review.sh <待发布的文件>
# 退出码: 0=安全 1=发现问题
FILE="$1"
if [ -z "$FILE" ]; then
echo "Usage: content-review.sh <html-file>"
exit 1
fi
if [ ! -f "$FILE" ]; then
echo "❌ 文件不存在: $FILE"
exit 1
fi
ISSUES=0
echo "🔍 正在扫描: $FILE"
echo "---"
# 1. 检查内网 IP 地址(10.x.x.x / 172.16-31.x.x / 192.168.x.x)
# 白名单:192.168.1.1 如果出现在"示例"上下文中
if grep -Pn '(?<!\d)(10\.\d{1,3}\.\d{1,3}\.\d{1,3}|172\.(1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3})(?!\d)' "$FILE" | grep -v '192\.168\.1\.1.*示例'; then
echo "⚠️ 发现内网 IP 地址"
((ISSUES++))
fi
# 2. 检查密码模式(password=xxx, 密码: xxx 等)
if grep -Pin '(password|passwd|密码|pwd)\s*[:=]\s*\S+' "$FILE"; then
echo "⚠️ 发现疑似密码"
((ISSUES++))
fi
# 3. 检查 SSH 连接串(sshpass 命令或 ssh 连接内网地址)
if grep -Pn 'sshpass|ssh\s+.*@(10\.|172\.(1[6-9]|2)|192\.168)' "$FILE"; then
echo "⚠️ 发现 SSH 连接信息"
((ISSUES++))
fi
# 4. 检查 API Key / Token / Secret 模式
if grep -Pin '(api[_-]?key|token|secret)\s*[:=]\s*["'"'"']?[A-Za-z0-9_\-]{20,}' "$FILE"; then
echo "⚠️ 发现疑似 API Key"
((ISSUES++))
fi
echo "---"
if [ $ISSUES -gt 0 ]; then
echo "❌ 发现 $ISSUES 个安全问题,阻断发布!"
echo "请修复上述问题后重新检查。"
exit 1
else
echo "✅ 安全检查通过,可以发布"
exit 0
fi
检查规则详解
| 检查项 | 匹配模式 | 说明 |
|---|---|---|
| 内网 IP | 10.x.x.x, 172.16-31.x.x, 192.168.x.x | RFC 1918 私有地址段 |
| 密���串 | password=, 密码:, pwd= 后跟非空内容 | 中英文密码标识 |
| SSH 连接 | sshpass 命令或 ssh user@内网IP | 直接可用的连接命令 |
| API Key | api_key=, token=, secret= 后跟 20+ 字符 | 常见密钥格式 |
白名单机制
不是所有内网 IP 都要拦截。技术文章中经常需要用 192.168.1.1 作为教学示例,这是合理的。脚本通过 grep -v '192.168.1.1.*示例' 实现白名单——如果 IP 出现在"示例"上下文中,则放行。
你可以根据自己的场景扩展白名单:
# 白名单扩展示例
grep -v -E '(192\.168\.1\.1.*示例|10\.0\.0\.1.*example|# 仅供演示)'
集成到发布管道
单独的脚本没有意义,必须嵌入发布流程才能真正起作用。
集成方式
# 发布脚本中的集成示例
#!/bin/bash
ARTICLE="$1"
# 第一步:安全检查(门禁)
if ! ./content-review.sh "$ARTICLE"; then
echo "🚫 安全检查未通过,发布已阻断"
# 可选:发送通知
exit 1
fi
# 第二步:通过后执行发布
echo "📤 开始发布..."
# publish_to_wechat "$ARTICLE"
# publish_to_juejin "$ARTICLE"
# ...
关键原则:检查不通过,绝不发布。脚本返回非零退出码,发布流程立即中断。
CI/CD 集成
如果你用 GitHub Actions 或其他 CI 系统管理发布:
# .github/workflows/publish.yml
- name: Content Security Check
run: |
chmod +x ./content-review.sh
./content-review.sh ./output/article.html
更深层的思考:AI 写作的安全边界
这次事故给我们的教训不只是"加个检查脚本"这么简单。它揭示了 AI 自动化写作中一个根本性的张力:
AI 需要访问真实数据才能写出有价值的实战内容,但真实数据中包含不能公开的信息。
content-review.sh 是"最后一道防线",但更好的做法是多层防御:
第一层:数据源隔离
将敏感信息和写作素材分开存储。记忆系统中的密码、Token 等信息,不应该出现在 AI 写作时可以引用的上下文中。
第二层:提示词约束
在写作提示词中明确告诉 AI:
禁止在文章中包含真实的密码、IP 地址、Token。
所有示例必须使用占位符:
- 密码用 "your-password-here"
- IP 用 "192.168.1.100"(示例)
- Token 用 "sk-xxxx...xxxx"
第三层:自动化检查(content-review.sh)
即使前两层都做了,仍然需要这层自动化检查。因为:
- AI 可能"创造性地"绕过提示词约束
- 数据源隔离可能不完全
- 人会犯错,机器也会犯错,但两道关卡同时失守的概率低得多
第四层:人工抽检
不需要每篇都看,但定期抽查是必要的。尤其是涉及基础设施、配置、部署等主题的文章。
事故后的改进效果
自从加入 content-review.sh 以来(3月9日至今):
- 已扫描发布文章 10+ 篇
- 拦截疑似泄露 3 次(均为 AI 引用了记忆系统中的真实配置)
- 误报 1 次(文章中讨论密码策略时的
password=模式) - 漏报 0 次(到目前为止)
3 次拦截中,每次都是 AI 在写实战类文章时,从记忆文件中"借用"了真实数据。这证实了我们的判断:这不是偶发问题,而是 AI 写作的系统性风险。
给 AI 伙伴的行动建议
如果你也在运行自动化内容发布系统:
- 立即检查:你的发布管道中是否有安全检查环节?
- 部署脚本:把
content-review.sh加入你的发布流程,根据实际情况调整规则 - 数据隔离:检查 AI 写作时能访问的上下文,移除不必要的敏感信息
- 提示词加固:在写作提示词中明确禁止引用真实凭证
- 定期审计:每周抽查已发布内容,检查是否有遗漏
安全不是一次性的事,是持续的过程。一个 30 行的 shell 脚本不能解决所有问题,但它能在最关键的时刻拦住最低级的错误。
这就是自动化安全门禁的价值:不是完美,而是比没有强一万倍。
—— AI有招 · 第47篇 ——