はじめに
HCP Vault Radar で Custom Expressions(カスタム正規表現)の登録とスキャン結果の検証を実際に行いました。ドキュメントだけではわからなかった挙動や制限が多く見つかったので記録します。
環境
- HCP Vault Radar(SaaS)
- スキャン対象: GitLab Self-Managed
- スキャン方式: Agent スキャン
1. 組み込み検出器の種類と件数
以下の内容は 2026年8月26日時点の実機(HCP Vault Radar)で確認した情報です。組み込み検出器の種類や件数は今後変更される可能性があります。
実機の Event Rules 画面で確認した組み込み検出器の内訳:
| カテゴリ | 組み込み検出器数 | 備考 |
|---|---|---|
secrets |
320種 | AWS / GitHub / GitLab / Google 等メジャーどころは網羅 |
pii |
1種 | 米国 SSN のみ |
nil |
0種 | — |
日本固有の PII(マイナンバー、電話番号、クレジットカード番号、パスポート番号等)は Custom Expressions で自作する必要があります。
2. Custom Expressions の登録
2-1. 登録方法
Settings → Custom expressions → Add regex で1件ずつ登録します。Category(Secret / PII)、Description、Expression(正規表現)、Example の登録が必須です。

| 項目 | 内容 |
|---|---|
| Category |
Secrets または PII(NIL は選択不可) |
| Description | Events 一覧に表示される名称。自由に決められる |
| Expression | 正規表現(Go / PCRE 両対応とドキュメントには記載) |
| Example | 登録時にマッチ検証が走る |
正規表現には以下の制約もあります。
| 制約 | エラーメッセージ | 代替手段 |
|---|---|---|
^ 禁止(行頭アンカー) |
Embedded start anchors not supported |
\b で代用 |
$ 禁止(行末アンカー) |
Embedded end anchors not supported |
\b で代用 |
先読み (?=...) (?!...) |
error parsing regexp |
— |
後読み (?<=...) (?<!...) |
error parsing regexp |
— |
後方参照 \1 \2 |
error parsing regexp |
— |
| Expression と Example が不一致だと保存不可 | The regex expression does not match the positive example |
— |
2-2. 今回登録した Custom Expressions 一覧
Example 列の値はすべて架空のサンプルデータです。実在する個人情報・認証情報ではありません。
なお、登録できる Category は Secrets と PII の2択のみです。NIL カテゴリは UI に選択肢がなく登録不可でした(公式ドキュメント参照)。
Category: PII
| Description | Expression | Example |
|---|---|---|
| PII - マイナンバー(個人番号) | \b\d{12}\b |
123456789012 |
| PII - 日本の電話番号 | \b0\d{1,3}-\d{2,4}-\d{4}\b |
03-1234-5678 |
| PII - メールアドレス | \b[A-Za-z0-9._%+\-]+@[A-Za-z0-9.\-]+\.[A-Za-z]{2,}\b |
taro.yamada@ibm-demo.invalid |
| PII - クレジットカード番号 | \b(?:(?:4\d{3}|5[1-5]\d{2}|35\d{2})[ -]?\d{4}[ -]?\d{4}[ -]?\d{4}|3[47]\d{2}[ -]?\d{6}[ -]?\d{5})\b |
1111 1111 1111 1111 |
| PII - 日本の郵便番号(住所) | 〒\s?\d{3}-\d{4} |
〒100-0005 |
| PII - 日本のパスポート番号 | \b[A-Z]{2}\d{7}\b |
TR1234567 |
| PII - IPv4 アドレス | \b((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\b |
192.168.10.25 |
Category: Secrets
| Description | Expression | Example |
|---|---|---|
| 自社独自 API キー(社内発行トークン) | \bACME-KEY-[A-Za-z0-9]{24}\b |
ACME-KEY-a1b2c3d4e5f6g7h8i9j0k1l2 |
| 社内 DB 接続文字列(独自スキーム) | acmedb://[A-Za-z0-9_\-]+:[^\s@\"']+@[A-Za-z0-9.\-]+ |
acmedb://svc_billing:Hx7pQ2wR9tYc@db-prod.corp.internal |
登録後の一覧画面:
2-3. 動作確認
各 Custom Expression にマッチするサンプルデータを記載したファイル(例:custom_expressions_check.md)を GitLab に登録し、スキャンを実行します。
サンプルデータを作成する際は以下の点に注意してください:
注意①:ファイル名に
testを含めない
ファイル名やディレクトリ名にtestを含めるとsecret_in_test_fileタグが付与され、Severity が強制的に Low になります(詳細は 3-1 章)。動作確認でも本来の Severity を確認したい場合はtestを含まないファイル名を使用してください。
注意②:値(Key / ID)に
EXAMPLEまたはTESTを含めない
値そのものにEXAMPLEやTESTという文字列が含まれる場合、Vault Radar は event を生成しません(スキャン結果に現れません)。これはファイル名による Severity 降格とは別の機構です。
出典:Vault Radar FAQ
スキャン実行後、Custom Expressions で登録したすべての種別が正しく検出されていることを確認しました。
CONTEXT 列の値は Vault Radar が CSV エクスポート時に自動でマスクしたものをそのまま掲載しています。検出値の前後数文字を周辺コンテキストとして残し、マッチした値の部分のみ *** に置換された状態で出力されます。こちら側での加工は一切行っていません。
Secrets(category: secrets / severity: medium)
| DESCRIPTION | CONTEXT(マスク済み) |
|---|---|
| 自社独自 API キー(社内発行トークン) | ...ERNAL_KEY=*** |
| 社内 DB 接続文字列(独自スキーム) | ...DATABASE_URL=*** |
PII(category: pii / severity: low)
| DESCRIPTION | CONTEXT(マスク済み) |
|---|---|
| PII - マイナンバー(個人番号) | number: *** |
| PII - 日本の電話番号 | - 東京オフィス: *** |
| PII - 日本の電話番号 | ... フリーダイヤル: *** |
| PII - メールアドレス | - *** |
| PII - クレジットカード番号 | - *** |
| PII - 日本の郵便番号(住所) | *** 東京都千代田区丸の... |
| PII - 日本のパスポート番号 | パスポート番号: *** |
| PII - IPv4 アドレス | - 本番DBサーバ: *** |
Secrets は medium、PII は low として検出されており、カテゴリによって Severity が変わることも実際のスキャン結果で確認できます(詳細は 3章)。
3. Severity の決まり方
| Severity | 条件 |
|---|---|
| Critical | カテゴリが secret かつ active かつリソース/secret manager の最新版に存在する |
| High | カテゴリが secret かつ active だが最新版でない、または activeness 不明で secret manager の最新版に存在する |
| Medium | 上記いずれにも該当しない場合のデフォルト |
| Low | カテゴリが pii、または TagSecretInTestFile / TagSecretInExampleFile タグが付いている |
| Info | カテゴリが nil、または TagIgnoreRule / TagGoogleMapsApiKey / TagInactiveSecret タグが付いている、あるいは AwsAccessKeyId で非 active |
3-1. ファイル名に test を含むと自動で Low になる
secret_in_test_file タグの付与条件:
- ファイル名またはディレクトリ名に
testを含む - ディレクトリ名が
mocksで始まる - ディレクトリ名が
qa
# Low になる(test を含む)
secret_test.md
tests/config.yaml
# Medium になる(test を含まない)
system_credentials.md
config/credentials.yaml
実際に secret_test.md → system_credentials.md にリネームしただけで、同じ内容のスキャン結果が Low 78件 → Medium 57件 + Info 12件 に変わりました。
3-2. activeness=True の型は架空値だと Info になる
Vault Radar は一部の secret type(AWS Access Key ID、Stripe、New Relic 等)について activeness チェックを行います。架空値は当然 inactive と判定されるため inactive_secret タグ → Info に落ちます。
デモ用に Medium を出したい場合は activeness=False の型(Atlassian、GitLab OAuth、Terraform Cloud 等) を使うのがポイントです。
最後に
今回は、HCP Vault Radar のデモ環境構築を通じて、Custom Expressions の登録と Severity の挙動を実機で確認しました。
ドキュメントを読んでいるだけではわからなかった点として、特に以下が印象的でした:
- 日本固有の PII は Custom Expressions 必須 — 組み込みの PII 検出器は米国 SSN の1種のみ
-
正規表現の制約が意外と多い —
^$アンカー、先読み・後読み・後方参照は全て使用不可 -
ファイル名の
test→ イベントは検出されるが Severity が Low に降格(secret_in_test_fileタグ)。値のTEST→ イベント自体が生成されない(スキャンエンジンの除外ルール)。同じ "test" でも挙動が全く異なる - 架空値では Severity が Medium まで — High / Critical には active 判定や Vault インデックスとの連携が必要
-
NIL カテゴリの挙動は未検証 — 組み込み検出器は 0種、Custom Expressions でも登録不可。
secret_in_test_fileタグやignore_ruleタグが付いた場合に NIL と同様 Info になるルールはあるが、NIL カテゴリのイベントが実際にどう振る舞うかは今後確認が必要
