Skip to content

chore(security): 🔒 gitleaks による AIトークン変数名検知およびデバッグURL露出防止 強化 - #527

Merged
genzouw merged 3 commits into
mainfrom
chore/security-gitleaks-ai-tokens-15705405061812637940
Aug 11, 2026
Merged

genzouw merged 3 commits into
mainfrom
chore/security-gitleaks-ai-tokens-15705405061812637940

Conversation

@genzouw

@genzouw genzouw commented Aug 11, 2026 •

Copy link
Copy Markdown
Owner

背景

対象リポジトリは React 19, Vite, Bun を用いたアプリケーションであり、既に Gitleaks, Secretlint, Trivy, CodeQL 等が導入済みで強固な防御層を持っています。しかし、AI エージェントを多用する開発環境において、独自のフォーマットを持つ AI トークン(例: GH_MODELS_TOKEN への任意文字列の代入)や、デバッグ目的で使用されるローカルトンネル(ngrok 等)の URL がハードコードされてしまうリスクに対する網羅的な防止策が不足していました。

現状認識(事前調査結果のサマリー)

  • 既存防御策: gitleaks.yml, codeql.yml, trivy.yml, .pre-commit-config.yaml 導入済み。
  • 未カバー領域: 固有のフォーマットに当てはまらない AI 系トークンの変数への代入、およびデバッグ用トンネル URL のハードコード。
  • 直近の漏洩リスク兆候: .env ファイル等の流出はないものの、ワークフロー等で多数利用される GH_MODELS_TOKEN や一時的なデバッグ環境が誤ってコミットされる潜在的リスクが存在。

このPRで導入・強化するもの

  • 対象: 既存の .gitleaks.toml カスタムルールおよび docs/security/leak-prevention.md への追記。
  • ツール名とバージョン: gitleaks v8.x (既存)
  • 期待される効果: 汎用的な文字列フォーマットであっても GH_MODELS_TOKEN や TAVILY_API_KEY のような変数への直接代入を検知。また ngrok-free.app 等のデバッグURLを検知し、コミット・Push 前にブロック。

検知漏れリスクと補完策

  • 検知できないケース: 全く未知の変数名に格納された AI トークンや、独自の自社ドメインを用いたローカルトンネル URL。
  • 補完策: 既存の GitHub Secret Scanning と組み合わせて二重化し、Trivy 等の静的解析でカバー。

マージ前に必要な手動作業(チェックリスト)

レビュアーは PR をマージする前に必ず以下を実施してください。
本 PR の CI は手動作業完了を前提に通る設計です。

  • 特になし(0件)。本 PR は既存のルールファイルの更新のみであるため、追加の手動設定は不要です。

マージ後の確認手順

  • 次の push / PR で導入した Gitleaks ワークフローが引き続き green になることを確認
  • ローカルで Gitleaks のカスタムルールがフックとして正常に動作することを確認

ロールバック手順

問題が出た場合は、PR をリバートすることで以前の Gitleaks ルールに戻ります。

参考情報

  • 公式ドキュメント: https://github.com/gitleaks/gitleaks
  • 比較検討した他案: 新規での AI workspace 専用ワークフローの追加 (既存の forbid-sensitive-files と責務が被るため却下)、Secretlint のカスタムルール開発 (Gitleaks の設定ファイル拡張の方が軽量で確実なため却下)。
  • 直近の関連 PR / Issue: なし

PR created automatically by Jules for task 15705405061812637940 started by @genzouw

Summary by CodeRabbit

  • セキュリティ

    • AI関連トークンやローカルトンネルURLの検出対象を拡充しました。
    • 環境変数参照、<REDACTED>、dummy値を除外し、誤検知を抑制します。
  • ドキュメント

    • 追加された検出対象と、漏えい防止に関する設定内容を追記しました。

Co-authored-by: genzouw <29957+genzouw@users.noreply.github.com>
@google-labs-jules

Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@github-actions github-actions Bot added the docs label Aug 11, 2026
@coderabbitai

coderabbitai Bot commented Aug 11, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@genzouw, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 26 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: c720b643-4db8-4dd8-bea3-5743d4e7e24c

📥 Commits

Reviewing files that changed from the base of the PR and between 87b67b9 and 162cee7.

📒 Files selected for processing (2)
  • .gitleaks.toml
  • docs/security/leak-prevention.md
📝 Walkthrough

Walkthrough

.gitleaks.toml にAIトークンとローカルトンネルURLの検知ルールを追加しました。除外条件と検知内容をセキュリティ文書に記載しました。

Changes

リーク検知ルール

Layer / File(s) Summary
カスタムGitleaksルールと文書
.gitleaks.toml, docs/security/leak-prevention.md
AIトークン変数のハードコード値を検知し、環境変数参照、<REDACTED>、dummy値を除外します。ngrok、localtunnel、Cloudflare Quick TunnelsなどのURLを検知します。検知内容をセキュリティ文書に追加します。

Estimated code review effort: 3 (Moderate) | ~15 minutes

Possibly related PRs

  • genzouw/monopo#379: GH_MODELS_TOKEN と TAVILY_API_KEY の検知ルールに関連します。
  • genzouw/monopo#504: AIトークン向けのGitleaksルール追加に関連します。
  • genzouw/monopo#511: Gitleaksルールとリーク防止文書の拡張に関連します。
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed タイトルは、GitleaksによるAIトークン変数名とデバッグURLの検知強化という主要変更を明確に示しています。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/security-gitleaks-ai-tokens-15705405061812637940

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

gitleaks強化: AIトークン変数代入とデバッグ用トンネルURLの漏洩検知を追加

⚙️ Configuration changes 📝 Documentation 🕐 10-20 Minutes

Grey Divider

AI Description

• gitleaksにAI系トークン/APIキーの変数名ベース検知ルールを追加
• ngrok等のデバッグ用ローカルトンネルURLのハードコードを検知対象に追加
• 漏洩防止ドキュメントに新ルールの目的と検知対象を追記
Diagram

graph TD
  Dev(("Developer")) --> Hook(["pre-commit"]) --> Scan(["Gitleaks scan"]) --> Decision{"Leak?"}
  CI(["CI workflow"]) --> Scan
  Scan --> Config[".gitleaks.toml"] --> Docs[/"leak-prevention.md"/]
  Decision -->|"Yes"| Block(["Block commit/PR"]) 
  Decision -->|"No"| Pass(["Allow"/])

  subgraph Legend
    direction LR
    _actor(("Actor")) ~~~ _proc(["Process"]) ~~~ _file["Config file"] ~~~ _doc[/"Doc"/] ~~~ _dec{"Decision"}
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Secretlintのカスタムルールで同等検知
  • ➕ 既存のsecretlint運用(ある場合)に統合しやすい
  • ➕ ルール記述・テスト体系を一元化できる可能性
  • ➖ ルール実装/検証の開発コストが相対的に高い
  • ➖ 既存のGitleaks運用と責務が重なり二重管理になり得る
2. GitHub Secret Scanning(カスタムパターン)中心に寄せる
  • ➕ プラットフォーム側で集中管理でき、ローカル環境差分が出にくい
  • ➕ 検知結果の可視化・通知が強い
  • ➖ コミット前ブロックが弱く、検知が遅れる可能性
  • ➖ リポジトリ外(ローカル)での早期抑止になりにくい
3. デバッグURLのみ専用CIジョブでチェック
  • ➕ 誤検知時の切り分けがしやすい
  • ➕ 用途別にしきい値/例外を調整しやすい
  • ➖ 既存の漏洩検知と分散し、運用が複雑化
  • ➖ フック/CI双方の一貫性が崩れやすい

Recommendation: 本PRの「Gitleaksのカスタムルール拡張」による対処が最も軽量で、コミット前(pre-commit)とCIの両方で同一ルールを強制できる点が優位。代替案は運用/実装コストや責務分散が増えるため、まずは本方式を採用し、誤検知が出た場合はallowlist拡充(例: 既存の${VAR}や``に加え、必要なテスト用固定値の追加)で調整するのがよい。

Files changed (2) +29 / -0

Documentation (1) +7 / -0
leak-prevention.mdGitleaks強化(AIトークン変数名・デバッグURL検知)の運用説明を追記 +7/-0

Gitleaks強化(AIトークン変数名・デバッグURL検知)の運用説明を追記

• AIエージェント開発で起きやすい漏洩リスクとして、AIトークンの変数代入とデバッグ用トンネルURL露出を明示しました。'.gitleaks.toml'拡張の目的と検知対象を追記し、チームの認識合わせを補強します。

docs/security/leak-prevention.md

Other (1) +22 / -0
.gitleaks.tomlAIトークン代入・トンネルURL露出を検知するGitleaksルール追加 +22/-0

AIトークン代入・トンネルURL露出を検知するGitleaksルール追加

• AI関連トークン/APIキーの「変数名+代入」パターンを汎用的に検知するカスタムルールを追加しました。あわせてngrok/localtunnel/Cloudflare Quick Tunnels系ドメインのURLハードコードを検知するルールを追加し、意図しないデバッグURL露出を防ぎます。

.gitleaks.toml

@qodo-code-review

qodo-code-review Bot commented Aug 11, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. AI token rule misses cases ✓ Resolved 🐞 Bug ⛨ Security
Description
monopo-ai-token-assignment only matches quoted values limited to [A-Za-z0-9-_+/=], so hardcoded
tokens assigned without quotes (common in YAML/GitHub Actions) won’t be detected, despite the docs
claiming format-agnostic detection. This reduces the intended leak-prevention coverage for
GH_MODELS_TOKEN/TAVILY_API_KEY/etc.
Code

.gitleaks.toml[R220-222]

+id = "monopo-ai-token-assignment"
+description = "AI トークン・APIキーのハードコード検知 (変数名ベースの汎用検知)"
+regex = '''(?i)(?:GH_MODELS_TOKEN|TAVILY_API_KEY|OPENAI_API_KEY|ANTHROPIC_API_KEY|GROQ_API_KEY|DEEPSEEK_API_KEY)[\s]*[:=][\s]*["'][A-Za-z0-9\-_+/=]{10,}["']'''
Relevance

●●● Strong

Team frequently tightens .gitleaks.toml regexes for better coverage/correctness; unquoted YAML cases
align with that pattern.

PR-#486
PR-#511

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The rule currently requires a quote immediately after := and restricts the value to a base64-like
character class; however, this repo’s workflows use YAML env mappings without quotes, so a hardcoded
token in the same style would not match. The docs also explicitly claim it detects values regardless
of format, which is inconsistent with the implemented regex.

.gitleaks.toml[219-231]
.github/workflows/ai-ci-analyzer.yml[28-32]
.gitleaks.toml[191-195]
docs/security/leak-prevention.md[137-142]
PR-#511

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new gitleaks rule `monopo-ai-token-assignment` requires the secret value to be quoted and to match a narrow character set. This misses common real-world hardcoding patterns like YAML env mappings without quotes (e.g., `OPENAI_API_KEY: sk-...`) and contradicts the documentation that says it detects values regardless of format.

## Issue Context
- Many existing rules in `.gitleaks.toml` use optional quotes (`["']?`) to detect both quoted/unquoted assignments.
- GitHub Actions workflows in this repo use unquoted YAML mappings for env vars, so hardcoding would likely follow the same style.

## Fix Focus Areas
- .gitleaks.toml[219-231]
- docs/security/leak-prevention.md[137-142]

## What to change
1. Update the `monopo-ai-token-assignment` `regex` to:
  - enforce variable-name boundaries (e.g. `\b(?:GH_MODELS_TOKEN|...)\b`)
  - accept both quoted and unquoted assignments
  - accept a broader set of token characters than just base64-ish (e.g. `[^"'\s#]{10,}` for unquoted; `[^"\r\n]{10,}` / `[^'\r\n]{10,}` for quoted)
2. Either:
  - keep docs statement, and make the regex truly format-agnostic, OR
  - narrow the docs statement to reflect the actual detection constraints.

(Optionally) consider setting `secretGroup` to capture the value only, if you restructure the regex with capture groups.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Tunnel URL regex lacks boundary ✓ Resolved 🐞 Bug ☼ Reliability
Description
monopo-local-tunnel-url does not enforce an end-of-host boundary, so it can match inside longer
domains (e.g. https://x.ngrok.io.evil.com) and trigger avoidable false positives. This makes the
new rule noisier than necessary in CI/pre-commit.
Code

.gitleaks.toml[R234-236]

+id = "monopo-local-tunnel-url"
+description = "デバッグ用ローカルトンネル (ngrok, localtunnel, Cloudflare Quick Tunnels 等) の URL 露出"
+regex = '''(?i)https?://[a-z0-9-]+\.(?:ngrok-free\.app|ngrok\.io|loca\.lt|trycloudflare\.com)'''
Relevance

●●● Strong

Strong precedent: they accept adding explicit boundaries/host-end checks in .gitleaks.toml to avoid
partial matches.

PR-#405
PR-#511

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The added tunnel regex ends immediately after the tunnel domain alternative and lacks the kind of
boundary already used elsewhere in this config to prevent partial matches in URLs/hosts.

.gitleaks.toml[233-239]
.gitleaks.toml[82-85]
.gitleaks.toml[179-189]
PR-#511

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new tunnel URL rule matches `https?://<sub>.<tunnel-domain>` but does not require the match to end at a valid host boundary. This can incorrectly match prefixes inside unrelated domains.

## Issue Context
Other URL-like patterns in this repo’s `.gitleaks.toml` already use explicit terminators like `(?:[:/?]|$)` to avoid partial matches.

## Fix Focus Areas
- .gitleaks.toml[233-239]

## What to change
Update the regex to require a host boundary after the domain, e.g.:
- `(?i)https?://[a-z0-9-]+\.(?:ngrok-free\.app|ngrok\.io|loca\.lt|trycloudflare\.com)(?:[:/?#]|$)`

If you expect ports, paths, query strings, or fragments, keep them covered by the boundary class as above.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context
✅ Compliance rules (platform): 34 rules

Grey Divider

Tip of the day
💡 Did you know, you can group findings by type and pick your Finding display, from Minimal to Full

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread .gitleaks.toml Outdated
Comment thread .gitleaks.toml Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.gitleaks.toml:
- Around line 236-239: Extend the URL regex in the gitleaks rule to include
localtunnel.me alongside the existing tunnel domains, so
https://<subdomain>.localtunnel.me is detected and matches the documented
leak-prevention targets.
- Around line 218-239: Update the validation fixtures for the visible rules
monopo-ai-token-assignment and monopo-local-tunnel-url: use quoted API-key
assignments matching the rule’s required quote syntax, and use a supported
tunnel domain such as localtunnel’s configured domain, or expand the rule regex
to include the intended fixture domain. Ensure the fixtures are validated with
Gitleaks v8.30.1 rather than BetterLeaks.
- Around line 222-225:
AIトークン検知用のregexを、変数名境界を付けて対象キーそのものだけに一致させ、値の形式や長さに依存せず検出できるよう更新してください。引用符の有無、空白、`$`、`.`、Unicode、短い値を扱える値captureを追加し、`secretGroup`がそのcaptureを指すよう調整してください。`MY_OPENAI_API_KEY`を誤検知しないことを含め、関連fixtureで各形式と境界条件を検証してください。
- Around line 226-231: Update the dummy allowlist rule in [rules.allowlist] so
it captures only the placeholder value, sets secretGroup to 1, and uses
regexTarget = "secret". Anchor the regex with ^ and $ to allow only complete
intended dummy placeholders, excluding values such as dummy-real-looking-secret.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f016fae2-a986-498e-9c82-120b1b3672af

📥 Commits

Reviewing files that changed from the base of the PR and between 077e43d and 87b67b9.

📒 Files selected for processing (2)
  • .gitleaks.toml
  • docs/security/leak-prevention.md

Comment thread .gitleaks.toml
Comment thread .gitleaks.toml Outdated
Comment thread .gitleaks.toml
Comment thread .gitleaks.toml Outdated
@github-actions

Copy link
Copy Markdown

⚠️ コンフリクトが発生しています

@genzouw さん

このプルリクエストは main ブランチとコンフリクトが発生しています。
マージする前にコンフリクトを解消してください。

解消方法

# ローカルで main ブランチを最新化
git checkout main
git pull origin main

# 作業ブランチに戻って main をマージ
git checkout <your-branch>
git merge main

# コンフリクトを解消してコミット
git add .
git commit -m "fix: 🐛 main ブランチとのコンフリクトを解消"
git push

このコメントは自動的に投稿されました。コンフリクトが解消されると、次回のチェック時にこのコメントは削除されます。

- monopo-ai-token-assignment: 変数名に単語境界を追加してMY_OPENAI_API_KEY等の
  誤検知を防止、値の引用符を任意化・ドット区切りを許容して未引用値/ドット含有
  値の検知漏れを解消、secretGroupを値部分のみに絞りdummyアローリストを
  dummy-real-looking-secretのような値まで許可しないよう厳格化
- monopo-local-tunnel-url: localtunnel.meドメインを追加、ホスト名末尾に境界を
  付与しngrok.io.evil.comのような偽装ドメインでの誤検知を防止
- docs/security/leak-prevention.md: 実際の検知範囲に即した記述へ修正

レビューコメント: #527 (comment)
レビュアー: qodo-code-review
優先度: high

レビューコメント: #527 (comment)
レビュアー: coderabbitai
優先度: high
coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 11, 2026
@genzouw
genzouw enabled auto-merge (squash) August 11, 2026 23:18
…ks-ai-tokens-15705405061812637940

# ------------------------ >8 ------------------------
# Do not modify or remove the line above.
# Everything below it will be ignored.
#
# Conflicts:
#	.gitleaks.toml
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant