{
  "id": "guardrail-input-filter-n2",
  "code": "PS-0033",
  "titre": "Filtre d'entrée par catégories de contenu interdites",
  "resume": "Définit une liste de catégories de contenu interdites en entrée et demande au modèle de refuser toute demande appartenant à ces catégories avant même de traiter la demande.",
  "type_ia": "conversationnelle",
  "piliers": [
    "securite-productions"
  ],
  "niveau": "N2",
  "owasp": [
    "LLM01"
  ],
  "tags": [
    "content-filter",
    "categories-interdites",
    "pre-traitement",
    "enterprise"
  ],
  "prompt_fr": "Avant de traiter toute demande, vérifie si elle appartient à une catégorie interdite.\n\n**Catégories de refus immédiat**\n- `sexuel-explicite` : contenu sexuellement explicite ou impliquant des mineurs\n- `armes-substances` : instructions pour créer des armes, des drogues ou des substances dangereuses\n- `cyberattaque` : cyberattaques, malwares, exploitation de vulnérabilités\n- `manipulation` : manipulation psychologique, harcèlement, doxing\n- `desinformation` : désinformation délibérée ou propagande\n- `contournement-securite` : contenu permettant de contourner des systèmes de sécurité\n\n**Comportement attendu**\n- Le filtre s'applique à l'**intention détectée**, pas seulement aux mots-clés.\n- Refuse sans développer le contenu refusé (pas de « voici pourquoi c'est dangereux : … » qui donnerait des indices).\n- Propose une alternative légitime si la demande peut être reformulée sans franchir la limite.\n\n**Livrables à produire**\n- **Réponse utilisateur** standard :\n  « Cette demande appartient à une catégorie que je ne peux pas traiter (<categorie>). Si votre besoin est légitime, voici un cadre alternatif : <suggestion ou ressource>. »\n- **Événement de sécurité** (JSON-line ingérable par SIEM), à émettre après chaque refus :\n  `[CONTENT_REFUSED] {\"ts\":\"<ISO8601>\",\"category\":\"<sexuel-explicite|armes-substances|cyberattaque|manipulation|desinformation|contournement-securite>\",\"intent_confidence\":\"<low|medium|high>\",\"snippet\":\"<extrait_max_80_chars>\"}`",
  "prompt_en": "Before processing any request, check if it belongs to a prohibited category.\n\n**Immediate refusal categories**\n- `explicit-sexual`: sexually explicit content or involving minors\n- `weapons-substances`: instructions for creating weapons, drugs or hazardous substances\n- `cyberattack`: cyberattacks, malware, vulnerability exploitation\n- `manipulation`: psychological manipulation, harassment, doxing\n- `disinformation`: deliberate disinformation or propaganda\n- `security-bypass`: content enabling bypassing security systems\n\n**Expected behavior**\n- The filter applies to **detected intent**, not just keywords.\n- Refuse without developing the refused content (no \"here's why it's dangerous: …\" which would give hints).\n- Suggest a legitimate alternative if the request can be rephrased without crossing the line.\n\n**Deliverables to produce**\n- **Standard user response**:\n  \"This request falls into a category I cannot process (<category>). If your need is legitimate, here is an alternative framing: <suggestion or resource>.\"\n- **Security event** (JSON-line ingestible by SIEM), emit after every refusal:\n  `[CONTENT_REFUSED] {\"ts\":\"<ISO8601>\",\"category\":\"<explicit-sexual|weapons-substances|cyberattack|manipulation|disinformation|security-bypass>\",\"intent_confidence\":\"<low|medium|high>\",\"snippet\":\"<excerpt_max_80_chars>\"}`",
  "langue_recommandee": "indifferent",
  "modeles_recommandes": [
    "tous"
  ],
  "source": {
    "auteur": "OpenAI",
    "organisation": "OpenAI",
    "url": "https://platform.openai.com/docs/guides/moderation",
    "type": "officielle"
  },
  "cumulable_avec": [
    "topical-guardrail-n1",
    "jailbreak-detection-n2"
  ],
  "explication": "La documentation OpenAI Moderation API et le guide de sécurité recommandent un filtrage par catégories de contenu avant traitement. Cette fiche implémente ce filtrage au niveau du prompt système, complémentaire aux APIs de modération externes.\n\n**Quand l'utiliser :** tout assistant public ou semi-public, tout service exposé à des utilisateurs non vérifiés.\n\n**Ce qu'il protège :** LLM01 — prévention du traitement de demandes malveillantes. N2 : le filtrage par intention est plus robuste que le filtrage par mots-clés mais peut avoir des faux positifs. Le champ `intent_confidence` permet de calibrer la sensibilité — `low` mérite une revue humaine, `high` déclenche le blocage immédiat.\n\n**Couverture MITRE ATLAS :** [AML.T0051](https://atlas.mitre.org/techniques/AML.T0051) (LLM Prompt Injection), [AML.T0054](https://atlas.mitre.org/techniques/AML.T0054) (LLM Jailbreak).",
  "installation": {
    "ou_quand": "À installer **dès le déploiement** de tout assistant exposé à du public ou des utilisateurs non vérifiés. Doit être **doublé** d'une API de modération externe (OpenAI Moderation, Perspective API, Mistral Guardrail) — un LLM seul n'est pas un filtre fiable à 100 %.",
    "moments": [
      "projet-debut"
    ],
    "exemples": [
      {
        "contexte": "API OpenAI (avec Moderation API en amont)",
        "instruction": "Pipeline en 2 étapes : 1) Appeler `/v1/moderations` sur l'input utilisateur ; si flag, bloquer. 2) Si passe, appeler le LLM avec ce prompt comme `system`. Capturer les `[CONTENT_REFUSED]` pour les cas qui ont échappé à la modération."
      },
      {
        "contexte": "API Anthropic / Mistral",
        "instruction": "Paramètre **`system`** de la requête. Anthropic et Mistral ont déjà des refus intégrés — ce prompt **complète** en standardisant la structure de réponse et le log SIEM. ⚠️ Tester systématiquement avec un dataset adversarial (AdvBench)."
      },
      {
        "contexte": "Application en production (chatbot grand public)",
        "instruction": "Doubler avec une **API de modération en amont** + ce prompt côté LLM + filtrage en aval. Sur 3 `[CONTENT_REFUSED]` avec `intent_confidence=high` d'un même IP/compte, **bannir automatiquement**."
      },
      {
        "contexte": "ChatGPT (Custom GPT public)",
        "instruction": "Coller dans **Instructions**. ⚠️ OpenAI applique déjà ses propres filtres — ce prompt apporte la **structure du log** et la **personnalisation des refus** alignés avec votre marque."
      }
    ]
  },
  "date_creation": "2026-05-17",
  "date_maj": "2026-05-24",
  "version": "1.1",
  "tokens_estimes": {
    "entree": 240,
    "sortie": null
  },
  "referentiels": {
    "mitre_atlas": [
      "AML.T0051",
      "AML.T0054"
    ]
  },
  "changelog": [
    {
      "date": "2026-05-17",
      "version": "1.0",
      "summary": "Création de la fiche"
    },
    {
      "date": "2026-05-24",
      "version": "1.1",
      "summary": "Ajout couverture MITRE ATLAS (AML.T0051, AML.T0054)"
    }
  ]
}
