Two questions that sound like GitHub should just answer them. What open source libraries are developers pulling in across the org, and are there ML model files committed to repositories anywhere.

I said yes to both before I’d checked either. Neither one is answerable the way you’d expect, and working that out took considerably longer than the answer was worth.

The GitHub Dependency Graph is default branch only

The obvious starting point is the Dependency Graph and its SBOM API endpoint. Query a repo, get back packages with versions and licenses. Exactly right, until you go looking for the branch parameter.

There is no ?ref= parameter. It reads the default branch and nothing else.

In any real development workflow, dependencies land on develop or a feature branch first. A GPL library added to develop in January doesn’t merge to main until March, and the SBOM API can’t see it until it does. By then you’ve lost the chance to catch it before it ships, which was the whole reason for looking.

GitHub’s answer is the Dependency Submission API: modify every CI pipeline to push a dependency snapshot on every branch push. In a large org with varied pipeline configurations that’s a multi-month enablement project, and it buys you nothing retroactive for the repos that haven’t been touched yet.

The fix seems obvious to me and it isn’t implemented: put a ref parameter on the SBOM endpoint. Multi-branch dependency indexing should be native.

Code Search isn’t the answer for file scanning

The shortcut you reach for when you want to find files by extension at org scale is Code Search. Fast, org scoped, looks like exactly the right tool.

Don’t use it for compliance. The search index rebuilds continuously, so the same query can return different results on two consecutive runs depending on the rebuild state. You can’t report a number that changes based on when you ran the query.

More specifically, binary files and LFS pointer files aren’t reliably indexed at all. Model files are large binaries, usually in Git LFS, so Code Search simply can’t see the thing you’re looking for.

The Git Trees API can:

response = requests.get(
    f"https://api.github.com/repos/{owner}/{repo}/git/trees/{sha}",
    params={"recursive": "1"},
    headers={"Authorization": f"Bearer {token}"}
)

Pass any branch’s commit SHA and you get a deterministic flat file listing, read straight out of the Git object store. Filter by extension on your side. There’s no index involved, so there’s nothing to go stale.

The cost: at GitHub’s rate limit of 5,000 requests an hour, walking an org with tens of thousands of repositories across their non-default branches takes 12 to 15 hours. Fine as a nightly batch, useless on demand. Write it resume safe, because it will get interrupted.

ML model files are invisible to every GitHub security surface

The Dependency Graph is manifest-driven. It reads package.json, pom.xml, go.mod. Binary files are out of scope by design.

Which means a committed LLaMA model registers nothing. Not in the Dependency Graph, not in GHAS code scanning, not in secret scanning. It’s a possible license violation, a GDPR concern and a supply chain vector, and every security surface GitHub sells looks straight through it.

Pickle is the sharpest edge. .pkl is the default serialization format for scikit-learn and it’s common across ML pipelines, and deserializing one runs arbitrary code. A malicious or corrupted .pkl in a repository runs on every machine that loads it: CI runners, developer workstations, production. This has been exploited via Hugging Face model files. Your SAST scanner won’t catch it, because it has no idea what pickle even is.

The license is a separate problem from your code license. A developer pulls a model from Hugging Face and commits it for reproducibility into a private repo. LLaMA’s user threshold restriction, a Responsible AI License, a non-commercial clause: all of it still applies. Private repository doesn’t mean license-exempt. And a model fine-tuned on internal data retains information from that data in its weights, which is a GDPR question no matter where the file sits.

For detection we use the Git Trees API with extension heuristics:

MODEL_EXTENSIONS = {'.safetensors', '.gguf', '.pt', '.pth', '.onnx', '.pb', '.h5'}
# .pkl and .bin need size thresholds to avoid false positives
HIGH_FP_EXTENSIONS = {'.pkl': 10_000_000, '.bin': 100_000_000}  # bytes

Everything flagged goes to a manual review queue. The false positive rate on extension matching is too high to hang automated action off it.

Copilot usage metrics: better than expected, with gaps

For orgs running GitHub Copilot, the Usage Metrics API (GA since February 2026) gives you model usage breakdowns per user, by feature and editor. The is_custom_model flag surfaces cases where someone is routing Copilot through a fine-tuned or custom model. It exists, it works, and it’s more than I expected to get.

Start pulling it now if you’re going to pull it at all. The API retains one year of history and whatever you didn’t capture is gone.

What it won’t tell you is which repository. You can see that a user used model X, not what they were working on at the time, and “who used what model on which codebase” is the question AI governance actually asks. Telemetry is also opt out at the user’s discretion, so coverage has holes of unknown size, and that should be enforceable by org policy but isn’t. Model selection never reaches the audit log either, so “what model was active when this code was committed” isn’t answerable from anything GitHub holds.

What you end up building

Multi-branch dependency tracking is the expensive one. The SBOM API hands you default branch coverage for free. Past that you either wait for a ref parameter with no public timeline, wire Dependency Submission into every team’s CI over the next several months, or write a custom manifest parser that fetches package.json, pom.xml and the rest via the Contents API per branch. The parser is the pragmatic path, and the bill for it’s maintaining parsers as ecosystems change.

Model file inventory is Git Trees, multi-branch, LFS pointer parsing to get real file sizes, nightly batch, resume safe. Size heuristics on the high false positive extensions and a human queue in front of any action.

Copilot governance is a scheduled pull of the Usage Metrics API into your SIEM or data platform, with an alert on is_custom_model: true.

The data all exists. What doesn’t exist is anything that aggregates it at org scale, across branches, including binaries - so you end up building a layer that should have shipped with the platform.

I’m building it. I’d rather not be. And if somebody reading this knows of a tool that already does the multi-branch part properly, please tell me, because I went looking and I didn’t find one.