flawopen.com/Teardowns/cve-2026-90970-gitlab-ai-gateway-prompt-template-sandbox-escape
CVE-2026-90970: sandbox prompt GitLab AI Gateway ditembus
Alur Duo Agent Platform yang dirancang khusus dapat keluar dari sandbox template prompt AI Gateway dan menjalankan perintah. Operator Gateway yang di-host sendiri harus memperbarui ke rilis perbaikan pada lini GitLab yang sesuai.[1], [4]
Bayangkan petugas mengisi laporan berdasarkan catatan percakapan. Ia seharusnya menyalin kolom yang disetujui sebagai teks biasa. Namun, template yang dirancang khusus dapat menyuruhnya memakai fungsi “pulihkan” pada arsip, sehingga aplikasi membangun kembali objek aktif dari data tersimpan alih-alih sekadar menyalin kata. Batas antara menampilkan data dan meminta aplikasi menafsirkannya pun terlewati. Laporan peneliti mendokumentasikan jalur khusus melalui parse_raw() dan pickle; advisori GitLab mengonfirmasi sandbox dapat ditembus dan perintah dapat dijalankan, tetapi tidak menjelaskan setiap langkah.[3], [6]
Konsep Kunci & Istilah
AI Gateway- Layanan GitLab yang menghubungkan fitur AI ke penyedia model; image Gateway yang di-host sendiri memiliki versi terpisah.[5], [1]
Prompt template- Template yang menggabungkan instruksi tetap dengan nilai runtime seperti masukan alur dan konteks percakapan.[3], [6]
Pemetaan kerangka kerja
- Referensi CWE untuk kelemahan yang dijelaskan dalam panduan ini: CWE-1336
Analisis Akar Masalah (Root Cause)
GitLab mengonfirmasi bahwa dalam kondisi tertentu, pengguna terautentikasi dengan akses Duo Agent Platform dapat memakai konfigurasi alur khusus untuk keluar dari sandbox template prompt dan menjalankan perintah arbitrer pada AI Gateway. Masalah ini CWE-1336, CVSS 9,9. Advisori tidak menjelaskan semua syarat atau fungsi rentan yang tepat. Commit publik bertanggal 17-09-2026 menambahkan PromptSandboxedEnvironment, yang dijelaskan melarang akses metode pada objek terikat, serta memperkuat operasi dan filter Jinja. Ini sejalan dengan pembatasan kemampuan template terhadap objek runtime, tetapi commit tidak menyebut CVE ini dan sumber publik yang diperiksa tidak mengaitkannya ke image yang diperbaiki. Sebut sebagai perubahan penguatan publik yang terpisah; tidak ada sumber publik yang mengaitkannya dengan CVE ini atau image yang diperbaiki. Item publik GitLab #1850 menjelaskan jalur yang lebih spesifik: template Jinja memanggil parse_raw() pada HumanMessage dari LangChain di riwayat percakapan, sehingga memicu deserialisasi pickle. Item tersebut menyebut bahwa demonstrasi ini berasal dari laporan peneliti dan dilakukan di lingkungan staging GitLab; advisori vendor tidak merinci semua kondisi yang terdampak.[1], [3], [4], [2]
Rilis perbaikan AI Gateway yang di-hosting sendiri
| Deployment / lini rilis | Rilis AI Gateway yang diperbaiki | Tindakan operator |
|---|---|---|
| GitLab yang di-hosting sendiri, lini 19.2 | 19.2.4 | Tingkatkan ke tag image Gateway hosting sendiri yang sesuai dan verifikasi image yang diterapkan. |
| GitLab yang di-hosting sendiri, lini 19.3 | 19.3.2 | Tingkatkan ke tag image Gateway hosting sendiri yang sesuai dan verifikasi image yang diterapkan. |
| GitLab yang di-hosting sendiri, lini 19.4 | 19.4.1 | Tingkatkan ke tag image Gateway hosting sendiri yang sesuai dan verifikasi image yang diterapkan. |
| AI Gateway yang di-hosting GitLab | GitLab menyatakan layanan ini sudah diperbaiki. | Pastikan deployment menggunakan Gateway yang di-hosting GitLab; panduan image hosting sendiri tidak berlaku untuk kasus ini. |
Alur Serangan Langkah demi Langkah
Eksekusi template melewati batas sandbox
Item publik GitLab #1850 melaporkan bahwa template dapat memanggil parse_raw() pada HumanMessage dari LangChain di riwayat percakapan dan memicu deserialisasi pickle. Ini adalah jalur yang didokumentasikan peneliti; jangan menyimpulkan bahwa ini mencakup semua flow terdampak atau merupakan patch vendor.[3]
Kode Sumber: Rentan vs Aman
Item GitLab 1850 melaporkan bahwa flow rentan mengekspos objek HumanMessage dari LangChain ke Jinja, tempat template dapat memanggil parse_raw() dan memicu deserialisasi pickle. Contoh defensif ini tidak memasukkan objek pesan ke konteks template, hanya meneruskan teks, dan menolak akses ke atribut serta metode yang dapat dipanggil. Contoh ini menunjukkan batas yang perlu ditutup; ini bukan patch yang dirilis GitLab. Commit publik 89b72644 adalah perubahan keamanan yang terpisah: judulnya membahas penulisan Jinja block-set dan tidak ada sumber publik yang mengaitkannya dengan CVE-2026-90970 atau image yang diperbaiki. Operator harus mengikuti panduan versi perbaikan dari vendor.[3], [2], [6]
Cuplikan sumber: ai_gateway/prompts/base.py (formatter rentan yang dilaporkan; contoh desain defensif)
# Kutipan jalur rentan yang dilaporkan dalam item kerja 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
# Ini hanya contoh pola pertahanan, bukan patch GitLab untuk CVE ini.
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)
Daftar Periksa Penguatan Sistem Rekayasa
- ✓Perbarui AI Gateway yang di-host sendiri ke 19.2.4, 19.3.2, atau 19.4.1 pada lini GitLab yang sesuai dan gunakan tag image dari panduan instalasi.[1], [5]
- ✓Pastikan Gateway di-host sendiri atau oleh GitLab. GitLab menyatakan GitLab.com, GitLab Dedicated, dan instans yang memakai Gateway GitLab sudah diperbaiki.[1]
- ✓Jangan anggap sandbox template sebagai isolasi penuh jika menerima objek aplikasi yang aktif.[6]
- ✓Berikan hanya data inert ke template; keluarkan metode, deserialiser, handle file/proses, dan objek layanan dari konteks.[6], [2]
- ✓Batasi atribut dan pemanggilan, audit filter bawaan yang memanggil metode secara langsung, dan uji versi serta konfigurasi Jinja produksi.[3], [2], [6]
- ✓Tambahkan tes yang menolak operasi objek tidak aman dan mempertahankan rendering string biasa; jangan gunakan payload perintah nyata.[3], [6]
- ✓Jangan menyimpulkan adanya kampanye eksploitasi publik atau rantai serangan lengkap hanya dari advisori. NVD mencatat penilaian SSVC CISA Coordinator pada 02-10-2026 sebagai “exploitation: none”; ini status bertanggal, bukan pernyataan tentang aktivitas setelahnya.[1], [4]
Sumber
- GitLab AI Gateway Critical Patch Release: 19.2.4, 19.3.2, and 19.4.1
- Commit GitLab 89b72644 — penguatan terpisah tanpa hubungan yang terkonfirmasi: “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