Cartographie de la sécurité en propriété
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 de graphe pour Neo4j/Gephi. Construire également un graphe de co-modification de fichiers (similarité de Jaccard sur les commits partagés) pour regrouper les fichiers par la façon dont ils évoluent ensemble, 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)
Installation :
pip install networkx
Flux de travail
- Délimiter le dépôt et la fenêtre de temps (options facultatives
--since/--until). - Décider des règles de sensibilité (utiliser les valeurs par défaut ou fournir un fichier de configuration CSV).
- Construire la cartographie de propriété avec
scripts/run_ownership_map.py(le graphe de co-modification est activé par défaut ; utiliser--cochange-max-filespour ignorer les commits supernœuds). - Les communautés sont calculées par défaut ; la sortie graphml est facultative (
--graphml). - Interroger les sorties avec
scripts/query_ownership.pypour les tranches JSON délimitées. - Persister et visualiser (voir
references/neo4j-import.md).
Par défaut, le graphe de co-modification ignore les fichiers « glue » communs (fichiers de verrouillage, .github/*, config d'éditeur) afin que les clusters reflètent le mouvement réel du code plutôt que les modifications d'infra 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 motifs via --author-exclude-regex.
Si vous voulez exclure le glue de compilation Linux comme Kbuild du clustering de co-modification, 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 depuis 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. Utiliser --identity committer, --date-field committer ou --include-merges si nécessaire.
Exemple (remplacer les exclusions de co-modification) :
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 auth/crypto/secret courants. Remplacer en fournissant un fichier CSV :
# pattern,tag,weight
**/auth/**,auth,1.0
**/crypto/**,crypto,1.0
**/*.pem,secrets,1.0
Utiliser 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-modification fichier à fichier avec poids de Jaccard ; omis avec--no-cochange)summary.json(résultats de sécurité en propriété)commits.jsonl(facultatif, si--emit-commits)communities.json(calculé par défaut à partir des arêtes de co-modification quand disponibles ; inclutmaintainerspar communauté ; désactiver avec--no-communities)cochange.graph.json(JSON node-link NetworkX aveccommunity_id+community_maintainers; retombe àownership.graph.jsons'il n'y a pas d'arêtes de co-modification)ownership.graphml/cochange.graphml(facultatif, si--graphml)
people.csv inclut la détection de fuseau horaire basée sur les décalages de commit d'auteur : primary_tz_offset, primary_tz_minutes et timezone_offsets.
Aide pour interrogation LLM
Utiliser scripts/query_ownership.py pour retourner de petites tranches JSON délimité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
Utiliser --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 à des questions courantes de sécurité en propriété avec une sortie délimitée :
# Code sensible orphelin (obsolète + 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 souvent 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-modification (indices de regroupement pour dérive 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 cluster)
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
# Buckets 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 par défaut sont un commit créé (pas par fichier). Utiliser
--touch-mode filepour compter les touches par fichier. - Utiliser
--window-days 90ou--weight recency --half-life-days 180pour lisser le churn. - Filtrer les bots avec
--ignore-author-regex '(bot|dependabot)'. - Utiliser
--min-share 0.1pour afficher les mainteneurs stables uniquement. - Utiliser
--bucket quarterpour les regroupements de trimestre calendaire. - Utiliser
--identity committerou--date-field committerpour basculer de l'attribution d'auteur. - Utiliser
--include-mergespour inclure les commits de fusion (exclus par défaut).
Format de résumé (par défaut)
Utiliser cette structure, ajouter 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
Utiliser references/neo4j-import.md quand vous avez besoin de charger les CSVs dans Neo4j. Il inclut les contraintes, les Cypher d'import et les conseils de visualisation.
Remarques
bus_factor_hotspotsdanssummary.jsonliste les fichiers sensibles avec un bus factor faible ;orphaned_sensitive_codeest le sous-ensemble obsolète.- Si
git logest trop volumineux, affiner avec--sinceou--until. - Comparer
summary.jsonavec CODEOWNERS pour mettre en évidence la dérive de propriété.