Aller au contenu
Sécurité medium

GUAC : visualiser et interroger votre supply chain

20 min de lecture

Vous avez généré des SBOM pour documenter vos composants logiciels. Vous avez des scans de vulnérabilités qui s'accumulent. Vous avez peut-être même des attestations SLSA pour prouver la provenance de vos builds. Mais quand une nouvelle CVE critique tombe un vendredi soir, êtes-vous capable de répondre rapidement à cette question : "Quels sont tous les artefacts en production qui utilisent log4j 2.14.0 ?"

Si la réponse implique de fouiller manuellement dans des dizaines de fichiers JSON, vous avez besoin de GUAC.

GUAC (prononcé "gouac", comme la sauce mexicaine) signifie Graph for Understanding Artifact Composition. C'est un outil open source qui agrège toutes vos métadonnées de sécurité supply chain dans un graphe de connaissances interrogeable.

Les outils traditionnels traitent les données de sécurité en silos :

  • Un SBOM par image → fichier JSON isolé
  • Un scan Trivy → rapport séparé
  • Une attestation SLSA → document distinct

GUAC connecte toutes ces informations pour révéler les relations cachées. Par exemple : "Cette CVE affecte ce package → qui est inclus dans cette image → qui est déployée dans ces 15 services".

Sans GUACAvec GUAC
500 fichiers SBOM à parcourir manuellementUne requête pour tout le parc
"Est-ce qu'on utilise log4j ?" → plusieurs heuresRéponse en quelques secondes
Impact d'une CVE 0-day ? → "on ne sait pas"Graphe des dépendances transitives
Corrélation CVE ↔ SBOM ↔ SLSA → tableur ExcelRelations automatiques dans le graphe

Avant de passer à l'installation, comprenons comment GUAC fonctionne. Cette compréhension vous aidera à diagnostiquer les problèmes et à optimiser votre déploiement.

Architecture GUAC : Collectors, Ingestor, Assembler, CollectSub, Certifiers, GraphQL Server et Visualizer

ComposantRôle
CollectorsRécupèrent les documents (SBOM, attestations) depuis diverses sources
IngestorParse les documents et les traduit dans le modèle GUAC
AssemblerStocke les données dans la base de données graphe
CollectSubCoordonne les demandes d'informations supplémentaires
CertifiersEnrichissent automatiquement avec des données externes (CVE, licences)
GraphQL ServerExpose les données via une API interrogeable

Avant d'installer GUAC, assurez-vous d'avoir :

  • Docker et Docker Compose (v2.x recommandé)
  • Au moins 4 Go de RAM disponibles pour les conteneurs
  • Des SBOM à ingérer (sinon, GUAC sera vide et inutile)
  • Optionnel : PostgreSQL 14+ si vous voulez la persistance

Cette méthode utilise le backend in-memory. Idéale pour découvrir GUAC, mais les données sont perdues au redémarrage.

Fenêtre de terminal
# Cloner le dépôt officiel
git clone https://github.com/guacsec/guac.git
cd guac
# Démarrer tous les services
docker compose up -d

Services démarrés :

ServicePortDescription
GraphQL API8080Point d'entrée pour les requêtes
Visualizer3000Interface web d'exploration
NATS4222Bus de messages interne
Collector-Écoute les nouvelles données

Vérification :

Fenêtre de terminal
# Vérifier que tous les conteneurs tournent
docker compose ps
# Tester l'API GraphQL
curl -s http://localhost:8080/query \
-H "Content-Type: application/json" \
-d '{"query": "{ packages { type } }"}'

Vous devriez obtenir une réponse JSON (probablement vide si aucun SBOM n'a été ingéré).

GUAC organise les informations dans un graphe composé de nœuds (entités) et d'arêtes (relations). Comprendre ce modèle est essentiel pour écrire des requêtes efficaces.

Type de nœudCe que c'estExemple concret
PackageUn composant logiciel identifié par un pURLpkg:npm/lodash@4.17.21
SourceUn dépôt de code sourcegit+https://github.com/lodash/lodash
ArtifactUn fichier binaire ou une imagesha256:abc123... (image Docker)
VulnerabilityUne faille de sécurité connueCVE-2021-44228 (Log4Shell)
BuilderUn système de buildhttps://github.com/actions

Ces relations sont les arêtes du graphe, et ce sont elles qui font la valeur de GUAC : sans arêtes, vous n'auriez qu'une base de nœuds isolés, comme vos fichiers JSON de départ. La plus stratégique en réponse à incident est IsDependencyOf, car c'est elle qui remonte les dépendances transitives, ces composants que vous n'avez jamais installés directement mais qu'une de vos dépendances a tirés. Retenez le sens de lecture : la relation se lit de la dépendance vers ce qui la consomme, c'est en la parcourant à l'envers qu'une requête répond à « qui utilise ce paquet vulnérable ».

RelationCe qu'elle signifieUtilité
IsDependencyOfA est une dépendance de BTracer les dépendances transitives
HasSBOML'artefact possède un SBOMVérifier la couverture SBOM
CertifyVulnLe package a une vulnérabilité connueIdentifier les composants vulnérables
HasSlsaL'artefact a une attestation SLSAVérifier la provenance
HasSourceAtLe package provient de ce dépôtTracer l'origine du code
IsOccurrenceOfCet artefact est une instance de ce packageLier binaires et packages

Voici comment ces relations forment un graphe pour une image Docker :

Graphe GUAC montrant les relations entre Artifact, SBOM, SLSA, Package et CVE

Un GUAC vide est inutile. Voyons comment alimenter le graphe avec vos données de sécurité.

  1. Générer un SBOM (si vous n'en avez pas déjà)

    Fenêtre de terminal
    # Avec Syft
    syft myimage:latest -o cyclonedx-json > sbom.json
  2. Ingérer le SBOM dans GUAC

    Fenêtre de terminal
    # Avec guacone
    guacone collect files sbom.json

    Sortie attendue :

    {"level":"info","msg":"Collecting files from: sbom.json"}
    {"level":"info","msg":"Successfully ingested 1 document(s)"}
  3. Vérifier l'ingestion

    Ouvrez le Visualizer sur http://localhost:3000 et recherchez votre package.

GUAC peut extraire automatiquement les SBOM attachés aux images OCI :

Fenêtre de terminal
# Ingérer depuis GitHub Container Registry
guacone collect oci ghcr.io/mon-org/mon-image:v1.0.0
# Ingérer depuis Docker Hub
guacone collect oci docker.io/library/nginx:latest

Le certifier OSV surveille automatiquement les nouveaux packages et vérifie s'ils ont des vulnérabilités connues dans la base OSV.dev :

Fenêtre de terminal
# Lancer le certifier OSV (s'exécute en continu)
guacone certifier osv

Une attestation SLSA décrit la provenance d'un artefact : quel système de build l'a produit, à partir de quelle source, avec quels paramètres. Ingérée dans GUAC, elle alimente la relation HasSlsa et permet ensuite de répondre à « cet artefact a-t-il été construit par un pipeline de confiance ? », une question distincte de « contient-il une CVE ? ». La commande est la même que pour un SBOM, guacone collect files détecte le type de document. Le format attendu est le in-toto signé, souvent une ligne JSON par attestation, d'où l'extension .intoto.jsonl.

Fenêtre de terminal
# Ingérer une attestation de provenance signée
guacone collect files provenance.intoto.jsonl

GUAC expose une API GraphQL. Vous pouvez l'interroger via :

Trouver les vulnérabilités d'un package :

Fenêtre de terminal
guacone query vuln "pkg:npm/lodash@4.17.20"

Sortie :

+-------------+-----------+---------------------------------------+
| NODE TYPE | NODE ID | ADDITIONAL INFORMATION |
+-------------+-----------+---------------------------------------+
| certifyVuln | 148776 | vulnerability ID: ghsa-35jh-r3h4-6jhm |
| certifyVuln | 148777 | vulnerability ID: cve-2021-23337 |
+-------------+-----------+---------------------------------------+

Obtenir tout ce qu'on sait sur un package :

Fenêtre de terminal
guacone query known "pkg:golang/github.com/prometheus/client_golang@1.11.0"

Pour des requêtes complexes, utilisez directement l'API GraphQL.

Exemple 1 : Tous les packages vulnérables dans le graphe

query TousLesPackagesVulnerables {
CertifyVuln(certifyVulnSpec: {}) {
package {
type
namespaces {
namespace
names {
name
versions {
version
}
}
}
}
vulnerability {
vulnerabilityIDs {
vulnerabilityID
}
}
}
}

Exécution via cURL :

Fenêtre de terminal
curl -s http://localhost:8080/query \
-H "Content-Type: application/json" \
-d '{
"query": "{ CertifyVuln { package { type namespaces { names { name versions { version } } } } vulnerability { vulnerabilityIDs { vulnerabilityID } } } }"
}' | jq .

Exemple 2 : Impact d'une CVE spécifique

"Quels artefacts sont impactés par Log4Shell ?"

query ImpactLog4Shell {
CertifyVuln(
certifyVulnSpec: {
vulnerability: { vulnerabilityID: "cve-2021-44228" }
}
) {
package {
namespaces {
names {
name
versions {
version
}
}
}
}
}
}

Exemple 3 : Packages sans SBOM

"Quels packages n'ont pas de SBOM attaché ?" (pour identifier les trous de couverture)

query PackagesSansSBOM {
packages(pkgSpec: {}) {
namespaces {
names {
name
versions {
version
# Si ce package n'apparaît pas dans HasSBOM, c'est qu'il manque
}
}
}
}
}

Scénario : Une nouvelle CVE critique (type Log4Shell) est publiée un vendredi à 17h. Vous devez identifier rapidement tous les systèmes impactés.

  1. Identifier le package concerné

    La CVE mentionne log4j-core versions 2.0 à 2.14.1. Le pURL est : pkg:maven/org.apache.logging.log4j/log4j-core

  2. Requêter GUAC

    Fenêtre de terminal
    guacone query vuln "pkg:maven/org.apache.logging.log4j/log4j-core"
  3. Analyser les résultats

    GUAC retourne la liste de tous les artefacts qui utilisent log4j (directement ou transitivement).

  4. Prioriser la remédiation

    • Production critique → patch immédiat
    • Environnements de dev → planifier
    • Dépendances transitives → évaluer le risque réel

Temps de réponse : Quelques minutes au lieu de plusieurs heures.

Le Cyber Resilience Act européen et NIS2 imposent :

  • Inventaire des composants logiciels → SBOM dans GUAC
  • Traçabilité des artefacts → Attestations SLSA dans GUAC
  • Gestion des vulnérabilités → Certifiers OSV dans GUAC

Requête d'audit : "Prouvez que vous savez ce qui compose votre logiciel"

Fenêtre de terminal
# Export de tous les packages connus
guacone query known --all > inventaire-complet.json

Avant d'ajouter une nouvelle dépendance, interrogez GUAC :

query EvaluerDependance {
# Score OpenSSF Scorecard
scorecards(scorecardSpec: { source: { name: "github.com/nouveau/projet" } }) {
aggregateScore
checks {
check
score
}
}
# Historique de vulnérabilités
CertifyVuln(
certifyVulnSpec: { package: { name: "nouveau-projet" } }
) {
vulnerability {
vulnerabilityIDs {
vulnerabilityID
}
}
}
}

GUAC s'intègre dans votre écosystème existant :

OutilType d'intégrationDirection
Syft / TrivyGénérateurs SBOMSBOM → GUAC
CosignSignatures et attestationsAttestations → GUAC
GrypeScanner de vulnérabilitésRésultats scan → GUAC
Dependency-TrackGestion vulnérabilitésBidirectionnel
GitHub ActionsCI/CDIngestion automatique
HarborRegistry OCIPull SBOM automatique

Le vrai gain de GUAC vient de l'alimentation continue : un SBOM généré à chaque push sur main, poussé automatiquement dans le graphe, garde l'inventaire aligné sur ce qui tourne réellement. Le workflow ci-dessous applique le moindre privilège attendu sur le site : permissions: {} au niveau global neutralise le jeton par défaut, chaque job ne réclame que ce dont il a besoin (contents: read pour lire le code), et persist-credentials: false empêche le checkout de laisser traîner le jeton Git dans le runner. Les deux actions sont épinglées par SHA commenté avec leur version, seule protection contre le redéploiement silencieux d'un tag mobile.

.github/workflows/supply-chain.yml
name: Supply Chain Security
on:
push:
branches: [main]
permissions: {}
jobs:
sbom-to-guac:
runs-on: ubuntu-24.04
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Generate SBOM
uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0
with:
format: cyclonedx-json
output-file: sbom.json
- name: Push to GUAC
run: |
curl -X POST http://guac.internal:8080/collect/files \
-F "file=@sbom.json"

La plupart des blocages de GUAC ne sont pas des erreurs mais des silences trompeurs : le graphe répond sans jamais planter, il répond juste vide. Le réflexe de diagnostic est donc de distinguer trois couches, dans l'ordre : les données ont-elles été ingérées (guacone collect), les certifiers tournent-ils pour enrichir en vulnérabilités (guacone certifier osv), et les conteneurs sont-ils tous debout (docker compose ps). Le tableau ci-dessous suit cet ordre, du plus fréquent au plus structurel, et docker compose logs reste l'arbitre quand le symptôme reste ambigu.

SymptômeCause probableSolution
"No packages found"SBOM pas encore ingéréVérifier guacone collect et les logs
Visualizer ne répond pasPort 3000 non exposéVérifier docker compose ps
Pas de vulnérabilitésCertifier OSV non lancéLancer guacone certifier osv
Ingestion lenteBackend in-memory saturéPasser à PostgreSQL
"Connection refused" GraphQLAPI pas démarréeVérifier le conteneur guac-graphql
  1. GUAC = graphe de connaissances qui connecte SBOM, vulnérabilités, attestations SLSA et dépendances

  2. Une requête remplace des heures de recherche manuelle lors d'incidents de sécurité

  3. Les certifiers enrichissent automatiquement le graphe avec les données OSV, Scorecard et licences

  4. PostgreSQL en production : le backend in-memory est uniquement pour les démos

  5. L'alimentation est clé : un GUAC vide est inutile. Intégrez la génération et l'ingestion SBOM dans votre CI/CD

  6. GraphQL pour les requêtes avancées : la CLI couvre 80% des besoins, mais GraphQL débloque les cas complexes

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn