Aller au contenu

Revue de sécurité du code généré par un assistant IA

Revue de sécurité du code généré par un assistant IA

Section intitulée « Revue de sécurité du code généré par un assistant IA »

Un assistant de programmation fondé sur l’intelligence artificielle (IA) produit du code qui compile, passe les tests fournis et reproduit avec aplomb les défauts les plus fréquents du code sur lequel il a été entraîné. Le risque tient moins au modèle qu’à la revue : le volume augmente, la vigilance baisse. La position défendue ici : traiter chaque contribution générée comme celle d’un contributeur externe inconnu, avec des contrôles automatiques bloquants avant toute fusion.

→ Lire l’explication complète de la marmotte

Un modèle de langage reproduit les motifs majoritaires de son corpus. Or le code public contient une quantité considérable d’exemples de tutoriels, de réponses de forum et de projets anciens écrits sans contrainte de sécurité. Les classes de défauts qui reviennent correspondent à des entrées bien connues du catalogue CWE (Common Weakness Enumeration) :

  • Injection SQL (Structured Query Language), CWE-89 : requête construite par concaténation ou f-string au lieu de paramètres liés.
  • Validation TLS (Transport Layer Security) désactivée, CWE-295 : verify=False ou rejectUnauthorized: false ajouté pour « faire marcher » un appel qui échouait.
  • Secrets en dur, CWE-798 : clé d’exemple remplacée par une vraie clé au moment du test, puis commitée.
  • Traversée de chemin, CWE-22 : nom de fichier issu de la requête concaténé à un répertoire sans normalisation.
  • Désérialisation non sûre, CWE-502 : pickle.loads ou yaml.load sans chargeur sûr sur une donnée externe.
  • Cryptographie obsolète, CWE-327 : MD5 (Message Digest 5) pour des mots de passe, mode ECB (Electronic Codebook), aléa non cryptographique pour des jetons.
  • Autorisation absente, CWE-862 : point d’accès qui vérifie l’authentification mais pas le droit sur l’objet demandé.

Le dernier défaut est le plus coûteux, et aucun outil ne le trouve seul : le modèle ne connaît pas le modèle d’autorisation du projet, il ne peut donc pas l’appliquer. S’y ajoutent les API (Application Programming Interface) dépréciées, puisque le corpus d’entraînement a une date de coupure et que la documentation courante n’y figure pas toujours.

Des travaux académiques l’ont documenté. Une étude académique de 2022 (« Asleep at the Keyboard? ») a mesuré une proportion substantielle de programmes vulnérables parmi ceux générés dans des scénarios choisis pour exposer des faiblesses CWE. Une étude utilisateur de 2023 (« Do Users Write More Insecure Code with AI Assistants? ») a observé que les participants assistés écrivaient un code moins sûr que les autres, tout en se déclarant plus confiants dans sa sécurité. C’est ce second résultat qui compte pour l’architecture : l’outil dégrade le jugement qui devait le compenser.

Trois mécanismes l’expliquent. Le code généré est bien présenté (nommage cohérent, commentaires, tests), ce qui déplace la relecture vers la forme. Le volume d’un diff généré dépasse vite la capacité de lecture attentive. Enfin, l’auteur apparent du commit n’a pas écrit le code et ne peut pas en défendre chaque ligne en revue.

Les slides de productivité mesurent les lignes produites par heure ; aucune ne mesure les lignes relues par heure, et c’est pourtant la seule qui fixe le débit sûr.

Le compromis est connu : l’assistant fait gagner du temps d’écriture et en fait perdre en relecture. Le gain ne survit que si la relecture est outillée et que les contrôles bloquent au lieu de conseiller.

  1. Branche principale protégée : fusion uniquement par demande de fusion, au moins une approbation humaine d’une personne qui n’est pas l’auteur, contrôles d’intégration continue obligatoires.
  2. Analyse statique bloquante : un outil SAST (Static Application Security Testing) exécuté sur le diff, dont les constats de sévérité haute font échouer la fusion.
  3. Détection de secrets sur l’historique des commits de la branche, pas seulement sur l’état final : un secret ajouté puis supprimé reste dans l’historique.
  4. Propriétaires de code (fichier CODEOWNERS) sur les chemins sensibles (authentification, autorisation, cryptographie, désérialisation, configuration réseau) : une revue par un référent sécurité y devient obligatoire, quel que soit l’auteur.
  5. Tests d’autorisation négatifs exigés pour tout nouveau point d’accès : un utilisateur A ne lit pas l’objet de B. C’est le seul contrôle qui attrape la CWE-862.
  6. Diffs de taille bornée : une demande de fusion trop volumineuse pour être lue est refusée et redécoupée.

Ce que ces contrôles ne garantissent pas : l’analyse statique trouve des motifs, pas des erreurs de logique métier ; la revue humaine reste la seule défense sur l’autorisation et la cohérence avec le modèle de menace. L’ajout de dépendances inventées par les assistants relève d’un autre contrôle, sur la chaîne de dépendances.

Exemple : analyse statique et secrets en intégration continue

Section intitulée « Exemple : analyse statique et secrets en intégration continue »

Extrait reproductible pour un job d’intégration continue sur un dépôt Git. Prérequis : Semgrep et Gitleaks installés dans l’image du job, branche cible origin/main récupérée (git fetch origin main).

Fenêtre de terminal
# Analyse statique limitée aux constats introduits par la branche (comparaison avec main)
# --error : code de retour non nul si un constat est trouvé, donc job en échec
semgrep scan \
--config p/owasp-top-ten \
--config p/secrets \
--baseline-commit "$(git merge-base origin/main HEAD)" \
--severity ERROR \
--error
# Règle locale ciblant un défaut fréquent du code généré : validation TLS désactivée
mkdir -p .semgrep
cat > .semgrep/tls.yml <<'EOF'
rules:
- id: requests-verify-false
languages: [python]
severity: ERROR
message: Validation du certificat TLS désactivée (CWE-295)
pattern: requests.$METHOD(..., verify=False, ...)
EOF
semgrep scan --config .semgrep/tls.yml --error
# Secrets : parcours de chaque commit de la branche, pas seulement de l'état final
gitleaks detect --source . --log-opts="origin/main..HEAD" --redact

La règle locale se versionne avec le code et s’enrichit à chaque défaut trouvé en revue : la revue humaine alimente l’outil, l’outil décharge la revue. Les jeux de règles de la communauté servent de base, ceux du projet font la différence. Pour la chaîne logicielle au sens large, voir la rubrique Développement, et pour les autres pages de la rubrique, IA.

Sans contrôle bloquant, un défaut généré ne reste pas local : il entre dans la base de code, puis dans le contexte que l’assistant relit pour les suggestions suivantes, et le motif vulnérable se recopie dans les nouveaux fichiers du même projet. Sans détection de secrets sur l’historique, une clé commitée puis retirée reste lisible par quiconque clone le dépôt, et sa rotation n’est déclenchée par rien. Sans propriétaires de code sur les chemins sensibles, une modification de la vérification d’autorisation est approuvée par un relecteur qui ne connaît pas le modèle d’accès, et l’historique de revue ne permet plus d’établir qui a validé la règle en vigueur.

Un assistant de programmation écrit du code en imitant les millions d’exemples qu’il a lus. Beaucoup de ces exemples contenaient des erreurs de sécurité : des mots de passe écrits directement dans le code, des vérifications de connexion sécurisée désactivées, des requêtes vers une base de données que l’on peut détourner en tapant un texte piégé. L’assistant reproduit ces erreurs avec le même aplomb que le bon code. Il ne connaît pas non plus les règles propres au projet, par exemple qui a le droit de voir quelle information, donc il oublie souvent de les vérifier. Des chercheurs ont constaté que les programmeurs aidés par un assistant écrivent un code moins sûr, tout en étant plus confiants. Le code est bien présenté, il y en a beaucoup, et la personne qui l’a demandé ne l’a pas écrit elle-même : la relecture devient superficielle. La réponse consiste à imposer des contrôles avant que le code rejoigne la version principale. Des programmes d’analyse cherchent automatiquement les erreurs connues et les mots de passe oubliés, et bloquent l’intégration s’ils en trouvent. Une autre personne doit relire et approuver, un spécialiste pour les parties sensibles. Des tests vérifient qu’un utilisateur ne peut pas lire les données d’un autre. Ces programmes ne comprennent pas les règles du métier : la relecture humaine reste indispensable.

À lire aussi

Pages voisines