Opret gratis konto
Kodesikkerhed i LLM-applikationer

Din models output er utroværdigt input. Find der, hvor din kode glemmer det.

Statisk analyse af koden omkring din LLM — den kode, der bygger prompten, kalder modellen og gør noget ved svaret. Ikke modellen. Ikke promptens modstandskraft over for et jailbreak. Koden.

Den gratis plan dækker 3 projekter og 30 analyser om måneden, uden grænse for antal brugere og uden betalingskort. Denne analyse er omfattet.

Problemet

En model er ikke et bibliotek. Den er en utroværdig fortolker: du giver den en streng, og den giver en tilbage. Alt, hvad der påvirkede den streng — brugerens egen prompt, en side den fik vist, et dokument den fik, resultatet fra et andet værktøj — påvirkede svaret.

Svaret er harmløst, indtil koden giver det en evne. Faren er ikke, at en model sagde noget; den er, at et program troede på det. Hvert sted, hvor et program behandler genereret tekst som kode, som en kommando, som en forespørgsel, som en sti eller som en URL, er en injection med ét spring mere — og i modsætning til spørgsmålet om, hvorvidt en prompt kan omgås med et jailbreak, er det spring synligt i kildekoden.

Hvad Cybseco leder efter

Hvor modeloutput når noget, der handler. Det er motorens egne kategorier, alvorsgrader og CWE-identifikatorer.

Kodeudførelse — CWE-94
kritisk
eval, exec, compile, new Function, pickle.loads, yaml.load — svaret bliver til et program.
En shell — CWE-78
kritisk
os.system, subprocess, child_process.exec, execSync — svaret bliver til en kommando.
En SQL-forespørgsel — CWE-89
høj
execute, raw, createQuery — text-to-SQL er præcis dette mønster, og DROP TABLE er en plausibel fuldførelse.
En filsti — CWE-22
høj
open, readFile, shutil.rmtree, unlink — ../../etc/passwd er lige så plausibel en fuldførelse.
En udgående forespørgsel — CWE-918
høj
requests, httpx, fetch, axios, urlopen — server-side request forgery, valgt af modellen.

Et konkret eksempel

Ni linjer, og hele risikoens form.

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)
Kilde
client.chat.completions.create(…) — et kald, der returnerer modeloutput. Analysatoren binder den variabel, det blev tildelt, og netop det gør det muligt at følge værdien gennem funktionen uden interprocedural analyse.
Flow
answer indeholder tekst, en angriber har påvirket. Mellem kaldet og slutpunktet er der intet, der inspicerer den, begrænser den eller afbilder den på et fast sæt operationer.
Slutpunkt
exec(…) — teksten bliver til et program i applikationens egen proces, med dens legitimationsoplysninger, dens netværk og dens filsystem.
Hvorfor det betyder noget
Alt, der kan påvirke task — direkte eller gennem et dokument, modellen fik vist — vælger, hvad der kører. Dette er fjernudførelse af kode med ét spring mere.

Kørt mod den nuværende motor giver det uddrag ét fund: llm-output-to-code-execution, CWE-94, alvorsgrad kritisk, tillid høj, på linjen exec. Tilliden er høj, fordi variablen er bundet til et faktisk completion-kald. Et navn, der blot ligner et modelsvar — llm_response, reply — rapporteres i stedet med middel tillid, for det er et gæt, og at påstå andet ville være at lyve om beviset.

Hvad dette ikke er

Ikke en test af modellen
Vi afprøver ikke modellen, udsætter den ikke for red teaming og vurderer ikke, hvordan den opfører sig under pres. Intet her siger, om en prompt kan omgås med et jailbreak: det kan ikke afgøres ud fra kildekoden, og at påstå det ville være præcis den slags udsagn, som denne motor findes for at undgå.
Ikke fuldstændig detektion af prompt injection
Indirekte injection rapporteres, hvor utroværdigt indhold påviseligt når en prompt. En kanal, vi ikke kan se i koden, er en kanal, vi ikke rapporterer.
Ikke en garanti om en agent
Vi rapporterer, at en agent har fået et værktøj, der udfører kode eller kommandoer. Hvad agenten derefter gør under kørslen, ligger uden for, hvad statisk analyse kan afgøre.
Et supplement til AI-sikkerhed under kørsel
Guardrails, evalueringsopsætninger og red teaming besvarer spørgsmål, som dette ikke kan, og dette besvarer spørgsmål, som de ikke kan. Ingen af delene erstatter den anden.

Andre LLM-specifikke risici i koden

Hver enkelt blev udløst på en prøve mod den nuværende motor, før den blev skrevet her.

Hemmeligheder og persondata interpoleret ind i en prompt — CWE-200
En api_key, et kodeord, et IBAN eller en patientjournal placeret i den tekst, du sender. Rapporteres, hvor en reel promptkontekst bliver bygget, ikke på enhver f-streng, der tilfældigvis indeholder en nøgle.
En agent, der har fået et værktøj til kode eller kommandoer — CWE-250
PythonREPLTool, ShellTool, en kodefortolker, en terminal. At give ét af dem gør ethvert spørgsmål om prompt injection til et spørgsmål om fjernudførelse af kode.
En beskyttelse i frameworket slået fra igen — CWE-502
allow_dangerous_deserialization=True, trust_remote_code=True, dangerouslyAllow… — et framework slog den fra, fordi den var usikker.
Udbyderens sikkerhedskontroller deaktiveret — CWE-693
BLOCK_NONE, safety_settings=None, moderation=false.
En prompt eller agentdefinition hentet under kørsel — CWE-829
hub.pull(…), en promptskabelon hentet over HTTP. Den, der kontrollerer det endepunkt, kontrollerer instruktionerne.
Utroværdigt indhold indlæst direkte i en prompt — CWE-77
En skrabet side, en PDF, et repository, en wiki. Dette er kanalen for indirekte injection, genkendt på, hvor teksten kom fra, og ikke på, hvad den siger.
En model-API-nøgle skrevet ind i kildekoden — CWE-798
sk-…, sk-ant-…, AIza…, hf_… committet til repositoriet.
En tilbagetrukket eller afløst model låst fast i koden — CWE-1104
text-davinci-*, gpt-4-0314, claude-instant — svagere instruktionshierarki, ingen adskillelse af systemprompten.

Hvorfor du skulle tro på noget af dette

En offentliggjort benchmark
Præcision, recall og F1 pr. CWE, pr. sprog og pr. analyselag, over et versioneret, håndmærket korpus. Se tallene.
Et offentliggjort omfang
Hvert lag, vi ikke måler, er nævnt med begrundelse. Læs metoden.
Validering på offentlig kode
Analyserede repositories og commits, mødte sprog, gennemførelsesrate og determinisme — mængder og rater, ikke påstande om nøjagtighed. Se kørslerne.
Hvert fund bærer sit bevis
Filen, linjen, den konstruktion der matchede, og CWE'en. Et fund, du ikke kan efterprøve, er et fund, du ikke bør handle på.

Udbyderuafhængig af konstruktion. Analysatoren genkender formen — noget producerer tekst, noget forbruger den — frem for ét bestemt SDK's skrivemåde. Den nævner det framework, den så, når den kan (OpenAI, Anthropic, Google, Azure OpenAI, Mistral, Bedrock, Ollama, LiteLLM, LangChain, LangGraph, LlamaIndex, Semantic Kernel, AutoGen, CrewAI, Hugging Face), så et fund kan sige, hvor det kom fra. Det er en mærkat på fundet, ikke en integration pr. SDK, og et framework, der ikke står på listen, analyseres på nøjagtig samme måde.

Se Cybseco ræsonnere om et virkeligt system

Se den interaktive demo, og anmod derefter om en guidet prøveperiode til dit team.