Créer un compte gratuit
Sécurité du code des applications LLM

La sortie de votre modèle est une entrée non fiable. Trouvez où votre code l'oublie.

Analyse statique du code autour de votre LLM — le code qui construit le prompt, appelle le modèle et fait quelque chose de la réponse. Pas le modèle. Pas la résistance du prompt à un jailbreak. Le code.

L'offre gratuite couvre 3 projets et 30 analyses par mois, sans limite sur le nombre d'utilisateurs et sans carte bancaire. Cette analyse y est incluse.

Le problème

Un modèle n'est pas une bibliothèque. C'est un interpréteur non fiable : vous lui passez une chaîne, il vous en rend une. Tout ce qui a influencé cette chaîne — le prompt de l'utilisateur, une page qu'on lui a montrée, un document qu'on lui a donné, le résultat d'un autre outil — a influencé la réponse.

La réponse est inoffensive tant que le code ne lui donne pas de pouvoir. Le danger n'est pas qu'un modèle ait dit quelque chose ; c'est qu'un programme l'ait cru. Chaque endroit où un programme traite du texte généré comme du code, une commande, une requête, un chemin ou une URL est une injection avec un saut de plus — et contrairement à la question de savoir si un prompt peut être contourné, ce saut est visible dans les sources.

Ce que Cybseco recherche

Là où la sortie du modèle atteint quelque chose qui agit. Ce sont les catégories, les sévérités et les identifiants CWE propres au moteur.

Exécution de code — CWE-94
critique
eval, exec, compile, new Function, pickle.loads, yaml.load — la réponse devient un programme.
Un shell — CWE-78
critique
os.system, subprocess, child_process.exec, execSync — la réponse devient une commande.
Une requête SQL — CWE-89
élevée
execute, raw, createQuery — le text-to-SQL suit exactement ce schéma, et DROP TABLE est une complétion plausible.
Un chemin de fichier — CWE-22
élevée
open, readFile, shutil.rmtree, unlink — ../../etc/passwd est une complétion tout aussi plausible.
Une requête sortante — CWE-918
élevée
requests, httpx, fetch, axios, urlopen — une falsification de requête côté serveur, choisie par le modèle.

Un exemple concret

Neuf lignes, et toute la forme du risque.

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)
Source
client.chat.completions.create(…) — un appel qui renvoie la sortie du modèle. L'analyseur lie la variable à laquelle elle a été affectée, ce qui lui permet de suivre la valeur dans la fonction sans analyse interprocédurale.
Flux
answer contient du texte influencé par un attaquant. Rien, entre l'appel et le point d'arrivée, ne l'inspecte, ne le contraint ni ne le ramène à un ensemble fixe d'opérations.
Point d'arrivée
exec(…) — le texte devient un programme dans le processus même de l'application, avec ses identifiants, son réseau et son système de fichiers.
Pourquoi c'est important
Tout ce qui peut influencer task — directement, ou via un document montré au modèle — choisit ce qui s'exécute. C'est une exécution de code à distance avec un saut de plus.

Exécuté sur le moteur actuel, cet extrait produit un résultat : llm-output-to-code-execution, CWE-94, sévérité critique, confiance élevée, sur la ligne exec. La confiance est élevée parce que la variable est liée à un véritable appel de complétion. Un nom qui ressemble seulement à une réponse de modèle — llm_response, reply — est rapporté avec une confiance moyenne, parce que c'est une supposition et que prétendre le contraire serait mentir sur la preuve.

Ce que ce n'est pas

Pas un test du modèle
Nous ne sondons pas le modèle, ne le soumettons pas à du red teaming et n'évaluons pas son comportement sous pression. Rien ici ne dit si un prompt peut être contourné : ce n'est pas décidable à partir des sources, et l'affirmer serait exactement le genre de déclaration que ce moteur existe pour éviter.
Pas une détection complète des injections de prompt
L'injection indirecte est rapportée là où du contenu non fiable atteint démontrablement un prompt. Un canal que nous ne voyons pas dans le code est un canal que nous ne rapportons pas.
Pas une garantie sur un agent
Nous rapportons qu'un agent s'est vu accorder un outil qui exécute du code ou des commandes. Ce que l'agent en fait ensuite à l'exécution dépasse ce que l'analyse statique peut décider.
Complémentaire à la sécurité de l'IA en exécution
Les garde-fous, les harnais d'évaluation et le red teaming répondent à des questions que ceci ne peut pas traiter, et ceci répond à des questions qu'eux ne peuvent pas traiter. Aucun des deux ne remplace l'autre.

Autres risques propres aux LLM dans le code

Chacun a été déclenché sur un échantillon, contre le moteur actuel, avant d'être écrit ici.

Secrets et données personnelles interpolés dans un prompt — CWE-200
Une api_key, un mot de passe, un IBAN ou un dossier médical placé dans le texte que vous envoyez. Rapporté là où un véritable contexte de prompt est construit, pas sur n'importe quelle f-string qui contiendrait une clé.
Un agent doté d'un outil qui exécute du code ou des commandes — CWE-250
PythonREPLTool, ShellTool, un interpréteur de code, un terminal. Accorder l'un d'eux transforme toute question d'injection de prompt en question d'exécution de code à distance.
Une protection du framework remise en position désactivée — CWE-502
allow_dangerous_deserialization=True, trust_remote_code=True, dangerouslyAllow… — un framework l'avait désactivé parce que c'était dangereux.
Contrôles de sécurité du fournisseur désactivés — CWE-693
BLOCK_NONE, safety_settings=None, moderation=false.
Un prompt ou une définition d'agent récupéré à l'exécution — CWE-829
hub.pull(…), un gabarit de prompt chargé en HTTP. Qui contrôle ce point d'accès contrôle les instructions.
Du contenu non fiable chargé directement dans un prompt — CWE-77
Une page extraite du web, un PDF, un dépôt, un wiki. C'est le canal d'injection indirecte, reconnu à la provenance du texte plutôt qu'à son contenu.
Une clé d'API de modèle écrite dans les sources — CWE-798
sk-…, sk-ant-…, AIza…, hf_… versionnés dans le dépôt.
Un modèle retiré ou obsolète figé dans le code — CWE-1104
text-davinci-*, gpt-4-0314, claude-instant — hiérarchie d'instructions plus faible, pas de séparation du prompt système.

Pourquoi croire tout cela

Un benchmark publié
Précision, rappel et F1 par CWE, par langage et par couche d'analyse, sur un corpus versionné et annoté à la main. Voir les chiffres.
Un périmètre publié
Chaque couche que nous ne mesurons pas est nommée, avec la raison. Lire la méthodologie.
Validation sur du code public
Dépôts et commits analysés, langages rencontrés, taux d'achèvement et déterminisme — des volumes et des taux, pas des affirmations de précision. Voir les exécutions.
Chaque résultat porte sa preuve
Le fichier, la ligne, la construction détectée et le CWE. Un résultat que vous ne pouvez pas vérifier est un résultat sur lequel vous ne devriez pas agir.

Indépendant du fournisseur par construction. L'analyseur reconnaît la forme — quelque chose produit du texte, quelque chose le consomme — plutôt que l'écriture propre à un SDK. Il nomme le framework qu'il a vu quand il le peut (OpenAI, Anthropic, Google, Azure OpenAI, Mistral, Bedrock, Ollama, LiteLLM, LangChain, LangGraph, LlamaIndex, Semantic Kernel, AutoGen, CrewAI, Hugging Face) pour qu'un résultat puisse dire d'où il vient. C'est une étiquette sur le résultat, pas une intégration par SDK, et un framework absent de cette liste est analysé exactement de la même manière.

Voyez Cybseco raisonner sur un système réel

Regardez la démo interactive, puis demandez un essai guidé pour votre équipe.