flawopen.com/Teardowns/cve-2026-90970-gitlab-ai-gateway-prompt-template-sandbox-escape
CVE-2026-90970:GitLab AI Gateway のプロンプトサンドボックス脱出
細工された Duo Agent Platform フローは AI Gateway のプロンプトテンプレート用サンドボックスを脱出し、コマンドを実行できる可能性がありました。自前運用の場合は対応する修正版へ更新してください。[1], [4]
会話記録をもとに報告書を作る担当者を想像してください。許可された項目は通常のテキストとして転記するはずです。しかし細工されたテンプレートは、担当者に記録の「復元」操作を使わせ、単語を写す代わりに保存データからアプリケーション内で使えるオブジェクトを再構築させることができました。これはデータの表示と、アプリケーションにデータを解釈させることの境界を越えます。研究者の報告には parse_raw() と pickle を使う具体的な経路が記載され、GitLabの勧告はサンドボックス脱出とコマンド実行の影響を確認していますが、すべての手順は説明していません。[3], [6]
主要な概念と専門用語
フレームワーク対応
- このガイドで説明する弱点の CWE 参照: CWE-1336
根本原因の分析 (Root Cause)
GitLab によると、特定条件下で Duo Agent Platform にアクセスできる認証済みユーザーは、細工された設定でプロンプトテンプレート用サンドボックスを脱出し、AI Gateway 上で任意のコマンドを実行できる可能性がありました。CWE-1336、CVSS 9.9 です。条件や脆弱な関数の詳細は公開されていません。2026-09-17 の公開コミットは PromptSandboxedEnvironment を追加し、バインドされたオブジェクトのメソッドアクセスを禁止すると説明し、Jinja の操作やフィルターを強化します。これは実行時オブジェクトへの操作を制限する対策と合いますが、この CVE には触れておらず、修正版イメージとの対応も公開情報で確認できません。独立した公開強化変更として説明してください。公開情報ではこのCVEや修正版イメージとの関連は確認されていません。 GitLab の公開作業項目 1850 には、より具体的な経路が記載されています。Jinja テンプレートが会話履歴内の LangChain HumanMessage に parse_raw() を呼び出し、pickle のデシリアライズを起動します。この実証は報告者によるもので GitLab の staging 環境で行われたと記されていますが、ベンダーの勧告は影響条件のすべてを説明していません。[1], [3], [4], [2]
セルフホスト AI Gateway の修正リリース一覧
| デプロイ / リリース系列 | 修正済み AI Gateway バージョン | 運用担当者の対応 |
|---|---|---|
| セルフホスト GitLab 19.2 系列 | 19.2.4 | 対応するセルフホスト Gateway イメージタグに更新し、稼働中のイメージを確認する。 |
| セルフホスト GitLab 19.3 系列 | 19.3.2 | 対応するセルフホスト Gateway イメージタグに更新し、稼働中のイメージを確認する。 |
| セルフホスト GitLab 19.4 系列 | 19.4.1 | 対応するセルフホスト Gateway イメージタグに更新し、稼働中のイメージを確認する。 |
| GitLab ホスト型 AI Gateway | GitLab は修正済みと説明しています。 | GitLab ホスト型 Gateway を使っていることを確認する。この場合、セルフホスト用イメージの手順は適用しない。 |
ステップ・バイ・ステップの攻撃フロー
テンプレート実行がサンドボックス境界を越える
GitLab の公開作業項目 1850 は、テンプレートが会話履歴内の LangChain HumanMessage に parse_raw() を呼び出して pickle のデシリアライズを起動できたと報告しています。これは研究者が記録した経路です。影響を受ける全フローやベンダーのパッチと同一視しないでください。[3]
ソースコード比較:脆弱 vs 堅牢化
GitLab の作業項目 1850 によると、脆弱なフローは LangChain HumanMessage オブジェクトを Jinja に渡し、テンプレートから parse_raw() を呼び出して pickle のデシリアライズを起動できました。この防御例ではメッセージオブジェクトをテンプレートのコンテキストに渡さず、テキストだけを渡し、呼び出し可能な属性やメソッドへのアクセスを拒否します。これは閉じるべき境界を示す例であり、GitLab が公開したパッチではありません。公開コミット 89b72644 は独立したセキュリティ変更です。実際のタイトルは Jinja block-set の書き込みを扱っており、公開情報では CVE-2026-90970 や修正版イメージとの関連は確認されていません。運用者はベンダーが案内する修正版を適用してください。[3], [2], [6]
ソース抜粋: ai_gateway/prompts/base.py(報告された脆弱なフォーマッター。防御例)
# GitLab の作業項目 1850 で報告された脆弱な経路の抜粋。
from jinja2 import PackageLoader
from jinja2.sandbox import SandboxedEnvironment
from langchain_core.prompts.string import DEFAULT_FORMATTER_MAPPING
from typing import Any
jinja_loader = PackageLoader("ai_gateway.prompts", "definitions")
jinja_env = SandboxedEnvironment(loader=jinja_loader)
def jinja2_formatter(template: str, /, **kwargs: Any) -> str:
return jinja_env.from_string(template).render(**kwargs)
DEFAULT_FORMATTER_MAPPING["jinja2"] = jinja2_formatter
# これは防御パターンの例であり、このCVEに対するGitLabの修正パッチではありません。
from typing import Any
from jinja2 import StrictUndefined
from jinja2.sandbox import ImmutableSandboxedEnvironment
class DataOnlyPromptEnvironment(ImmutableSandboxedEnvironment):
def is_safe_attribute(self, obj: Any, attr: str, value: Any) -> bool:
if callable(value):
return False
return super().is_safe_attribute(obj, attr, value)
def is_safe_callable(self, obj: Any) -> bool:
return False
def render_prompt(template: str, history: list[Any]) -> str:
safe_history = []
for message in history:
content = message.content
if not isinstance(content, str):
raise TypeError("prompt history must contain text only")
safe_history.append({"content": content})
env = DataOnlyPromptEnvironment(undefined=StrictUndefined)
return env.from_string(template).render(history=safe_history)
エンジニアリング&システム堅牢化チェックリスト
- ✓自前運用 AI Gateway を対応する GitLab 系列の 19.2.4、19.3.2、または 19.4.1 に更新し、インストールガイドの対応イメージタグを使ってください。[1], [5]
- ✓Gateway が自前運用か GitLab ホストかを確認してください。GitLab.com、GitLab Dedicated、GitLab ホスト Gateway を使う自管インスタンスは修正済みです。[1]
- ✓テンプレートにアプリの生きたオブジェクトを渡す場合、テンプレートサンドボックスを完全な分離と見なさないでください。[6]
- ✓テンプレートには不活性データだけを渡し、メソッド、デシリアライザー、ファイル/プロセスハンドル、サービスオブジェクトを除外してください。[6], [2]
- ✓属性と呼び出しを制限し、メソッドを直接呼ぶ組み込みフィルターを監査し、本番の Jinja バージョンと設定をテストしてください。[3], [2], [6]
- ✓危険なオブジェクト操作を拒否し、通常の文字列レンダリングを保つ回帰テストを追加してください。実コマンド payload は使わないでください。[3], [6]
- ✓勧告だけから公開悪用キャンペーンや完全な攻撃経路を推測しないでください。NVDによると、CISA CoordinatorのSSVC評価は2026-10-02時点で「exploitation: none」です。これは日付付きの状態であり、その後の状況を示すものではありません。[1], [4]
参考資料
- GitLab AI Gateway Critical Patch Release: 19.2.4, 19.3.2, and 19.4.1
- GitLabコミット89b72644 — CVEとの関連が確認されていない別個の強化:「fix(prompts): block Jinja block-set NSRef writes on non-namespace objects」
- GitLab AI Gateway work item 1850 (reporter account; reproduction material omitted)
- NVD: CVE-2026-90970
- GitLab Self-Hosted AI Gateway installation guide
- Jinja 3.1 Sandbox documentation