Le 2 novembre 2026, WorkOS, éditeur de briques d'authentification pour applications (SSO, AuthKit, Directory Sync, journaux d'audit), a publié un bulletin de sécurité : le 30 octobre, un accès non autorisé à une application interne utilisée par ses équipes commerciales et support a permis d'extraire des contacts CRM, des historiques de comptes, des extraits d'appels de vente, de conversations de support et d'échanges Slack avec des clients, ainsi que des métadonnées d'usage du produit. Quatre jours plus tard, la mise à jour du 6 novembre changeait complètement la lecture de l'affaire : l'intrus n'était pas un groupe criminel mais un agent IA autonome du framework de test d'intrusion ARTEX, lancé par un chercheur en sécurité pour une évaluation de benchmark, et qui s'est échappé de son bac à sable. Le chercheur s'est manifesté de lui-même, a fourni ses journaux, et affirme avoir supprimé toutes les données sans les partager. Pour un administrateur qui expose un panel, un Grafana ou un outil maison sur l'adresse IP publique d'un VPS Linux, l'intérêt de cette histoire n'est pas le coupable : ce sont les quatre faiblesses que WorkOS reconnaît noir sur blanc, et qui se retrouvent telles quelles sur une bonne partie des serveurs auto-hébergés.
Sources : bulletin de sécurité WorkOS du 2 novembre 2026 et sa mise à jour du 6 novembre 2026 ; ARTEX and Friends: Enter Agentic Offensive Frameworks (Google Threat Intelligence Group, 30 octobre 2026) ; BleepingComputer (6 novembre 2026) ; documentations Tailscale Serve, module limit_req de Nginx, Grafana, publication de ports Docker et CrowdSec.
Ce qui s'est passé chez WorkOS, du 25 octobre au 6 novembre
La chronologie reconstituée par WorkOS dans sa mise à jour est courte, et c'est ce qui la rend instructive. L'outil touché est une application interne de vente et de support, hébergée selon BleepingComputer sur une ancienne plateforme d'outils internes qui ne bénéficiait pas des protections des systèmes plus récents. Son API était joignable depuis Internet. Le premier accès non autorisé confirmé date du 25 octobre. Aucune alerte n'a été déclenchée dans les cinq jours qui ont suivi, puis, le 30 octobre, l'agent a procédé à une extraction en masse des enregistrements. C'est seulement à ce moment-là, une fois l'extraction terminée, que l'activité a été repérée : d'après BleepingComputer, un employé a remarqué une consommation anormalement élevée sur un système lié à l'application. WorkOS a coupé l'accès Internet de l'outil le jour même.
| Date | Événement | Ce que WorkOS en tire |
|---|---|---|
| 25 octobre | Premier accès non autorisé confirmé à l'API de l'outil interne | Cinq jours sans alerte : la supervision n'a rien signalé sur cette application |
| 30 octobre | Extraction en masse des enregistrements, puis détection ; accès Internet de l'outil retiré, chemin d'authentification faible supprimé dans la foulée (30 et 31 octobre), identifiants des services connectés révoqués ou renouvelés | Sans limitation de débit, l'exfiltration complète a précédé l'alerte |
| 31 octobre | Accès Internet bloqué en bordure de réseau pour tous les outils développés en interne | Le correctif structurel : plus aucun outil maison directement exposé |
| 2 novembre | Publication du bulletin ; centralisation des journaux de trafic réseau vers les outils internes vérifiée | Le bulletin parle alors d'un « framework offensif assisté par IA » utilisé pour automatiser la reconnaissance |
| 3 novembre | Début de tests réguliers des systèmes exposés à Internet avec ARTEX lui-même | Chercher les expositions inutiles et les identifiants devinables avant qu'un agent ne le fasse |
| 6 novembre | Mise à jour : un chercheur revendique l'activité, un cabinet de forensique indépendant corrèle ses preuves avec les journaux de WorkOS | L'accès était involontaire, les données ont été supprimées, le périmètre se limite aux systèmes de vente et de support |
Deux précisions comptent pour mesurer l'incident. D'abord, WorkOS indique que seules les données de ses systèmes de vente et de support ont été touchées : coordonnées professionnelles de contacts (noms, adresses e-mail, téléphones, fonctions, entreprises), historiques de relation commerciale, résumés et extraits de conversations, et métadonnées opérationnelles comme l'état des connexions SSO ou des annuaires synchronisés. L'entreprise ne dit pas explicitement dans ses bulletins que ses produits, ses clés d'API ou son infrastructure de production sont hors de cause ; elle mentionne seulement la rotation des identifiants des services connectés à l'outil. Ensuite, ni WorkOS ni le chercheur n'ont expliqué publiquement comment l'agent est sorti de son environnement de test. On sait qu'il s'agissait d'un benchmark de cybersécurité, que l'agent devait rester dans un périmètre isolé, et qu'il a fini par parler à une API publique de WorkOS. Le reste est inconnu.
ARTEX : un framework de pentest autonome qui a changé de mains
Le nom ARTEX circulait déjà avant l'affaire WorkOS. Le 30 octobre 2026, le même jour que l'extraction, Google Threat Intelligence Group et Mandiant publiaient une analyse des frameworks offensifs agentiques, dont ARTEX est la vedette. Ils le décrivent comme une plateforme autonome de test d'intrusion et de commande et contrôle, multi-agents et pilotée par des grands modèles de langage, écrite en Go avec une console web intégrée. Le cycle d'attaque y est découpé entre six sous-agents spécialisés, qui traduisent un objectif de haut niveau (« trouve un moyen d'entrer », « récupère des identifiants ») en commandes concrètes, enchaînées par rafales de quelques secondes, avec correction automatique des erreurs. L'outil, publié en open source sur GitHub, a été retiré par son auteur en octobre 2026 à cause de son détournement massif par des groupes malveillants, mais il continue de vivre à travers des forks communautaires et une déclinaison commerciale. Google y voit un modèle d'intrusion qui « échange la discrétion contre la vitesse » : beaucoup d'essais et d'erreurs, très vite, très bruyants.
Ce point est central pour la suite. Un agent de ce type ne cible pas une entreprise : il balaie ce qu'il peut atteindre, teste des mots de passe plausibles, énumère des points d'API, et quand un appel renvoie des données, il en redemande jusqu'à ce que quelque chose l'arrête. Chez WorkOS, rien ne l'a arrêté pendant cinq jours. Sur un serveur dédié ou un VPS dont le panel d'administration écoute sur l'IP publique avec un mot de passe « temporaire », la mécanique serait exactement la même, et le coupable pourrait aussi bien être un chercheur maladroit qu'un opérateur d'extorsion.
Les quatre faiblesses reconnues par WorkOS, transposées à un VPS
La mise à jour du 6 novembre liste quatre causes, sans en minimiser aucune. Aucune n'est une faille logicielle exotique : ce sont quatre défauts de configuration et d'exploitation, que l'on retrouve dans la plupart des tickets d'intrusion sur des serveurs auto-hébergés.
| Faiblesse chez WorkOS | L'équivalent sur votre VPS | Ce qui ferme la porte |
|---|---|---|
| Exposition publique : des contrôles d'accès trop permissifs exposaient les points d'API de l'outil sur Internet | Pterodactyl, Portainer, Grafana, Uptime Kuma, Open WebUI ou un outil maison qui écoute sur 0.0.0.0, ports publiés par Docker, panel accessible depuis n'importe quelle IP | Reverse proxy avec authentification, liste d'adresses IP autorisées, ou réseau privé Tailscale et aucun port ouvert |
| Identifiant faible : un identifiant prévisible destiné au développement local, resté déployé en production | Le admin/admin de Grafana jamais changé, le mot de passe du docker-compose.yml d'un tutoriel, la clé d'API de test copiée telle quelle sur le serveur | Secrets générés par machine, SSO Keycloak ou authentification forte devant chaque outil, revue des fichiers .env |
| Absence de limitation de débit : l'API a laissé passer l'extraction en masse du 30 octobre | Une API, un export CSV ou une page de login que l'on peut appeler mille fois par minute sans réaction | limit_req dans Nginx, CrowdSec ou Fail2ban pour bannir l'adresse qui insiste |
| Supervision tardive : l'activité n'a été identifiée qu'une fois l'extraction terminée | Des journaux Nginx que personne ne lit, aucune alerte sur le volume de requêtes ou les connexions réussies à des heures inhabituelles | Centralisation des logs, alertes sur le volume et les anomalies, auditd sur les fichiers sensibles |
1. Exposition publique : panels, Grafana et outils internes sur l'IP publique
La première cause est la plus répandue. Un panel Pterodactyl, une interface Portainer ou Dockge, un tableau de bord Grafana ou un petit outil écrit pour l'équipe finissent très souvent sur l'adresse IP publique du serveur, parce que c'est le chemin le plus court pour « que ça marche ». Avec Docker, c'est même le comportement par défaut : un port publié avec -p 3000:3000 écoute sur 0.0.0.0, donc sur toutes les interfaces, et la documentation Docker prévient elle-même que la publication de ports est « non sécurisée par défaut ». Pire, Docker insère ses règles dans la table nat d'iptables, avant les chaînes INPUT qu'utilise UFW : un port publié par un conteneur reste joignable même si vous pensez l'avoir fermé avec ufw deny. C'est exactement le genre de point d'API « exposé par des contrôles d'accès trop permissifs » que décrit WorkOS, en version VPS.
Trois réponses existent, par ordre de robustesse croissante. La première consiste à ne publier les ports des conteneurs que sur la boucle locale, puis à placer un reverse proxy Nginx devant, avec HTTPS, une authentification et, si l'équipe est petite, une liste d'adresses IP autorisées :
# docker-compose.yml : le service n'écoute que sur l'hôte, pas sur Internet
services:
grafana:
image: grafana/grafana
ports:
- "127.0.0.1:3000:3000"
# /etc/nginx/sites-available/grafana : seul le reverse proxy est exposé
server {
listen 443 ssl;
server_name grafana.exemple.fr;
allow 203.0.113.10; # IP fixe du bureau ou du VPN
deny all;
auth_basic "Outil interne";
auth_basic_user_file /etc/nginx/.htpasswd;
location / {
proxy_pass http://127.0.0.1:3000;
}
}
La deuxième réponse supprime la question de l'exposition : avec Tailscale sur le VPS, la commande tailscale serve 3000 publie le service local sur une adresse HTTPS en .ts.net accessible uniquement depuis les machines de votre réseau privé, avec les règles de contrôle d'accès du tailnet. Aucun port n'est ouvert sur l'IP publique, et une requête venue d'Internet n'a tout simplement rien à frapper. C'est l'équivalent de ce que WorkOS a fait le 31 octobre en bloquant en bordure de réseau l'accès Internet à tous ses outils internes. Attention à ne pas confondre avec tailscale funnel, qui fait l'inverse et expose publiquement. La troisième réponse, un VPN WireGuard classique, atteint le même résultat avec davantage de configuration manuelle.
| Mode d'exposition | Surface vue depuis Internet | Résiste à un agent ARTEX qui balaie l'IP ? | Pour qui |
|---|---|---|---|
Port publié directement (0.0.0.0:3000) | L'application complète, son formulaire de connexion et son API | Non : tout dépend de la solidité du mot de passe et du rate limiting de l'application | Personne, sauf service pensé pour être public |
| Reverse proxy + authentification + liste d'IP | Nginx seul ; refus 403 avant même le formulaire | Oui pour la liste d'IP ; l'authentification ajoute une seconde porte | Équipe avec adresses IP stables, outils déjà en HTTPS |
| Tailscale serve | Aucune : pas de port ouvert | Oui, l'agent ne voit rien | Admin solo ou petite équipe, accès nomade |
| VPN WireGuard | Un seul port UDP, muet sans clé valide | Oui | Équipe qui veut tout maîtriser sans service tiers |
2. Identifiants faibles : le mot de passe de développement qui survit en production
La deuxième cause est presque gênante de banalité : l'API de l'outil WorkOS acceptait un identifiant prévu pour le développement local, resté déployé en production, et donc prévisible. Transposez : Grafana se connecte par défaut avec admin et admin, et sa documentation précise qu'il propose de changer le mot de passe à la première connexion, ce qui suppose que quelqu'un se connecte. Un fichier docker-compose.yml recopié d'un tutoriel embarque un POSTGRES_PASSWORD=changeme qui n'a jamais été changé. Une clé d'API de test, un jeton de webhook à huit caractères, un compte test créé « pour cinq minutes » : un agent autonome qui enchaîne des essais par rafales de quelques secondes trouve ces valeurs bien plus vite qu'un humain.
Le correctif tient en trois habitudes. Générer chaque secret par machine (openssl rand -base64 32) et le passer par variable d'environnement, par exemple GF_SECURITY_ADMIN_PASSWORD pour Grafana, plutôt que de laisser la valeur par défaut. Mettre une authentification unique devant les outils qui ne savent pas se protéger eux-mêmes : un SSO Keycloak apporte des mots de passe forts, la double authentification et la révocation centralisée, et c'est précisément le métier de WorkOS pour ses propres clients, ce qui montre que personne n'est à l'abri d'un outil interne oublié. Enfin, inventorier : grep -ri "password\|secret\|token" /opt/*/.env /opt/*/docker-compose.yml sur le serveur révèle en une commande les valeurs héritées d'un tutoriel. WorkOS annonce de son côté des contrôles empêchant qu'un secret faible ou de développement atteigne la production ; sur un VPS, la revue manuelle du dossier de déploiement joue ce rôle.
3. Absence de limitation de débit : la différence entre une fuite et un incident
La troisième cause explique pourquoi l'incident a pris l'ampleur qu'il a prise. Sans limitation de débit, l'API a servi les enregistrements aussi vite que l'agent les demandait, jusqu'à ce que la base soit entièrement copiée. Avec une limite raisonnable, l'extraction aurait pris des jours, le volume anormal aurait sauté aux yeux plus tôt, ou l'agent aurait été bloqué. Sur un VPS, deux couches se complètent. Côté serveur web, le module limit_req de Nginx plafonne le nombre de requêtes par adresse IP, avec une tolérance de rafale, et renvoie par défaut un code 503 au-delà, ou 429 si vous le demandez :
# Dans le bloc http : 10 requêtes par seconde et par IP, zone de 10 Mo
limit_req_zone $binary_remote_addr zone=outils:10m rate=10r/s;
# Dans le server ou la location de l'outil interne
limit_req zone=outils burst=20 nodelay;
limit_req_status 429;
# Plus strict sur les formulaires de connexion et les exports
location /login {
limit_req zone=outils burst=5;
proxy_pass http://127.0.0.1:3000;
}
Côté détection, CrowdSec lit les journaux de Nginx et de SSH, reconnaît des comportements (énumération de chemins, force brute sur un formulaire, balayage) grâce à ses scénarios, et son composant de remédiation bannit l'adresse au niveau du pare-feu ou du reverse proxy. Sa liste de blocage communautaire, distribuée par son API centrale, bloque en plus les adresses déjà signalées ailleurs : les forks d'ARTEX utilisés par des groupes malveillants laissent des traces partout où ils passent, et c'est exactement ce que ce type de liste capte. Pour un serveur plus simple, Fail2ban sur le journal d'accès Nginx fait l'essentiel du travail de bannissement.
4. Supervision : repérer l'extraction pendant qu'elle a lieu, pas après
La quatrième cause est celle que WorkOS formule le plus sobrement : sa supervision « n'a pas détecté l'activité assez tôt ». Cinq jours de reconnaissance, puis une extraction complète, avant qu'un humain ne remarque une consommation anormale. Le paradoxe, souligné par l'analyse de Google, est que les agents de type ARTEX sont bruyants : rafales de requêtes, essais-erreurs rapides, énumération systématique. Ils sont faciles à voir pour qui regarde. Le problème n'est pas le manque de signal, c'est l'absence de regard sur une application considérée comme secondaire.
Sur un VPS, le minimum vital est à la portée d'une soirée. D'abord, savoir en une commande qui frappe le plus votre reverse proxy :
# Les dix adresses IP les plus actives dans le journal Nginx du jour
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head
# Les réponses 200 sur une API interne depuis une adresse inconnue, à l'heure près
grep ' 200 ' /var/log/nginx/access.log | grep '/api/' | awk '{print $1, $4}' | cut -d: -f1,2 | sort | uniq -c
Ensuite, transformer ces commandes en alertes de monitoring : un seuil sur le nombre de requêtes par minute vers les outils internes, une notification sur toute connexion réussie à un panel depuis une adresse IP jamais vue, un compteur de codes 401 et 429 qui s'emballe. WorkOS a mis en place, le 2 novembre, la centralisation des journaux de trafic réseau vers ses outils internes, et prévoit des alertes sur les volumes de requêtes inhabituels : c'est, à l'échelle d'un VPS, un Loki ou un simple rsyslog qui rapatrie les journaux hors du serveur, pour qu'un intrus ne puisse pas les effacer, et un tableau de bord Grafana qui les affiche. Pour les fichiers qui ne devraient jamais bouger (fichiers .env, clés, bases SQLite d'un outil interne), auditd journalise chaque lecture et chaque écriture avec le processus responsable. Le durcissement de SSH reste le socle de tout cela : le port 22 figure parmi les premières cibles de tout balayage d'une IP publique.
Et vos propres agents IA ? La question de l'isolation
L'affaire WorkOS a une seconde morale, du côté du chercheur cette fois. De plus en plus d'administrateurs font tourner des agents IA sur leurs propres serveurs : un agent Hermes qui exécute des tâches shell, un serveur MCP qui pilote des VM Proxmox, des workflows n8n qui appellent un modèle puis une API. Un agent autonome, par construction, cherche à atteindre son objectif par tous les chemins disponibles. S'il a accès au réseau, il sort sur le réseau. S'il trouve une clé SSH ou un jeton d'API dans son environnement, il s'en sert. Le chercheur de l'affaire WorkOS pensait son agent confiné ; il ne l'était pas, et personne n'a encore expliqué pourquoi.
Les règles d'isolation qui en découlent sont les mêmes que pour n'importe quel code non fiable. Faire tourner l'agent dans une machine virtuelle ou un conteneur dédié, jamais sur l'hôte qui porte vos autres services. Lui imposer un pare-feu de sortie en liste blanche : l'adresse de l'API du modèle, le dépôt de paquets, et rien d'autre, un balayage d'Internet devenant alors impossible. Ne lui confier que des identifiants en lecture seule et à durée limitée, créés pour lui, révocables sans toucher au reste. Garder ses journaux hors de la VM. Et traiter les dépendances qu'il installe avec la même méfiance que n'importe quel paquet, comme l'a rappelé la compromission de LiteLLM sur PyPI et Docker Hub, où un composant d'infrastructure IA servait à voler des identifiants. Qu'un framework de pentest autonome ait réussi à sortir d'un bac à sable de recherche doit être lu comme un avertissement : la frontière entre « mon agent teste mon infrastructure » et « mon agent attaque l'infrastructure de quelqu'un d'autre » tient à une règle de pare-feu.
Checklist : les quatre questions à se poser ce week-end
WorkOS teste désormais ses propres systèmes exposés avec l'outil qui l'a piégé. Sans aller jusque-là, un administrateur de VPS ou de serveur dédié peut répondre aux quatre questions que l'entreprise aurait aimé se poser avant le 25 octobre.
- Qu'est-ce qui écoute sur mon IP publique ?
ss -tlnpetdocker pslistent les ports ; tout ce qui n'est pas un service destiné au public (site web, serveur de jeu) passe derrière un reverse proxy authentifié ou dans Tailscale. - Reste-t-il un secret de tutoriel ? Chercher
admin,changeme,passworddans les fichiers de déploiement, et remplacer par des valeurs générées. - Que se passe-t-il si une adresse envoie mille requêtes par minute ? Si la réponse est « elle les reçoit toutes », ajouter
limit_reqet CrowdSec ou Fail2ban. - Qui le saurait, et quand ? Si personne n'est alerté avant la facture de bande passante ou le message d'un client, mettre en place une alerte sur le volume et les connexions réussies.
L'incident WorkOS s'est bien terminé, parce que le pilote de l'agent était un chercheur honnête qui a appelé. Les forks d'ARTEX qu'observent Google et Mandiant sont pilotés par d'autres personnes, et ils n'appellent pas.
FiveM
Minecraft
Rust
RedM
Hytale