Filtre des données sensibles
Certains envois sont refusés avant d'atteindre le fournisseur du modèle. Ce que cela bloque, la forme exacte du refus, et quoi en faire dans votre code.
Ce que c'est
Avant qu'une requête ne parte chez le fournisseur du modèle, le filtre analyse le texte de la requête et refuse l'envoi quand il y reconnaît une donnée confidentielle. Vous n'avez rien à activer et rien à appeler, c'est le comportement par défaut de l'API.
Le filtre s'applique aux quatre routes qui transmettent du texte à un fournisseur : /chat/completions, /messages, /embeddings et /moderations. La consigne système est examinée comme les messages, parce que c'est souvent là qu'un identifiant de connexion se retrouve collé.
Sur une session d'agent, l'analyse ne s'arrête pas à ce que vous écrivez : les résultats d'outils et les arguments des appels d'outils rejoués dans l'historique sont examinés au même titre. C'est le cas qui compte en pratique, puisqu'un agent qui lit un fichier de configuration renvoie son contenu au modèle sans que personne ne l'ait tapé.
Ce qui est arrêté
Deux niveaux se superposent.
- Un socle commun à toute la plateforme, qui ne se désactive pas : les familles de données dont la sortie n'est jamais souhaitable. Un IBAN, un numéro de carte bancaire, une clé d'accès à un service.
- La politique de votre organisation, que son administrateur règle dans l'application : d'autres familles de données, et le traitement à leur appliquer. Un mot de passe écrit en clair, par exemple, est habituellement mis en quarantaine plutôt que simplement refusé.
Le refus nomme la famille de donnée concernée, jamais sa valeur : la valeur ne traverse ni la réponse, ni les journaux.
Le refus
Un envoi refusé rend un 451 avec le code netaix_dlp_blocked. L'enveloppe est l'enveloppe d'erreur unique de l'API, enrichie d'un bloc netaix qui porte ce que le format d'OpenAI ne sait pas dire : la règle, le mode, la référence de l'incident.
{
"error": {
"message": "Envoi refusé par Netaix : ce contenu contient une donnée de type « IBAN » et demande l'accord d'un administrateur. ...",
"type": "invalid_request_error",
"param": null,
"code": "netaix_dlp_blocked",
"netaix": {
"regle": "IBAN",
"mode": "QUARANTINE",
"retenu": true,
"incident_id": "...",
"message_key": "...",
"message_params": null,
"ou_retrouver": "Vous retrouverez cet envoi dans Netaix ..."
}
}
}
| Champ | Ce qu'il porte |
|---|---|
code | Toujours netaix_dlp_blocked. C'est ce champ que votre code doit tester ; il ne changera pas. |
message | Une phrase en français, destinée à être montrée telle quelle à la personne qui a déclenché l'appel. |
netaix.regle | Le nom de la règle qui a refusé, tel que l'administrateur l'a nommée. |
netaix.mode | QUARANTINE quand l'envoi peut être autorisé après coup, sinon un refus simple. |
netaix.retenu | true si l'élément est conservé, chiffré, en attendant la décision de l'administrateur. |
netaix.incident_id | La référence de l'incident, à donner à l'administrateur pour qu'il le retrouve. |
netaix.message_key, netaix.message_params | De quoi traduire le message dans vos propres écrans plutôt que d'afficher le nôtre. |
Le bloc netaix sort de la norme OpenAI, et c'est assumé : la règle et le mode n'ont pas de place dans ce format. Les champs type et param sont présents parce que des bibliothèques les lisent sans vérifier qu'ils existent.
Une différence à connaître si vous lisez les corps à la main : contrairement aux autres erreurs des routes au format Anthropic, ce 451 ne porte pas de champ type au premier niveau. L'objet error, lui, est au même endroit que partout ailleurs, et c'est ce que lisent les SDK.
La quarantaine
Quand le mode est QUARANTINE, le refus n'est pas définitif. L'envoi est mis de côté et l'administrateur de l'organisation le voit apparaître dans l'application, rubrique Protection des données. Il peut l'autoriser.
Une fois l'accord donné, renvoyez la même requête : elle passe. Il n'y a aucun jeton à transporter, aucun second appel à écrire, rien à coder de particulier. L'autorisation reste liée à ce contenu et à son auteur.
Comment le gérer dans votre code
- Ne réessayez pas tout de suite. Un
451n'est pas une erreur passagère : le même corps donnera le même refus tant que l'administrateur n'a pas tranché. Un réessai en boucle n'apporte rien. - Montrez le
messageà votre utilisateur. Il dit la famille de donnée concernée et la marche à suivre. Un message d'erreur générique le laisserait sans solution. - Distinguez les deux modes. Sur un refus en quarantaine, proposez d'attendre l'accord et de relancer. Sur un refus simple, proposez de corriger le contenu.
- Pour un traitement par lot, mettez l'élément refusé de côté avec son
incident_idet continuez le lot. Rejouez les éléments mis de côté après le passage de l'administrateur. - N'essayez pas de contourner le filtre en découpant ou en encodant la donnée. C'est votre organisation que cela expose, et les refus comme les contournements laissent une trace.
Le filtre est un garde-fou, pas un substitut au fait de ne pas envoyer la donnée. La meilleure façon de ne jamais rencontrer ce refus est de ne pas l'envoyer : un numéro de compte ou une clé d'accès n'a presque jamais besoin d'atteindre un modèle pour que la tâche se fasse. Remplacez-la par un identifiant interne dans la requête, et remettez la valeur de votre côté après la réponse.
La présentation destinée aux responsables, sans détail technique, est sur la page Filtre des données sensibles.