Carte de propriété de la sécurité
Aperçu
Construire un graphe bipartite de personnes et de fichiers à partir de l'historique git, puis calculer le risque de propriété et exporter les artefacts du graphe pour Neo4j/Gephi. Construire également un graphe de co-changement de fichiers (similarité de Jaccard sur les commits partagés) pour regrouper les fichiers selon la façon dont ils évoluent ensemble tout en ignorant les commits volumineux et bruyants.
Prérequis
- Python 3
networkx(requis ; la détection de communautés est activée par défaut)
Installez avec :
pip install networkx
Flux de travail
- Définir la portée du dépôt et la fenêtre de temps (optionnel
--since/--until). - Décider des règles de sensibilité (utiliser les valeurs par défaut ou fournir une configuration CSV).
- Construire la carte de propriété avec
scripts/run_ownership_map.py(le graphe de co-changement est activé par défaut ; utilisez--cochange-max-filespour ignorer les commits supernœud). - Les communautés sont calculées par défaut ; la sortie graphml est optionnelle (
--graphml). - Interroger les résultats avec
scripts/query_ownership.pypour les tranches JSON bornées. - Persister et visualiser (voir
references/neo4j-import.md).
Par défaut, le graphe de co-changement ignore les fichiers « glu » courants (lockfiles, .github/*, configuration d'éditeur) afin que les regroupements reflètent le mouvement réel du code au lieu des modifications d'infrastructure partagée. Remplacer avec --cochange-exclude ou --no-default-cochange-excludes. Les commits Dependabot sont exclus par défaut ; remplacer avec --no-default-author-excludes ou ajouter des modèles via --author-exclude-regex.
Si vous souhaitez exclure le glu de construction Linux comme Kbuild du regroupement de co-changement, passez :
python skills/skills/security-ownership-map/scripts/run_ownership_map.py \
--repo /path/to/linux \
--out ownership-map-out \
--cochange-exclude "**/Kbuild"
Démarrage rapide
Exécutez à partir de la racine du dépôt :
python skills/skills/security-ownership-map/scripts/run_ownership_map.py \
--repo . \
--out ownership-map-out \
--since "12 months ago" \
--emit-commits
Valeurs par défaut : identité de l'auteur, date de l'auteur et commits de fusion exclus. Utilisez --identity committer, --date-field committer, ou --include-merges si nécessaire.
Exemple (remplacer les exclusions de co-changement) :
python skills/skills/security-ownership-map/scripts/run_ownership_map.py \
--repo . \
--out ownership-map-out \
--cochange-exclude "**/Cargo.lock" \
--cochange-exclude "**/.github/**" \
--no-default-cochange-excludes
Les communautés sont calculées par défaut. Pour désactiver :
python skills/skills/security-ownership-map/scripts/run_ownership_map.py \
--repo . \
--out ownership-map-out \
--no-communities
Règles de sensibilité
Par défaut, le script signale les chemins d'authentification/crypto/secret courants. Remplacer en fournissant un fichier CSV :
# pattern,tag,weight
**/auth/**,auth,1.0
**/crypto/**,crypto,1.0
**/*.pem,secrets,1.0
Utilisez-le avec --sensitive-config path/to/sensitive.csv.
Artefacts de sortie
ownership-map-out/ contient :
people.csv(nœuds : personnes)files.csv(nœuds : fichiers)edges.csv(arêtes : touches)cochange_edges.csv(arêtes de co-changement fichier-à-fichier avec poids de Jaccard ; omis avec--no-cochange)summary.json(conclusions de propriété de sécurité)commits.jsonl(optionnel, si--emit-commits)communities.json(calculé par défaut à partir des arêtes de co-changement si disponibles ; inclutmaintainerspar communauté ; désactiver avec--no-communities)cochange.graph.json(JSON de lien-nœud NetworkX aveccommunity_id+community_maintainers; revenir àownership.graph.jsonsi aucune arête de co-changement)ownership.graphml/cochange.graphml(optionnel, si--graphml)
people.csv inclut la détection du fuseau horaire basée sur les décalages de commit de l'auteur : primary_tz_offset, primary_tz_minutes, et timezone_offsets.
Assistant de requête LLM
Utilisez scripts/query_ownership.py pour retourner de petites tranches JSON bornées sans charger le graphe complet en contexte.
Exemples :
python skills/skills/security-ownership-map/scripts/query_ownership.py --data-dir ownership-map-out people --limit 10
python skills/skills/security-ownership-map/scripts/query_ownership.py --data-dir ownership-map-out files --tag auth --bus-factor-max 1
python skills/skills/security-ownership-map/scripts/query_ownership.py --data-dir ownership-map-out person --person alice@corp --limit 10
python skills/skills/security-ownership-map/scripts/query_ownership.py --data-dir ownership-map-out file --file crypto/tls
python skills/skills/security-ownership-map/scripts/query_ownership.py --data-dir ownership-map-out cochange --file crypto/tls --limit 10
python skills/skills/security-ownership-map/scripts/query_ownership.py --data-dir ownership-map-out summary --section orphaned_sensitive_code
python skills/skills/security-ownership-map/scripts/query_ownership.py --data-dir ownership-map-out community --id 3
Utilisez --community-top-owners 5 (par défaut) pour contrôler le nombre de mainteneurs stockés par communauté.
Requêtes de sécurité de base
Exécutez celles-ci pour répondre aux questions courantes de propriété de sécurité avec une sortie bornée :
# Code sensible orphelin (stale + bus factor faible)
python skills/skills/security-ownership-map/scripts/query_ownership.py --data-dir ownership-map-out summary --section orphaned_sensitive_code
# Propriétaires cachés pour les tags sensibles
python skills/skills/security-ownership-map/scripts/query_ownership.py --data-dir ownership-map-out summary --section hidden_owners
# Points chauds sensibles avec bus factor faible
python skills/skills/security-ownership-map/scripts/query_ownership.py --data-dir ownership-map-out summary --section bus_factor_hotspots
# Fichiers auth/crypto avec bus factor <= 1
python skills/skills/security-ownership-map/scripts/query_ownership.py --data-dir ownership-map-out files --tag auth --bus-factor-max 1
python skills/skills/security-ownership-map/scripts/query_ownership.py --data-dir ownership-map-out files --tag crypto --bus-factor-max 1
# Qui touche le plus au code sensible
python skills/skills/security-ownership-map/scripts/query_ownership.py --data-dir ownership-map-out people --sort sensitive_touches --limit 10
# Voisins de co-changement (indices de regroupement pour déviation de propriété)
python skills/skills/security-ownership-map/scripts/query_ownership.py --data-dir ownership-map-out cochange --file path/to/file --min-jaccard 0.05 --limit 20
# Mainteneurs de communauté (pour un regroupement)
python skills/skills/security-ownership-map/scripts/query_ownership.py --data-dir ownership-map-out community --id 3
# Mainteneurs mensuels pour la communauté contenant un fichier
python skills/skills/security-ownership-map/scripts/community_maintainers.py \
--data-dir ownership-map-out \
--file network/card.c \
--since 2025-01-01 \
--top 5
# Compartiments trimestriels au lieu de mensuels
python skills/skills/security-ownership-map/scripts/community_maintainers.py \
--data-dir ownership-map-out \
--file network/card.c \
--since 2025-01-01 \
--bucket quarter \
--top 5
Remarques :
- Les touches consistent par défaut en un commit créé (non par fichier). Utilisez
--touch-mode filepour compter les touches par fichier. - Utilisez
--window-days 90ou--weight recency --half-life-days 180pour lisser l'agitation. - Filtrez les bots avec
--ignore-author-regex '(bot|dependabot)'. - Utilisez
--min-share 0.1pour afficher uniquement les mainteneurs stables. - Utilisez
--bucket quarterpour les regroupements de trimestres calendaires. - Utilisez
--identity committerou--date-field committerpour passer de l'attribution de l'auteur. - Utilisez
--include-mergespour inclure les commits de fusion (exclus par défaut).
Format de résumé (par défaut)
Utilisez cette structure, ajoutez des champs si nécessaire :
{
"orphaned_sensitive_code": [
{
"path": "crypto/tls/handshake.rs",
"last_security_touch": "2023-03-12T18:10:04+00:00",
"bus_factor": 1
}
],
"hidden_owners": [
{
"person": "alice@corp",
"controls": "63% of auth code"
}
]
}
Persistance du graphe
Utilisez references/neo4j-import.md lorsque vous devez charger les CSV dans Neo4j. Il comprend des contraintes, des Cypher d'importation et des conseils de visualisation.
Remarques
bus_factor_hotspotsdanssummary.jsonrépertorie les fichiers sensibles avec bus factor faible ;orphaned_sensitive_codeest le sous-ensemble stale.- Si
git logest trop volumineux, réduisez avec--sinceou--until. - Comparez
summary.jsonpar rapport à CODEOWNERS pour mettre en évidence la déviation de propriété.