Wyjście twojego modelu to niezaufane wejście. Znajdź miejsca, w których kod o tym zapomina.
Analiza statyczna kodu wokół twojego LLM — kodu, który buduje prompt, wywołuje model i coś robi z odpowiedzią. Nie modelu. Nie odporności promptu na jailbreak. Kodu.
Plan bezpłatny obejmuje 3 projekty i 30 analiz miesięcznie, bez limitu użytkowników i bez karty płatniczej. Ta analiza się w nim mieści.
Problem
Model nie jest biblioteką. Jest niezaufanym interpreterem: podajesz mu łańcuch znaków, a on oddaje inny. Wszystko, co wpłynęło na ten łańcuch — własny prompt użytkownika, strona, którą mu pokazano, dokument, który mu przekazano, wynik innego narzędzia — wpłynęło na odpowiedź.
Odpowiedź jest nieszkodliwa, dopóki kod nie nada jej możliwości działania. Niebezpieczeństwo nie polega na tym, że model coś powiedział, lecz na tym, że program w to uwierzył. Każde miejsce, w którym program traktuje wygenerowany tekst jak kod, polecenie, zapytanie, ścieżkę lub adres URL, jest wstrzyknięciem o jeden skok dalej — i w odróżnieniu od pytania, czy prompt da się obejść jailbreakiem, ten skok widać w kodzie źródłowym.
Czego szuka Cybseco
Tam, gdzie wyjście modelu trafia do czegoś, co działa. To są własne kategorie, poziomy istotności i identyfikatory CWE silnika.
eval, exec, compile, new Function, pickle.loads, yaml.load — odpowiedź staje się programem.os.system, subprocess, child_process.exec, execSync — odpowiedź staje się poleceniem.execute, raw, createQuery — text-to-SQL to dokładnie ten wzorzec, a DROP TABLE jest prawdopodobnym dokończeniem.open, readFile, shutil.rmtree, unlink — ../../etc/passwd jest równie prawdopodobnym dokończeniem.requests, httpx, fetch, axios, urlopen — fałszowanie żądań po stronie serwera, wybrane przez model.Konkretny przykład
Dziewięć linii i cały kształt ryzyka.
from openai import OpenAI
client = OpenAI()
def run_plan(task: str):
answer = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": task}],
)
exec(answer.choices[0].message.content)client.chat.completions.create(…) — wywołanie zwracające wyjście modelu. Analizator wiąże zmienną, do której zostało przypisane, i właśnie to pozwala mu śledzić wartość w obrębie funkcji bez analizy międzyproceduralnej.answer zawiera tekst, na który mógł wpłynąć atakujący. Między wywołaniem a ujściem nic go nie sprawdza, nie ogranicza ani nie sprowadza do stałego zbioru operacji.exec(…) — tekst staje się programem we własnym procesie aplikacji, z jej poświadczeniami, jej siecią i jej systemem plików.task — bezpośrednio albo przez dokument pokazany modelowi — wybiera, co zostanie uruchomione. To zdalne wykonanie kodu o jeden skok dalej.Uruchomiony na bieżącym silniku ten fragment daje jeden wynik: llm-output-to-code-execution, CWE-94, istotność krytyczna, pewność wysoka, w linii exec. Pewność jest wysoka, ponieważ zmienna jest związana z rzeczywistym wywołaniem completion. Nazwa, która jedynie wygląda jak odpowiedź modelu — llm_response, reply — jest zgłaszana ze średnią pewnością, bo to domysł, a twierdzenie inaczej byłoby kłamstwem o dowodach.
Czym to nie jest
Inne ryzyka charakterystyczne dla LLM w kodzie
Każde z nich zostało wyzwolone na próbce wobec bieżącego silnika, zanim je tutaj zapisano.
api_key, hasło, IBAN albo dokumentacja medyczna umieszczone w wysyłanym przez ciebie tekście. Zgłaszane tam, gdzie faktycznie budowany jest kontekst promptu, a nie przy każdym f-stringu, który przypadkiem zawiera klucz.PythonREPLTool, ShellTool, interpreter kodu, terminal. Przyznanie jednego z nich zamienia każde pytanie o wstrzyknięcie promptu w pytanie o zdalne wykonanie kodu.allow_dangerous_deserialization=True, trust_remote_code=True, dangerouslyAllow… — framework je wyłączył, bo było niebezpieczne.BLOCK_NONE, safety_settings=None, moderation=false.hub.pull(…), szablon promptu ładowany przez HTTP. Kto kontroluje ten punkt końcowy, kontroluje instrukcje.sk-…, sk-ant-…, AIza…, hf_… zacommitowane do repozytorium.text-davinci-*, gpt-4-0314, claude-instant — słabsza hierarchia instrukcji, brak oddzielenia promptu systemowego.Dlaczego w cokolwiek z tego wierzyć
Niezależny od dostawcy z założenia. Analizator rozpoznaje kształt — coś wytwarza tekst, coś go konsumuje — a nie zapis jednego konkretnego SDK. Nazywa framework, który zobaczył, kiedy może (OpenAI, Anthropic, Google, Azure OpenAI, Mistral, Bedrock, Ollama, LiteLLM, LangChain, LangGraph, LlamaIndex, Semantic Kernel, AutoGen, CrewAI, Hugging Face), żeby wynik mógł powiedzieć, skąd pochodzi. To etykieta na wyniku, a nie integracja z każdym SDK, i framework nieobecny na tej liście jest analizowany dokładnie tak samo.
Zobacz, jak Cybseco wnioskuje o rzeczywistym systemie
Obejrzyj interaktywne demo, a następnie poproś o prowadzony okres próbny dla swojego zespołu.