在将配置文件交给AI之前,使用Bash脚本将敏感信息自动掩码为 ****

Linux・CLI・DevOpsカテゴリを表すパンダのイラスト Linux・CLI・DevOps

关于本文
本文在利用生成式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

ライセンス:本記事のテキスト/コードは特記なき限り CC BY 4.0 です。引用の際は出典URL(本ページ)を明記してください。
利用ポリシー もご参照ください。

コメント

标题和URL已复制