Aller au contenu
Documentation

Modules

Secrets

Où Ctadel cherche des identifiants exposés (buckets, disques, fonctions, dépôts, images), comment il les masque, comment il vérifie s'ils sont encore valides, et la page Secrets.

Le module de secrets cherche des identifiants (clés d'API, jetons, mots de passe, clés privées) dans ce que vos comptes cloud et vos dépôts contiennent, les enregistre masqués, puis vérifie auprès de l'éditeur si certains sont encore valides. La page « Secrets » présente le résultat.

Où Ctadel cherche

Le même catalogue de règles est appliqué sur chaque source ; une règle ne s'applique qu'aux sources qu'elle déclare.

SourceCe qui est luCe qui est ignoré
Buckets d'objets (S3, Scaleway, OUTSCALE, OVHcloud, Azure Blob, Google Cloud Storage)Les 10 premiers Mo de chaque objet texte ; les PDF, archives (zip, tar, gz, tgz) et documents bureautiques (xlsx, xlsm, docx, pptx, odt, ods) sont téléchargés en entier jusqu'à 50 Mo et leur texte est extrait, y compris les fichiers contenus dans une archiveLes anciens formats binaires doc et xls, une archive tronquée à 50 Mo, un objet au format non lisible : comptés comme « non analysables » sans rendre le résultat incomplet
Disques (copie de volume montée sur une machine de scan)Tout le système de fichiers, fichiers jusqu'à 256 Mo ; les fichiers binaires sont lus par extraction de leurs chaînes de caractèresLes répertoires système (proc, sys, dev, boot, var/log, les données du moteur de conteneurs, les bibliothèques sous usr/lib, les répertoires Windows WinSxS, Installer, etc.), les dépendances tierces à toute profondeur (node_modules, site-packages, vendor, .terraform), les caches du répertoire personnel
Fonctions et conteneurs serverless (AWS, Azure, Google Cloud, Scaleway, OVHcloud)Le code déployé (y compris dist/ et build/, qui sont le code qui tourne), fichiers jusqu'à 10 Mo et 10 000 fichiers par fonction ; les variables d'environnement, lues sous la forme NOM=valeur et sous la forme de la valeur seule ; les couches de l'image d'un conteneurnode_modules, vendor, .git, les fichiers compilés, les médias, les fichiers de verrouillage de dépendances (package-lock.json, go.sum, yarn.lock)
Dépôts Git (à chaque push et pull request)Chaque fichier texte du dépôt cloné, ligne par ligne, fichiers jusqu'à 1 Mo.git, node_modules, vendor, dist, build, .next, .terraform, les images, polices, archives et fichiers .lock
Images de conteneurs (clusters Kubernetes et fonctions déployées depuis une image)Les secrets relevés par le scanner intégré de Trivy dans les couches de l'image ; chaque type Trivy connu est rattaché à la règle Ctadel correspondante, les autres sont classés sous une règle unique « Secret in a container image layer » qui garde l'identifiant Trivy

Familles de règles

Chaque règle est une expression régulière tirée de la documentation de l'éditeur ou du jeu de règles par défaut de Gitleaks, avec une sévérité et un niveau de confiance. Les familles :

FamilleExemples
Clés cloudAWS, Google Cloud, Azure (clés de stockage, SAS, Service Bus, DevOps), Alibaba, DigitalOcean, Heroku
Plateformes Git et registresGitHub, GitLab, Bitbucket, Atlassian, npm, PyPI, NuGet, RubyGems, Docker
PaiementStripe, Square, PayPal Braintree, Plaid, GoCardless
CommunicationSlack, Discord, Twilio, Telegram, SendGrid, Mailgun, Mailchimp, Zoom
IA et MLOpenAI, Anthropic, OpenRouter, Hugging Face, Cohere, Replicate, Pinecone, Groq
CryptographieClés privées PEM, PKCS, clés SSH, JWT, Age, Fernet, validationKey ASP.NET, cpassword GPP
DevOps et observabilitéCircleCI, Buildkite, Datadog, New Relic, Grafana, Sentry, HCP Terraform et Vault, Pulumi, JFrog, Doppler, Okta
Bases de donnéesChaînes JDBC et ODBC, URI Redis, Snowflake, Databricks, PlanetScale, Supabase, mots de passe génériques
SaaS collaboratifsSalesforce, HubSpot, Zendesk, Notion, Trello, Figma, Jira, Airtable
Stockage et CDNDropbox, Cloudflare, Fastly, Shopify, Algolia, Mapbox, Tailscale, 1Password

Trois filtres communs retirent les faux positifs évidents :

  • Les valeurs d'exemple publiées par les éditeurs (AKIAIOSFODNN7EXAMPLE, la clé de l'émulateur Azurite, toute clé AWS qui se termine par EXAMPLE) ne sont jamais rapportées.
  • Quand une règle d'éditeur et une règle générique (fichier d'environnement, valeur entre guillemets, identifiant dans une URL) trouvent le même secret, seule la règle d'éditeur est conservée.
  • Dans le code serverless, une règle de confiance moyenne ne rapporte rien si la valeur a une entropie faible ou contient test, example, mock, dummy, fake, sample, placeholder, changeme et quelques autres marqueurs.

Pour les autres scanners et l'ensemble du catalogue, voir la section Scanners de l'accueil du site.

Masquage

La valeur d'un secret n'est jamais stockée en clair. Chaque constat porte :

  • un extrait masqué : au plus les quatre premiers et les quatre derniers caractères, et seulement quand la valeur fait au moins 16 caractères (20 pour les dépôts Git) ; en dessous, tout est remplacé par des étoiles ;
  • une empreinte SHA-256 de la valeur, la même quelle que soit la source où elle a été trouvée, qui sert à dédupliquer entre sources et à rattacher le verdict de vérification ; pour les clés privées et les fichiers de compte de service, l'empreinte inclut le chemin du fichier ;
  • le chemin du fichier, la ressource qui l'héberge, et pour un dépôt le numéro de ligne, la branche et le commit.

La valeur en clair ne sert qu'à la vérification de validité, à l'intérieur de votre instance, où elle circule chiffrée (AES-256-GCM). Elle n'est jamais stockée et le graphe ne la reçoit jamais.

Vérification de validité

Pour les règles qui déclarent un point de terminaison de vérification chez l'éditeur, Ctadel fait une requête GET authentifiée sur ce point de terminaison, selon le schéma d'authentification de l'éditeur : jeton Bearer, authentification basique (le secret comme nom d'utilisateur, mot de passe vide, le modèle de Stripe) ou en-tête propre à l'éditeur.

VerdictQuand
ACTIVE (« Valide » dans la liste, « Actif » dans le panneau)Réponse 200 ; ou 403, lue comme « clé acceptée mais non autorisée sur ce point de terminaison » ; pour Slack, réponse ok: true ; pour Cloudflare, jeton au statut active
INACTIVE (« Invalide », « Inactif »)Réponse 401 ; pour Slack, invalid_auth, token_revoked, token_expired ; pour Cloudflare, tout autre statut ; pour Datadog, une réponse 403
UNKNOWN (« Inconnu »)Réponse 429 ou inattendue, erreur réseau, schéma inconnu, ou aucune vérification possible

Un éditeur injoignable est réessayé plusieurs fois ; après la dernière tentative le constat est publié UNKNOWN. Le verdict est écrit sur le constat et dans le graphe.

La vérification est active par défaut et se coupe dans « Paramètres », onglet « Général », interrupteur « Validation des secrets » (« Valider les secrets détectés auprès de services externes »).

Score de risque

Chaque constat reçoit un score de 0 à 100 où la validité domine la sévérité : base 80 pour CRITICAL, 60 pour HIGH, 40 pour MEDIUM, 20 pour LOW, multipliée par 1,0 si le secret est ACTIVE, 0,75 si UNKNOWN, 0,15 si INACTIVE ; plus 10 si la ressource qui l'héberge est exposée publiquement, plus 10 si le secret est visible depuis plus de 90 jours. Une clé révoquée reste donc à bas risque quelle que soit sa sévérité. Le panneau de détail montre la décomposition.

La page Secrets

La page « Secrets » (entrée « Secrets » du menu) liste les constats avec un champ « Rechercher un secret par nom, chemin, ressource... », un bouton « Exporter CSV » et un regroupement par « Sévérité », « Type de secret » ou « Ressource ».

ColonneContenu
« Risque »Le score de 0 à 100
« Sévérité »Celle de la règle
« Type »La famille de la règle (cloud, SaaS, base de données...)
« Nom »Le nom de la règle
« Emplacement »Le chemin du fichier, ou ENV:NOM pour une variable d'environnement
« Ressource »Le bucket, le volume, la fonction, l'image ou le dépôt (git://organisation/dépôt)
« Extrait »La valeur masquée
« Validité »« Valide », « Invalide » ou « Inconnu »

Les filtres sont « Sévérité », « Validité », « Type de secret » et « Ressource » (les 30 valeurs les plus fréquentes).

Un clic ouvre le panneau de détail avec trois onglets : « Vue d'ensemble » (règle, ressource affectée, « Preuve » avec l'extrait et le chemin, validité, score), « Rotation » (« Procédure de rotation » pas à pas, « Vérifier s'il est encore actif » avec la commande curl du point de terminaison de l'éditeur quand il existe, et « Nettoyage de l'historique Git » qui rappelle que supprimer le secret dans un commit ultérieur ne l'invalide pas) et « Historique ».

La page Secrets avec la liste des constats, leur score, leur validité et les filtres.
Figure 1. Figure 1. La page « Secrets » sur l'instance de démonstration. Données de démonstration.

Secrets dans les pull requests

Sur un dépôt GitHub, chaque pull request reçoit un commentaire listant les secrets du dépôt (règle, sévérité, fichier, ligne) et un statut de commit ctadel/secrets que votre protection de branche peut exiger. Le statut échoue selon le seuil réglé sur le dépôt dans « Paramètres » (« Bloquer la PR en cas d'échec », « Bloquer si des détections ≥ » pour la famille « Secrets »). Une entrée ignores: du fichier .ctadel.yaml du dépôt exclut un faux positif assumé (une fausse clé de jeu de test) : il reste stocké, marqué ignoré, et ne compte plus pour le statut. Voir Infrastructure as code.

Limites

  • La vérification de validité ne porte que sur les règles qui déclarent un point de terminaison chez l'éditeur, soit une partie du catalogue ; les autres restent « Inconnu ». Les clés privées, les mots de passe de bases et les jetons génériques ne sont jamais vérifiés.
  • Les secrets trouvés dans un dépôt Git ne sont pas envoyés en vérification : le scanner de dépôts ne conserve pas la valeur. Leur validité reste « Inconnu », et le commentaire de pull request l'affiche ainsi.
  • Un secret trouvé dans une couche d'image par Trivy est rapporté avec le type de Trivy ; il n'est pas vérifié.
  • Les buckets : seuls les 10 premiers Mo d'un objet texte sont lus ; un secret placé au-delà n'est pas vu. Les formats doc et xls anciens ne sont pas lus. Un objet illisible pour cause réseau ou droits rend le scan incomplet, et les constats précédents de ce bucket ne sont pas fermés.
  • Les disques : un fichier de plus de 256 Mo est compté comme ignoré. Les répertoires système et de dépendances listés plus haut ne sont pas lus. Le code serverless ignore un fichier de plus de 10 Mo et s'arrête à 10 000 fichiers ; le résultat est alors marqué incomplet et ne ferme aucun constat antérieur.
  • Dans un dépôt, un fichier de plus de 1 Mo n'est pas lu, et une ligne de plus de 1 Mo arrête la lecture du fichier.
  • Les filtres d'entropie et de jeton de test ne s'appliquent qu'au code serverless, pas aux buckets, disques ni dépôts.
  • Le commentaire et le statut de pull request existent sur GitHub seulement ; sur GitLab, les constats sont enregistrés mais la merge request ne reçoit ni commentaire ni statut.
  • Une réponse 403 de l'éditeur est lue comme « valide » sauf pour Datadog ; pour un éditeur qui répond 403 à une clé invalide, le verdict est faux.