A Bash script to automatically mask sensitive information into **** before sharing configuration files with AI

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

About This Article
This article organizes its content by leveraging generative AI while verifying official and primary sources.

Verification Status: 🧪 Syntax and Logic Verified
Syntax and conversion tests using dummy sensitive information were performed in a Linux / GNU Bash environment. Please verify it in your own environment before applying it to actual configuration files.

By incorporating a step to mechanically mask sensitive information before handing configuration files over to AI, you can reduce the number of forgotten redactions compared to relying solely on manual work. However, automatic masking is not a mechanism that eliminates the need for a final check. It should be used under the premise of combining automated processing with human visual inspection. Here, we will create a Bash script that creates a separate masked file without modifying the original file.

What We Want to Protect with This Script

The targets are values that commonly appear in configuration files, such as the following:

  • password / passwd

  • token

  • api_key / api-key

  • secret / client_secret

  • access_key

  • user:password@ within URLs

  • PEM-formatted PRIVATE KEY bodies

On the other hand, we do not assume that it can completely identify unique key names or complex JSON/YAML structures.

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へ渡す]

Do Not Overwrite the Original File

To err on the side of safety, this sample does not rewrite the input file.

app.conf
  ↓ Read
mask-secrets.sh
  ↓
app.conf.masked

This is to ensure that even if there is a bug in the masking process, the original configuration file is not corrupted. Furthermore, if a .masked file with the same name already exists, it stops without overwriting it.

Bash Script

Save it as 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"

We set umask 077 before creating a temporary file, and finally apply chmod 600. The purpose is to handle files during the masking process in a state that makes them difficult for other users to read.

Verify with Dummy Data

Do not use real passwords or API keys; verify using values dedicated for testing.

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

This is the expected output.

host=localhost
password = ****
API_KEY: ****
export ACCESS_TOKEN= ****
url=https://****:****@example.com/api
note=keep-this-line
-----BEGIN PRIVATE KEY-----
****
-----END PRIVATE KEY-----

You can also check whether any known dummy values remain.

grep -En 'dummy-password|dummy-api-key|dummy-token|dummy-pass|DUMMY-PRIVATE-KEY-BODY' demo.conf.masked

If nothing is displayed, the dummy secret strings prepared this time do not remain. However, this does not prove that unknown sensitive information does not exist.

Why Automatic Masking Alone Is Not Enough

Names of sensitive information vary from system to system. For example, credentials, bearers, private_tokens, or custom variable names might be missed by the regular expressions in this sample.

flowchart TB
    A[自動マスク] --> B[既知の秘密文字列をgrep]
    B --> C[差分と本文を目視]
    C --> D{怪しい値が残る?}
    D -->|Yes| E[ルールを追加して再実行]
    E --> A
    D -->|No| F[必要な範囲だけAIへ渡す]

In formats where structure matters, such as JSON or YAML, using dedicated parsers like jq or yq rather than simple line processing may be safer.

Reducing the Amount of Information Passed to AI Itself

Just as important as masking is “passing only the necessary parts.” If you do not need to send the entire configuration file, extract only the sections required to reproduce the issue.

Security should be considered through a multi-layered structure like the following:

flowchart LR
    A[必要範囲だけ抽出] --> B[秘密情報をマスク]
    B --> C[機械チェック]
    C --> D[人間が確認]
    D --> E[AIへ送信]

Conclusion

  • Create a masked copy without modifying the original file

  • Restrict permissions of temporary files right from creation

  • Do not assume automated detection is 100% effective; retain known-value checks and visual inspection

  • Consider dedicated parsers for complex structured data

  • Keep the amount of information passed to AI to the absolute minimum

Official and Primary Sources

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(本ページ)を明記してください。
利用ポリシー もご参照ください。

コメント

Copied title and URL