数据分析

security-ownership-map

试用

把 git 历史变成人-文件所有权图谱,并给出巴士因子与敏感代码风险结论。

它能做什么

读取仓库的 git log,构建人员与文件的双部图,同时基于共同提交的 Jaccard 相似度生成文件共变图。敏感路径可用内置的 auth/crypto/secret 规则识别,也可通过 CSV 自定义;在此基础上计算巴士因子、孤立敏感代码、隐藏所有者与所有权社区。结果输出到指定目录,包含 people.csv、files.csv、edges.csv、cochange_edges.csv、summary.json、communities.json 以及 NetworkX node-link JSON,可选生成 GraphML 与提交记录。

什么时候用它

  • 找出长期无人维护且只有一个人负责的敏感文件
  • 核对 CODEOWNERS 与实际提交 auth/crypto 代码的人是否一致
  • 把所有权 CSV 导入 Neo4j 或 Gephi 做风险图谱
  • 按共变关系聚类文件,发现模块内的所有权漂移

技能文档

Security Ownership Map

Overview

Build a bipartite graph of people and files from git history, then compute ownership risk and export graph artifacts for Neo4j/Gephi. Also build a file co-change graph (Jaccard similarity on shared commits) to cluster files by how they move together while ignoring large, noisy commits.

Requirements

  • Python 3
  • networkx (required; community detection is enabled by default)

Install with:

pip install networkx

Workflow

  1. Scope the repo and time window (optional --since/--until).
  2. Decide sensitivity rules (use defaults or provide a CSV config).
  3. Build the ownership map with scripts/run_ownership_map.py (co-change graph is on by default; use --cochange-max-files to ignore supernode commits).
  4. Communities are computed by default; graphml output is optional (--graphml).
  5. Query the outputs with scripts/query_ownership.py for bounded JSON slices.
  6. Persist and visualize (see references/neo4j-import.md).

By default, the co-change graph ignores common “glue” files (lockfiles, .github/*, editor config) so clusters reflect actual code movement instead of shared infra edits. Override with --cochange-exclude or --no-default-cochange-excludes. Dependabot commits are excluded by default; override with --no-default-author-excludes or add patterns via --author-exclude-regex.

If you want to exclude Linux build glue like Kbuild from co-change clustering, pass:

python skills/skills/security-ownership-map/scripts/run_ownership_map.py \
  --repo /path/to/linux \
  --out ownership-map-out \
  --cochange-exclude "**/Kbuild"

Quick start

Run from the repo root:

python skills/skills/security-ownership-map/scripts/run_ownership_map.py \
  --repo . \
  --out ownership-map-out \
  --since "12 months ago" \
  --emit-commits

Defaults: author identity, author date, and merge commits excluded. Use --identity committer, --date-field committer, or --include-merges if needed.

Example (override co-change excludes):

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

Communities are computed by default. To disable:

python skills/skills/security-ownership-map/scripts/run_ownership_map.py \
  --repo . \
  --out ownership-map-out \
  --no-communities

Sensitivity rules

By default, the script flags common auth/crypto/secret paths. Override by providing a CSV file:

# pattern,tag,weight
**/auth/**,auth,1.0
**/crypto/**,crypto,1.0
**/*.pem,secrets,1.0

Use it with --sensitive-config path/to/sensitive.csv.

Output artifacts

ownership-map-out/ contains:

  • people.csv (nodes: people)
  • files.csv (nodes: files)
  • edges.csv (edges: touches)
  • cochange_edges.csv (file-to-file co-change edges with Jaccard weight; omitted with --no-cochange)
  • summary.json (security ownership findings)
  • commits.jsonl (optional, if --emit-commits)
  • communities.json (computed by default from co-change edges when available; includes maintainers per community; disable with --no-communities)
  • cochange.graph.json (NetworkX node-link JSON with community_id + community_maintainers; falls back to ownership.graph.json if no co-change edges)
  • ownership.graphml / cochange.graphml (optional, if --graphml)

people.csv includes timezone detection based on author commit offsets: primary_tz_offset, primary_tz_minutes, and timezone_offsets.

LLM query helper

Use scripts/query_ownership.py to return small, JSON-bounded slices without loading the full graph into context.

Examples:

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

Use --community-top-owners 5 (default) to control how many maintainers are stored per community.

Basic security queries

Run these to answer common security ownership questions with bounded output:

# Orphaned sensitive code (stale + low bus factor)
python skills/skills/security-ownership-map/scripts/query_ownership.py --data-dir ownership-map-out summary --section orphaned_sensitive_code

# Hidden owners for sensitive tags
python skills/skills/security-ownership-map/scripts/query_ownership.py --data-dir ownership-map-out summary --section hidden_owners

# Sensitive hotspots with low bus factor
python skills/skills/security-ownership-map/scripts/query_ownership.py --data-dir ownership-map-out summary --section bus_factor_hotspots

# Auth/crypto files with 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

# Who is touching sensitive code the most
python skills/skills/security-ownership-map/scripts/query_ownership.py --data-dir ownership-map-out people --sort sensitive_touches --limit 10

# Co-change neighbors (cluster hints for ownership drift)
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

# Community maintainers (for a cluster)
python skills/skills/security-ownership-map/scripts/query_ownership.py --data-dir ownership-map-out community --id 3

# Monthly maintainers for the community containing a file
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

# Quarterly buckets instead of monthly
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

Notes:

  • Touches default to one authored commit (not per-file). Use --touch-mode file to count per-file touches.
  • Use --window-days 90 or --weight recency --half-life-days 180 to smooth churn.
  • Filter bots with --ignore-author-regex '(bot|dependabot)'.
  • Use --min-share 0.1 to show stable maintainers only.
  • Use --bucket quarter for calendar quarter groupings.
  • Use --identity committer or --date-field committer to switch from author attribution.
  • Use --include-merges to include merge commits (excluded by default).

Summary format (default)

Use this structure, add fields if needed:

{
  "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"
    }
  ]
}

Graph persistence

Use references/neo4j-import.md when you need to load the CSVs into Neo4j. It includes constraints, import Cypher, and visualization tips.

Notes

  • bus_factor_hotspots in summary.json lists sensitive files with low bus factor; orphaned_sensitive_code is the stale subset.
  • If git log is too large, narrow with --since or --until.
  • Compare summary.json against CODEOWNERS to highlight ownership drift.

常见问题

运行需要什么依赖?
需要 Python 3 和 networkx,用 pip install networkx 安装。社区检测默认开启,依赖 networkx。
怎么定义哪些代码算敏感?
默认会标记常见的 auth、crypto、secret 路径。也可以用 --sensitive-config 传入 CSV,每行是 pattern、tag、weight。
如何避免把整张图塞进 LLM 上下文?
用 scripts/query_ownership.py,它按需返回有界的 JSON 片段,支持 people、files、单个 person 或 file、共变邻居、summary 各分区以及 community 查询。
合并提交和机器人会被统计吗?
默认排除合并提交和 Dependabot 提交。需要时可用 --include-merges、--no-default-author-excludes 或 --author-exclude-regex 调整。

相关技能

从 AdMapix API 拉取广告创意、应用、榜单和收入预估等数据,原样返回结构化 JSON。

作者 fly0pants4.3k 次安装296 星标

把自然语言描述转为结构化 JSON,并由 mcp-diagram-generator MCP 服务生成 Draw.io、Mermaid 或 Excalidraw 图表文件。

作者 nssa.io1.0k 次安装47 星标

为 Codex 生成插件目录骨架,包含必需的 .codex-plugin/plugin.json 清单和可选的 marketplace 条目。

作者 OpenAI28.1k 星标

Deploy web projects to Netlify using the Netlify CLI (`npx netlify`). Use when the user asks to deploy, host, publish, or link a site/repo on Netlify, including preview and production deploys.

作者 OpenAI28.1k 星标

sentry

官方

Use when the user asks to inspect Sentry issues or events, summarize recent production errors, or pull basic Sentry health data via the Sentry CLI; perform read-only queries using the `sentry` command

作者 OpenAI28.1k 星标

OpenAI 的更多技能

浏览全部技能

按当前 OpenAI 文档生成 MCP 服务端 + 小组件 UI 的 ChatGPT Apps SDK 项目脚手架。

作者 OpenAI28.1k 星标

复用已发布的设计系统组件、变量与样式,在 Figma 中新建或更新整页屏幕。

作者 OpenAI28.1k 星标

按阶段把代码库对应的设计系统搭进 Figma,每个阶段都先给你确认再继续。

作者 OpenAI28.1k 星标

figma-use

官方

在 Figma 文件里通过 Plugin API 执行 JavaScript,并带上避免脚本报错的 API 规则与常见坑。

作者 OpenAI28.1k 星标

hatch-pet

官方

把角色图、品牌线索或参考图做成 Codex 可用的动画宠物与 8x9 精灵图集。

作者 OpenAI28.1k 星标

imagegen

官方

为项目生成或编辑位图图像,覆盖主视觉、精灵图到透明背景抠图等需求。

作者 OpenAI28.1k 星标