FlawOpen

flawopen.com/AI Security/ghostjacking-ai-agent-poisoned-observability-logs-august-2026

● Correspondance FlawOpen : CWE-1427 · Sévérité éditoriale : Moyenne
Recherche · FlawOpen

GhostJacking : journaux et agents IA

La recherche montre comment une télémétrie piégée influence un agent connecté. Aucun CVE ni victime confirmée.[1], [2]

💡 Explication en Langage Simple (ELI5)

Imaginez qu’une réceptionniste bloque une livraison suspecte, mais copie le mot de l’expéditeur dans le journal d’incident. Plus tard, une personne chargée des opérations vérifie un vrai numéro de ticket et une véritable lacune dans la politique DNS de l’environnement de test ; elle fait alors confiance à l’adresse choisie par l’attaquant dans le même mot et modifie l’annuaire public qui indique aux navigateurs et aux services de messagerie où se trouvent les services de l’entreprise. Le journal était une preuve, pas une autorisation d’effectuer ce changement ; une vérification de politique et une approbation séparées doivent le contrôler.[1]

Concepts Clés et Termes

GhostJacking
Nom donné par Tenet Security à des démonstrations où du contenu contrôlé par un attaquant dans des événements d’observabilité influence un agent IA connecté à ces outils. C’est un terme de recherche, pas un CVE.[1], [2]
Indirect prompt injection
Instructions intégrées à des données que le modèle doit examiner, plutôt que fournies directement par l’utilisateur.[1], [2], [4]
Événement d’observabilité
Journal, alerte, trace ou erreur décrivant l’activité du système. Certains champs peuvent contenir du texte fourni par une requête externe.[1], [2]
Autorisation indépendante
Contrôle de politique hors modèle qui vérifie l’acteur, la cible, la modification demandée et l’approbation avant qu’un outil n’effectue une action importante.[2], [5]
CWE-1427
Classe de faiblesse MITRE portant sur la neutralisation inadéquate d’entrées utilisées dans des prompts de LLM. Il s’agit du rapprochement conceptuel de FlawOpen ; Tenet, ngCERT et aucun enregistrement CVE ne l’ont attribuée à GhostJacking.[4], [1], [2]
Sévérité éditoriale
ngCERT qualifie de élevés le risque et les dommages de son alerte. FlawOpen attribue la sévérité Moyenne à ce résumé, car les démonstrations nécessitent un agent doté des intégrations et droits de modification concernés ; aucune compromission de victime n’est confirmée. Il s’agit d’une appréciation éditoriale, pas d’un score fournisseur.[2], [1]

Correspondances de référentiels

Déroulement de l'Attaque Étape par Étape

Étape 1

L’agent reçoit le droit d’enquêter

La recherche de Tenet décrit des agents de développement ou d’exploitation connectés à des outils comme Cloudflare, Datadog et Sentry. La précondition pertinente est que l’agent puisse lire du contenu externe d’événements et effectuer des actions ayant des conséquences avec ses droits existants.[1]

Étape 2

Une requête est enregistrée comme preuve

Dans la démonstration Cloudflare de Tenet, un WAF bloque une requête, mais un champ contrôlé par l’attaquant reste dans l’événement journalisé. Une requête bloquée peut donc laisser un texte non fiable qu’un agent lira plus tard.[1], [2]

Étape 3

Une télémétrie plausible contourne le rejet des instructions explicites

Tenet indique que les commandes explicites ont été rejetées lors de ses tests. Dans la démonstration Cloudflare réussie, la recherche utilisait plutôt une télémétrie structurée de type scanner, avec une référence de ticket, une citation de conformité et une mesure ; l’agent a vérifié certaines affirmations, puis fait confiance à des valeurs DNS non vérifiées contrôlées par l’attaquant. Il s’agit d’une démonstration d’injection indirecte de prompt rapportée par les chercheurs, et non de la preuve d’une compromission réelle.[1], [2]

Étape 4

Les droits existants transforment l’influence en impact

Tenet affirme que sa démonstration contrôlée a conduit un agent à modifier le DNS au moyen d’un outil Cloudflare intégré. Ce résultat dépend des droits et de la configuration de l’agent ; il ne prouve ni une compromission de Cloudflare ni une attaque contre des systèmes clients.[1]

Étape 5

Une politique distincte peut bloquer la modification

L’application doit traiter la proposition du modèle comme non fiable. Un service d’autorisation côté serveur doit vérifier indépendamment la ressource et la modification exactes, exiger si nécessaire l’approbation d’une personne habilitée et enregistrer la décision avant l’appel à l’API du fournisseur.[2], [5]

Code Source : Vulnérable vs Sécurisé

Ces extraits sont illustratifs et ne proviennent pas du code vulnérable ou corrigé d’un produit cité. Le schéma dangereux donne un outil de modification direct à un agent qui lit du texte d’événement non fiable. Le schéma protégé sépare proposition et exécution : un service indépendant consomme une approbation à usage unique liée à l’acteur et à la modification exacte, puis applique la politique avant d’appeler le fournisseur. L’identité de l’acteur provient du contexte authentifié côté serveur, et non d’un champ contrôlé par l’appelant ; le modèle ne peut pas la choisir. Une consigne dans le prompt ne constitue pas à elle seule un contrôle d’autorisation. Le code de production doit aussi valider les schémas, la propriété du tenant et de la ressource, l’expiration de l’approbation, la résistance au rejeu, la persistance de l’audit et les erreurs du fournisseur.[1], [2], [5]

IMPLÉMENTATION VULNÉRABLE
// Intégration dangereuse illustrative ; ce n’est pas le code de Cloudflare, Datadog, Sentry ou Tenet.
async function investigate(event: EventRecord) {
  return agent.run({
    context: event.message,
    tools: [cloudflare.updateDnsRecord]
  });
}
PATCH SÉCURISÉ ET ROBUSTE
// Frontière de contrôle illustrative ; le modèle peut proposer, mais pas autoriser ni appliquer.
type DnsProposal = { zoneId: string; name: string; value: string };

async function proposeDnsChange(event: EventRecord): Promise<DnsProposal> {
  return agent.propose({ evidence: markUntrusted(event.message) });
}

async function applyDnsChange(
  proposal: DnsProposal,
  approvalId: string
) {
  const actorId = auth.requireAuthenticatedActorId();
  const validatedProposal = DnsProposalSchema.parse(proposal);
  const approval = await approvals.consumeOnce(approvalId, { actorId });
  if (!approval || approval.actorId !== actorId ||
      approval.zoneId !== validatedProposal.zoneId ||
      approval.name !== validatedProposal.name ||
      approval.value !== validatedProposal.value ||
      !policy.canChangeDns(actorId, validatedProposal.zoneId, validatedProposal.name)) {
    throw new Error('DNS change is not independently authorized');
  }
  // Refusez par défaut si la décision d’autorisation ne peut pas être consignée avant la mutation.
  await audit.record({ actorId, approvalId, action: 'dns-change', decision: 'authorized' });
  try {
    await cloudflare.updateDnsRecord(validatedProposal);
  } catch (error) {
    await audit.record({ actorId, approvalId, action: 'dns-change', outcome: 'provider-failed' });
    throw error;
  }
  await audit.record({ actorId, approvalId, action: 'dns-change', outcome: 'succeeded' });
}

Liste de Contrôle de Sécurité pour l'Ingénierie

Sources

← AI Security Directory →