关于本文
本文在利用生成式AI的同时,结合官方信息与一手资料进行核实与整理。验证状态:🧪 语法与逻辑已验证
在 Linux / GNU Bash 环境下,使用虚拟的敏感信息进行了语法与转换测试。在应用到实际的配置文件之前,请也在您自己的环境中进行确认。
在将配置文件传递给AI之前,加入自动将敏感信息进行掩码处理的步骤,比完全依赖手工操作更能减少遗漏。不过,自动掩码并不是“让最后确认变得不必要的机制”。它是建立在机械处理与人工目视相结合的前提下使用的。 我们制作一个Bash脚本,它不修改原文件,而是生成一个经过掩码处理的副本文件。
本脚本想要守护的事项
作为对象的是配置文件中容易出现的以下值:
password / passwd
token
api_key / api-key
secret / client_secret
access_key
URL 中的 user:password@
PEM 格式的 PRIVATE KEY 正文
另一方面,我们不认为它能够完全判定独特的键名或复杂的 JSON/YAML。
flowchart LR
A[元の設定ファイル] -->|読み取り| B[mask-secrets.sh]
B --> C{秘密情報らしいか}
C -->|Yes| D[値を **** に置換]
C -->|No| E[そのまま出力]
D --> F[.masked ファイル]
E --> F
F --> G[機械チェック]
G --> H[人間が目視]
H --> I[AIへ渡す]
不覆盖原文件
为了保持安全侧,此样本不会重写输入文件。
app.conf ↓ 读取 mask-secrets.sh ↓ app.conf.masked
这是为了即使掩码处理中存在bug,也不会破坏原配置文件。此外,如果同名的 .masked 已经存在,也不会覆盖并会停止运行。
Bash 脚本
将其保存为 mask-secrets.sh。
#!/usr/bin/env bash
set -euo pipefail
if [[ $# -ne 1 ]]; then
echo "Usage: $0 <config-file>" >&2
exit 2
fi
input=$1
if [[ ! -f "$input" ]]; then
echo "ERROR: file not found: $input" >&2
exit 2
fi
output="${input}.masked"
if [[ -e "$output" ]]; then
echo "ERROR: output already exists: $output" >&2
exit 3
fi
umask 077
tmp=$(mktemp "${output}.tmp.XXXXXX")
trap 'rm -f "$tmp"' EXIT
awk '
BEGIN { in_private_key = 0 }
{
line = $0
if (line ~ /-----BEGIN ([A-Z0-9 ]+ )?PRIVATE KEY-----/) {
print line
print "****"
in_private_key = 1
next
}
if (in_private_key) {
if (line ~ /-----END ([A-Z0-9 ]+ )?PRIVATE KEY-----/) {
print line
in_private_key = 0
}
next
}
gsub(/://[^/:@[:space:]]+:[^@/[:space:]]+@/, "://****:****@", line)
lower = tolower(line)
if (lower ~ /^[[:space:]]*(export[[:space:]]+)?[a-z0-9_.-]*(password|passwd|token|api[_-]?key|secret|client[_-]?secret|access[_-]?key)[a-z0-9_.-]*[[:space:]]*[:=]/) {
eq = index(line, "=")
co = index(line, ":")
if (eq == 0) sep = co
else if (co == 0) sep = eq
else if (eq < co) sep = eq
else sep = co
print substr(line, 1, sep) " ****"
next
}
print line
}
' "$input" > "$tmp"
chmod 600 "$tmp"
mv "$tmp" "$output"
trap - EXIT
printf 'Created: %sn' "$output"
在设置了 umask 077 之后创建临时文件,并在最后应用 chmod 600。其目的是在其他用户难以读取的状态下处理正在掩码途中的文件。
使用虚拟数据进行确认
不使用真正的密码或API密钥,而是用测试专用的值进行确认。
cat > demo.conf <<'EOF' host=localhost password = dummy-password API_KEY: dummy-api-key export ACCESS_TOKEN=dummy-token url=https://alice:dummy-pass@example.com/api note=keep-this-line -----BEGIN PRIVATE KEY----- DUMMY-PRIVATE-KEY-BODY -----END PRIVATE KEY----- EOF chmod +x mask-secrets.sh bash -n mask-secrets.sh ./mask-secrets.sh demo.conf cat demo.conf.masked
这是预期的输出。
host=localhost password = **** API_KEY: **** export ACCESS_TOKEN= **** url=https://****:****@example.com/api note=keep-this-line -----BEGIN PRIVATE KEY----- **** -----END PRIVATE KEY-----
还可以确认已知的虚拟值是否没有残留。
grep -En 'dummy-password|dummy-api-key|dummy-token|dummy-pass|DUMMY-PRIVATE-KEY-BODY' demo.conf.masked
如果没有显示任何内容,则说明本次准备的虚拟秘密字符串没有残留。但是,这并不证明不存在未知的秘密信息。
仅靠自动掩码还不够的原因
秘密信息的名称因系统而异。例如 credential、bearer、private_token、独特的变量名等,可能会在此样本的正则表达式中漏掉。
flowchart TB
A[自動マスク] --> B[既知の秘密文字列をgrep]
B --> C[差分と本文を目視]
C --> D{怪しい値が残る?}
D -->|Yes| E[ルールを追加して再実行]
E --> A
D -->|No| F[必要な範囲だけAIへ渡す]
在 JSON 或 YAML 等结构很重要的格式中,与其进行简单的行处理,有时使用 jq 或 yq 等专用解析器会更安全。
减少传递给AI的信息本身
与掩码同样重要的是“只传递必要的部分”。如果不需要发送整个配置文件,则只截取出复现问题所需的代码段。
安全性可以从以下多层结构来考虑。
flowchart LR
A[必要範囲だけ抽出] --> B[秘密情報をマスク]
B --> C[機械チェック]
C --> D[人間が確認]
D --> E[AIへ送信]
总结
不修改原文件,而是生成经过掩码处理的副本
从创建时起就限制临时文件的权限
不要认为自动检测有100%的效果,要保留已知值的检查和目视检查
复杂的结构化数据应考虑使用专用解析器
传递给AI的信息量本身也要控制在最低必需范围内
官方信息与一手资料
GNU Bash Reference Manual
https://www.gnu.org/software/bash/manual/bash.html
GNU Awk User’s Guide
https://www.gnu.org/software/gawk/manual/gawk.html
OWASP Secrets Management Cheat Sheet
https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html

コメント