Pousser
Un seul saut réseau : l'alerte arrive instantanément — et vous êtes exactement aussi fiable que la politique de réessai de votre outil. Une alerte que personne n'a reçue est une alerte dont personne ne sait rien.
Documentation
La page d'accueil est la version courte. Voici la longue : ce que fait chaque partie, ce qu'elle refuse de faire, et le raisonnement derrière les deux. Lisez dans l'ordre ou allez droit à ce qui vous intéresse — rien ici ne dépend de ce qui précède.
MENATER est une console de sécurité opérationnelle que vous installez sur votre propre machine. Elle prend les alertes que remontent vos outils de détection, détermine lesquelles comptent, et met devant une personne celles qui demandent une décision. C'est gratuit, open source, et il n'y a aucune société derrière.
Elle a deux moitiés qui partagent un même écran. Le côté alertes traite ce qui a déjà eu lieu — une alerte est un fait accompli. Le côté code traite ce qui est sur le point d'arriver : une faille dans votre code source, avant qu'elle ne parte en production. Elles partagent une interface et une connexion ; elles ne s'alimentent pas encore l'une l'autre.
L'idée de conception, en une phrase. Une IA qui lit une alerte de sécurité lit un texte écrit par un attaquant : l'IA a donc le droit de lire et de proposer, et une personne est la seule chose autorisée à agir.
Trois programmes tournent : une base de données, la console elle-même, et l'analyseur de code. Rien d'autre n'est nécessaire, et rien ne quitte votre machine hormis les requêtes que vous avez configurées — vers le fournisseur d'IA dont vous avez fourni la clé, et vers les services de réputation que vous avez choisi d'activer.
Docker est la façon normale d'installer MENATER, pas une option parmi d'autres. Il vous faut Docker et rien de plus : pas de base de données à configurer, pas de schéma à appliquer à la main, pas de deuxième machine.
# renseignez les deux mots de passe demandés
cp .env.example .env
# base de données + console + analyseur de code
docker compose up -d --build
→ http://localhost:4400
Utile ensuite : docker compose logs -f console suit ce que fait la console, docker compose down arrête tout en gardant vos données, et docker compose down -v efface tout, base de données comprise.
La base de données et l'analyseur de code ne sont joignables que depuis l'intérieur de la pile. Un seul port est publié, et il sert à la fois l'interface et l'API — un second point d'entrée voudrait dire une serrure qui ne protège que la moitié de l'application.
Vous voulez le faire tourner sans Docker ? npm run dev dans dashboard/ démarre les trois processus avec rechargement à chaud. C'est un mode de développement : il suppose que vous avez déjà Node, une base de données en marche et le schéma appliqué.
Elle démarre en trois minutes et ne trie rien. C'est délibéré : chacun des quatre points ci-dessous est une décision que la console refuse de prendre à votre place. Une liste de contrôle en haut de la page de réglages les suit tous les quatre jusqu'à ce qu'ils soient faits.
| # | Ce que vous devez faire | Ce qui arrive si vous le sautez |
|---|---|---|
| 1 | Définir un secret partagé pour le point d'entrée des alertes | La porte reste fermée. Un secret vide la ferme au lieu de l'ouvrir — « aucune authentification configurée » ne doit jamais se lire « aucune authentification requise ». |
| 2 | Activer le point d'entrée | Toutes les alertes sont refusées. |
| 3 | Lui donner une clé pour un modèle d'IA | Chaque alerte atterrit chez un humain avec une confiance de zéro, et dit pourquoi. Rien n'est perdu ; rien n'est trié. |
| 4 | Pointer un outil de détection vers lui | Aucune alerte n'arrive. |
Les clés des services de réputation et les notifications de messagerie sont facultatives. Un service auquel vous n'avez pas donné de clé s'affiche Pas interrogé — une question que personne n'a posée, ce qui n'est pas la même chose qu'une question restée sans réponse.
L'onglet Santé teste à la demande chaque maillon de la chaîne et nomme, pour chacun, la conséquence puis le remède. Il rapporte quatre états et non deux, si bien que « vérification en cours » n'est jamais annoncé comme « rompu ».
MENATER exécute son propre moteur. Il n'y a aucune plateforme de workflows à installer et aucun second produit qui devrait être joignable pour qu'une alerte soit triée — un workflow ne peut donc pas être à moitié déployé, renommé dans un éditeur, ou laissé non publié. La console lit son propre registre de ce qui s'est exécuté.
Un sixième existe et ne s'exécute jamais dans la séquence. Le gestionnaire d'erreurs est déclaré sur les cinq autres et appelé seulement depuis leurs branches d'échec. Aucune panne n'est silencieuse : chaque branche journalise, notifie, ou les deux.
Il y a deux façons de livrer une alerte, et elles échouent différemment. Votre outil peut la pousser vers MENATER à l'instant où elle survient, ou MENATER peut demander à votre outil les nouvelles alertes à intervalle régulier. Aucune n'est meilleure.
Un seul saut réseau : l'alerte arrive instantanément — et vous êtes exactement aussi fiable que la politique de réessai de votre outil. Une alerte que personne n'a reçue est une alerte dont personne ne sait rien.
En moyenne, la moitié d'un intervalle d'attente — et rien n'est perdu à cause d'un appel qui n'est jamais arrivé, parce que le signet est resté où il était.
Le réglage par défaut utilise les deux, parce que le coût ne tombe pas sur les mêmes alertes. Une alerte critique contenue quatre minutes trop tard n'a pas été contenue ; une alerte de faible priorité triée quatre minutes trop tard reste de faible priorité. Les deux niveaux urgents prennent donc le chemin instantané et les deux autres sont interrogés. Une alerte dont la priorité n'a pas pu être lue prend le chemin rapide — garer discrètement quelque chose qui pourrait être critique est précisément l'échec que ce produit existe pour empêcher.
Deux niveaux, et la différence entre eux est celle qui sépare on ne peut rien en faire de cette détection n'avait tout simplement pas d'adresse de destination.
| Niveau | Champs | Règle |
|---|---|---|
| Identité | alert_id · rule_name · severity · timestamp · raw_log | Obligatoire. Un champ manquant vaut refus — et le refus nomme les champs. |
| Observables | source_ip · dest_ip · user · host · process · file_path · url | Facultatif. Absent reste absent : null, jamais une chaîne vide, jamais inventé. La plupart des détections réelles n'ont pas d'adresse de destination. |
| Tout le reste | ce que votre outil envoie | Conservé intégralement, sur le dossier et dans la ligne d'audit. Rien de ce qu'envoie votre outil n'est jeté. |
La conséquence à retenir. Isoler une machine refuse de s'exécuter quand il n'y a aucune machine à nommer. Une action dont la cible est inconnue n'est pas une action.
Les alertes arrivent sur POST /api/ingest/<source>, et c'est la route qui décide comment le contenu est lu — jamais le contenu lui-même, si bien qu'un émetteur ne peut pas se faire passer pour un autre. L'intégration Wazuh ne convertit rien : elle transmet l'alerte telle quelle et la console traduit.
Regroupés plutôt qu'amputés. Dix boutons identiques coûtent une décision chaque fois qu'on les regarde ; le remède, ce sont des catégories, pas un second menu à l'intérieur du premier.
| Onglet | Ce qu'on y trouve |
|---|---|
| Alerts | La file et la fiche d'incident. Cinq colonnes portent huit informations : la gravité est à l'intérieur de ce que c'est, et la confiance à l'intérieur du verdict, parce que 0,58 ne veut rien dire sans le verdict qu'il qualifie. Chaque valeur d'une alerte porte un raccourci vers Recherche avec la question déjà posée. |
| Code | Lancer une analyse de code et lire le rapport. L'onglet est chargé à la première ouverture puis gardé en mémoire — changer d'onglet pendant une analyse ne la coupe pas. |
| Ingestion | Comment les alertes entrent : la politique de livraison, les sources sur chaque chemin, et le pipeline tel qu'il s'exécute, avec ses variables modifiables. |
| Rules | Déclarez ce qui est normal chez vous — le scanner autorisé, la fenêtre de sauvegarde — avec un essai à blanc qui répond quelle règle correspondrait à cette alerte sans toucher au pipeline. Huit modèles sont livrés désactivés et sans propriétaire. |
| Tracking | La vue non réduite : chaînes rompues, exécutions rattachées à aucune alerte, journal cherchable, rejeu. Les orphelines attendues — la sonde de diagnostic envoie exprès une alerte invalide — sont listées et jamais comptées, sinon l'onglet clignoterait après chaque test de connectivité, et une alarme permanente cesse d'être lue. |
| Metrics | Deux taux, jamais additionnés. Voir Le mode observation. |
| Health | Un bouton qui teste chaque maillon de la chaîne, et neuf alertes de test à y faire passer — une par chemin de code plutôt qu'une par scénario : sans destination, avec une empreinte, malformée, en double. |
| Lookup | Poser une question sur une valeur — une adresse, un domaine, une adresse web, une empreinte de fichier, un e-mail — plus une vérification de mot de passe compromis dont l'empreinte ne quitte jamais votre navigateur. Les formats obfusqués (1.2.3[.]4, hxxp://) sont acceptés, et les deux formes sont affichées. |
| Guide | La documentation intégrée à la console, cherchable — et la recherche lit aussi le glossaire, si bien qu'un mot cherché dans le mauvais vocabulaire trouve quand même sa section. |
| Settings | Clés, sources de journaux, la table qui relie machines et code, les moteurs d'analyse, l'assistant — et la liste de ce qui manque encore. |
Un panneau de discussion ancré sur le côté de l'écran où vous êtes. Il répond aux questions sur cette installation — explique-moi l'alerte 1234 simplement, pourquoi attend-elle encore ?, que reste-t-il à configurer ? — et il reçoit la page où vous vous trouvez, si bien que « cette alerte » ne demande rien à taper.
Tout son modèle de sécurité tient dans le fait qu'il ne peut pas agir. Sa liste d'outils est fermée à sept consultations en lecture seule : la file, une alerte, une chaîne, les règles, les mesures, la santé, et l'état de configuration. Il n'y a rien qui approuve, isole, clôt, rejoue, modifie une règle ou écrit un réglage.
Ce n'est pas de la prudence pour la forme. Qui pose une question sur une alerte pose une question sur un journal qu'un attaquant a composé, et un accès sans restriction d'un modèle au contenu des journaux se mesure à 87 % de réussite d'injection de consignes. Trois couches y répondent, dans l'ordre où elles tiennent réellement :
Quatre fournisseurs d'IA sont pris en charge, une clé chacun, choisis dans les réglages. Rien n'est conservé : la conversation voyage avec chaque question et n'est stockée nulle part. Garder les fils créerait une quatrième copie du contenu des alertes, hors du registre d'audit, sans politique de conservation. Chaque réponse montre ce qu'elle a consulté — une réponse que vous ne pouvez pas vérifier est une réponse crue pour de mauvaises raisons.
Ces mêmes consultations en lecture seule peuvent être exposées à un assistant IA que vous faites tourner vous-même — Claude Desktop, Claude Code, Cursor, VS Code — via le protocole MCP. C'est désactivé par défaut, et éteint ou sans jeton, l'adresse répond comme si elle n'existait pas.
Les réglages contiennent une page d'installation en quatre étapes : l'activer, générer un jeton, copier le bloc pour votre client, appuyer sur le bouton de test. L'adresse dans ce bloc vient de l'adresse par laquelle vous avez atteint la console, pas d'un document — installez-la sur la machine d'un collègue et le bloc nomme leur machine. Le jeton est affiché une seule fois, et le test s'exécute sur le serveur, parce que le navigateur est délibérément refusé par la même protection qui empêche une page web hostile d'atteindre un service tournant chez vous.
Ce qui est exposé : 14 outils, 8 questions toutes prêtes, 9 ressources, tous en lecture seule. Les questions toutes prêtes comptent plus qu'il n'y paraît — un client qui voit dix noms d'outils voit dix lectures et aucune raison de s'en servir, alors que explique cette alerte, à quel point est-ce dangereux, pourquoi ça attend et rédige-moi une passation d'équipe sont les questions que cette console existe pour répondre, proposées plutôt que devinées.
Le jeton constitue tout le contrôle d'accès. Quiconque peut joindre la console et le détient peut lire la file, les alertes et les règles. Traitez-le comme le mot de passe de la console. Il ne peut rien modifier : il n'y a aucune écriture dans la liste.
Six jeux de couleurs, changeables depuis l'en-tête de cette page aussi. Chacun redéfinit la palette entière : hériter trois couleurs d'un autre thème produit un accident que la relecture ne rattrape pas, comme un gris foncé resté sur un fond crème.
Le contraste est mesuré, pas jugé à l'œil. Un test calcule les rapports de contraste standard et refuse une palette qui passe en dessous — 4,5:1 pour le texte sur chaque surface, pour le texte posé sur la couleur d'accent, et pour les couleurs de risque à l'intérieur de leurs propres pastilles. Il a rattrapé un rouge d'échec à 2,5:1, sur l'écran qui dépend le plus du rouge, et un gris resté depuis toujours à 2,77:1 dans le thème d'origine.
L'interface fonctionne sur téléphone : la barre d'onglets défile latéralement et le dit, le tableau d'alertes se replie en fiches, les zones tactiles font 44 px, et les champs de formulaire font 16 px pour qu'iOS ne zoome pas quand on les touche.
Quatre listes, dans ce produit, sont fermées — on ne peut rien y ajouter, pas même derrière une approbation. Chacune l'est pour la même raison : un opérateur pointe cette console sur du texte écrit par un attaquant toute la journée, et une liste ouverte est à une consigne près d'être celle de quelqu'un d'autre.
| Liste | Taille | Ce que la fermeture empêche |
|---|---|---|
| Actions | 4 | Isoler temporairement une machine (avec une expiration et une annulation automatique), ouvrir un ticket, escalader, clore en faux positif. Aucune règle de réglage ne peut passer outre cette liste non plus. |
| Outils de l'assistant | 7 en lecture | Le panneau de discussion peut lire la file, une alerte, une chaîne, les règles, les mesures, la santé et l'état de configuration, et n'écrire rien. Une consigne injectée arrive à un modèle qui n'a rien pour y obéir. |
| Noms de secrets | liste nommée | Les deux coffres à clés n'acceptent que des noms figurant sur une liste fixe. Un nom arbitraire transformerait la page de réglages en moyen d'injecter n'importe quelle variable d'environnement dans le processus, PATH compris. |
| Services de réputation | 7 | Le point d'entrée de recherche prend une valeur et un type — jamais une adresse web. Une route qui irait chercher ce qu'on lui tend serait une faille de falsification de requête avec un bouton dessus. |
Une cinquième limite pèse sur les règles de réglage. Une équipe peut déclarer ce qui est normal chez elle — le scanner autorisé, la fenêtre de sauvegarde — et la console refuse une autorisation permanente fondée sur un seul champ d'identité, une mise en sourdine sans expiration, et toute règle sans propriétaire ou sans raison énoncée.
Une installation neuve n'exécute rien. Elle consigne la décision qu'elle aurait prise et poursuit. Sortir de ce mode n'est pas un interrupteur à basculer le premier jour : cela attend un chiffre mesuré sur de vraies alertes passées par les vrais garde-fous.
Deux taux sont mesurés, et ils ne sont jamais additionnés, parce qu'ils répondent à des questions différentes :
Une mesure de répartition, pas de justesse. Un modèle qui qualifierait tout de faux positif obtiendrait ici un score magnifique.
La part des décisions soumises à un humain qu'il a rejetées. C'est celui-ci qui ouvre la porte — c'est le seul substitut à la justesse disponible sans vérité de terrain.
Deux choses à ne pas comparer. Deux appels au même modèle sur la même alerte renvoient 0,88 et 0,91 — les comparer mesure le bruit du modèle, pas quoi que ce soit de votre installation. Et comparer un dossier que le pipeline n'a pas produit — une alerte de test injectée à mi-parcours, un verdict de repli écrit faute de clé — produit des désaccords qui n'en sont pas, et bloque la porte pour rien.
Le comportement par défaut est sûr en échouant. Une configuration absente ne peut pas autoriser une exécution, et seul le mot exact false désactive le mode observation. Une approbation qui expire n'exécute rien — le silence ne vaut jamais accord.
Chaque décision écrit une ligne dans une table à laquelle on ajoute et que l'on ne modifie jamais. Chaque ligne est scellée à la précédente : retirer ou altérer une ligne, où que ce soit dans la chaîne, se voit à la vérification suivante. C'est la seule preuve d'intégrité du produit.
Un vérificateur qui crie au loup est un vérificateur qu'un auditeur cesse de croire — ce qui masquerait une vraie suppression dans le bruit. Une fausse alerte coûte donc ici plus cher que pas d'alerte du tout.
Ce n'est pas théorique. Une passe de charge a trouvé le vérificateur signalant des maillons rompus sur 22 lignes parfaitement saines sur 3 195. La cause : le numéro de ligne était attribué avant le verrou qui ordonne le scellement, si bien que sous charge deux transactions pouvaient sceller dans un ordre en portant des numéros dans l'autre. La chaîne était une liste intacte qui n'était simplement plus dans l'ordre des numéros, et le vérificateur la parcourt par numéro. Corrigé en déplaçant le numéro à l'intérieur du verrou ; revérifié sur ~500 lignes écrites 40 à la fois, sans une seule rupture.
Les lignes scellées avant ce correctif gardent leurs maillons rompus. La table est en ajout seul et immuable par conception, ce qui est le bon compromis : elles ne peuvent pas être réécrites, et le vérificateur continue de les nommer honnêtement.
Exécuté contre un simple docker compose up — base de données, console, analyseur de code, rien d'autre. C'est une passe de qualité sur une machine, pas un banc d'essai publié ; ce qui compte est que ce soit reproductible et que les conditions soient dites.
Cette passe a trouvé huit défauts et ils ont été corrigés. Trois méritent d'être nommés, parce que chacun est une panne qui ressemblait à un succès :
Dit ici pour la même raison que la console le dit : une page qui n'énumère que ce qui marche est un vert qui n'a pas été gagné.
La page d'accueil les évite exprès. Ils apparaissent sur cette page et dans la console : ils sont donc définis une fois, ici.