Format NDJSON neutre vis-à-vis des fournisseurs pour les graphes d'attaque, avec taxonomie des nœuds/arêtes, mappages AWS/GCP/Azure, règles de dérivation et une base de données d'exposition pour l'outillage de sécurité offensive.
Un graphe d'attaque que vous pouvez réellement transmettre à quelqu'un d'autre.
Chaque produit de sécurité basé sur les graphes garde votre graphe d'attaque enfermé dans un stockage propriétaire. Vous ne pouvez pas l'exporter, comparer deux scans, le mettre sous contrôle de version, ou l'interroger avec autre chose que l'interface du fournisseur. Lorsque la mission se termine, le graphe s'en va avec elle.
RAGE est un format de fichier neutre vis-à-vis des fournisseurs pour les graphes de sécurité offensive, accompagné du corpus ouvert qui lui donne du sens : la taxonomie des nœuds et des arêtes, les mappings AWS/GCP/Azure et les recettes de collecte, ainsi que les règles de dérivation des arêtes. Un fichier. N'importe quel langage. Prêt à l'emploi.
Statut : ébauche précoce (spec_version: 0.1). Pas encore stable ; retours et pull
requests sont les bienvenus.
Un graphe RAGE est un unique fichier NDJSON (un objet JSON par ligne). La ligne 1 est le
manifeste ; chaque autre ligne est un enregistrement étiqueté avec kind.
{"kind":"manifest","spec_version":"0.1"}
{"kind":"node","node_id":"gcp|proj-a|gcp:iam:service-account|sa-deploy","node_type":"ServiceAccount"}
{"kind":"node","node_id":"gcp|proj-a|gcp:iam:service-account|sa-admin","node_type":"ServiceAccount"}
{"kind":"node","node_id":"gcp|proj-a|gcp:storage:bucket|bucket-crown","node_type":"ObjectStorage"}
{"kind":"edge","type":"CanImpersonate","source":"gcp|proj-a|…|sa-deploy","target":"gcp|proj-a|…|sa-admin"}
{"kind":"edge","type":"CanReadData","source":"gcp|proj-a|…|sa-admin","target":"gcp|proj-a|…|bucket-crown"}
{"kind":"finding","resource_id":"gcp|proj-a|…|bucket-crown","severity":"critical"}
Une chaîne à deux sauts qui respecte la taxonomie : sa-deploy peut usurper l'identité de
sa-admin (une arête d'identité à identité), qui peut lire le bucket aux joyaux de la
couronne (identité vers stockage).
Lisez-le en trois lignes dans n'importe quel langage :
for line in open("graph.rage.ndjson"): rec = json.loads(line) # switch on rec["kind"]
jq 'select(.kind=="edge" and .type=="CanImpersonate")' graph.rage.ndjson
| kind | champs requis | objectif |
|---|---|---|
manifest | spec_version | ligne 1 : version + compteurs/portée/producteur optionnels |
node | node_id, node_type | une ressource ou une identité |
edge | source, target, type | une capacité ou une relation |
fact | fact_id | une observation normalisée à partir de laquelle le graphe a été construit |
evidence | evidence_id, content_hash | reçu inviolable (une opération d'API/collecte) |
finding | resource_id, severity | une exposition |
surface / path | - | types d'extension optionnels |
La chaîne de provenance est evidence (API) puis fact puis edge/finding, reliés par
des ids. node_type et le type d'arête proviennent des registres ouverts dans
vocab/. Tout le reste est un enrichissement optionnel. Voir
spec/format.md.
Le format n'est que la moitié de RAGE. L'autre moitié est le corpus partagé qui donne du
sens aux types, afin que deux outils indépendants s'accordent sur ce qu'est
CanImpersonate et où une credential peut fuiter :
vocab/) : 105 types de nœuds dans 10 classes, 80 types d'arêtes dans 9 catégories.providers/) : 219 types de ressources natives à travers AWS, GCP et Azure, chacun mappé à un type de nœud générique avec les appels qui l'énumèrent.rules/) : le contrat dans rules/derivation.json plus 2 400+ règles exécutables match/where/emit pour la façon dont les arêtes sont dérivées.exposure-db/) : 1 049 sites de fuite de credentials mappés, chacun lié à l'arête RAGE qu'il émet et à la recette qui le lit.Le corpus entier, lisible par un humain, se trouve dans TAXONOMY.md.
RAGE est conçu pour que n'importe qui puisse le produire ou le consommer. Le format est le contrat ; les outils sont interchangeables, et la liste est ouverte.
RAGE est le format, Thunderstorm le produit, Blaze l'explore.
| implémentation | rôle | où |
|---|---|---|
| Thunderstorm | producteur : collecteur cloud en lecture seule + moteur de dérivation | github.com/ustayready/thunderstorm |
| votre outil ici | producteur ou consommateur | émettez ou lisez .rage.ndjson et il interopère |
Tout ce qui lit ou écrit le format parle RAGE. Les producteurs et moteurs conformes se
conforment aux registres de ce dépôt ; RAGE ne dépend d'aucun d'entre eux. Voir
COMPATIBILITY.md pour la façon dont les implémentations s'épinglent à
une spec_version.
spec/format.md - le format de transmission (enregistrements, grammaire de node_id, .rage.zip, portée).spec/edges.md - sémantique des arêtes : direction/traversée, state, weight/walkable, canonicalisation.spec/rules.md - sémantique d'évaluation des règles : point fixe, fusion d'état, le catalogue de fonctions.schemas/ - JSON Schema pour les 8 types d'enregistrements.vocab/ - node-types.json + edge-types.json + conditions.json.rules/derivation.json - le contrat de dérivation des arêtes (par arête : conditions + permissions/déclencheurs par cloud).rules/{derived,explicit}/** - le corpus exécutable de 2 400+ règles match/where/emit.providers/{aws,gcp,azure}.json - mappings natif vers générique + recettes de nœuds + recettes de faits.exposure-db/{aws,gcp,azure}.json + vocabulary.json - l'Exposure DB (1 049 sites de fuite).TAXONOMY.md - le corpus entier, lisible par un humain (généré à partir des registres ci-dessus).tools/rage_engine.py - le moteur de règles de référence : exécute le corpus de règles dérivées sur un graphe jusqu'à un point fixe.validate/ - validateurs d'enregistrements (JSON Schema complet), de registres, de chaînes de permissions et de corpus de règles.examples/ - un graphe valide minimal exerçant les 8 types d'enregistrements.python3 -m venv .venv && ./.venv/bin/pip install -r requirements.txt
./.venv/bin/python validate/rage_validate.py examples/minimal.rage.ndjson # full JSON Schema + refs
./.venv/bin/python validate/check_registries.py # registry integrity
./.venv/bin/python validate/check_rules.py # rule corpus vs vocab
La CI exécute tout ce qui précède plus une barrière anti-dérive gen_taxonomy.
Apache-2.0 (voir LICENSE).