FlawOpen

flawopen.com/Teardowns/cve-2026-90970-gitlab-ai-gateway-prompt-template-sandbox-escape

● CVE-2026-90970 · CVSS 9.9[4] · Kritis
Riset Keamanan · FlawOpen

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]

Vektor CVSSCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H[4]
💡 Penjelasan Sederhana (ELI5)

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]
Sandbox escape
Pemanfaatan perilaku di lingkungan terbatas untuk melewati batas yang seharusnya ditegakkan.[3], [6]
CWE-1336
Netralisasi elemen khusus mesin template yang tidak tepat; catatan CVE mengaitkan kelemahan ini.[4], [1]

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 rilisRilis AI Gateway yang diperbaikiTindakan operator
GitLab yang di-hosting sendiri, lini 19.219.2.4Tingkatkan ke tag image Gateway hosting sendiri yang sesuai dan verifikasi image yang diterapkan.
GitLab yang di-hosting sendiri, lini 19.319.3.2Tingkatkan ke tag image Gateway hosting sendiri yang sesuai dan verifikasi image yang diterapkan.
GitLab yang di-hosting sendiri, lini 19.419.4.1Tingkatkan ke tag image Gateway hosting sendiri yang sesuai dan verifikasi image yang diterapkan.
AI Gateway yang di-hosting GitLabGitLab 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

Langkah 1

Pengguna dapat mengatur alur khusus

Syarat advisori adalah pengguna terautentikasi dengan akses Duo Agent Platform. Peran lebih rinci dan seluruh kemampuan alur yang dibutuhkan tidak dijelaskan.[1], [3]

Langkah 2

Alur memberikan konfigurasi template khusus

Konfigurasi alur khusus mencapai sandbox template prompt Gateway. Advisori publik tidak memberikan reproduksi aman lengkap atau ekspresi template yang tepat.[1], [3]

Langkah 3

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]

Langkah 4

Perintah dapat dijalankan pada Gateway

Dampak yang dikonfirmasi adalah eksekusi perintah arbitrer di server AI Gateway, bukan sekadar model gagal mengikuti instruksi.[1], [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)

IMPLEMENTASI RENTAN
# 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
PERBAIKAN AMAN & KUAT
# 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

Sumber