Use a service catalog as the primary source for who owns a finding, CODEOWNERS as the path level refinement, and git history as a last resort fallback. Each fails in a different way, so a good SCA tool should combine them and report findings that no source could route.
Why routing is the hard part at scale
Finding a vulnerable package is the easy half. In a large organization the harder question is who fixes it. A finding sent to a shared security inbox ages. A finding sent to the wrong team gets bounced. Ownership routing is what turns a list into work.
The three sources compared
| Source | Strength | Typical failure |
|---|---|---|
| CODEOWNERS file | Lives with the code, path level, reviewed in pull requests | Stale teams, missing paths, owner without access |
| Service catalog | One named owner per service, includes on call and tier | Entries go out of date after reorgs |
| Git history | Always available, needs no setup | Points to individuals who left or only touched one file |
CODEOWNERS
GitHub documents several behaviors that matter for routing. The file can sit in .github/, the root or docs/, and each branch has its own copy. When several patterns match, the last one wins. Files over 3 MB are not loaded. Owners can be users, teams or linked emails, but nonexistent users or teams, or those without write access, are not assigned (see Sources).
That last point is a silent failure. A team renamed in the org leaves a line that looks valid and routes nowhere. Ask a vendor whether their tool detects owners that GitHub would ignore.
Service catalog
Backstage's descriptor format shows the idea well: a Component has a required spec.owner, described as the singular entity, commonly a team, that bears ultimate responsibility. That "singular" is useful. A finding needs one accountable owner, not a committee. The same docs warn the field is not meant for automated runtime authorization, which is fine here because routing a ticket is not authorization.
The failure mode is freshness. Catalogs are only as accurate as the last person who updated them.
Git history
Blame data is a hint, not an owner. People move teams and leave. Use it to suggest a candidate when nothing else resolves, and label the result as a guess.
How to combine them
A sensible order for an SCA tool:
- Match the manifest path to a catalog component, take its team.
- If the repo has CODEOWNERS and the path matches a more specific rule, prefer that team for that directory.
- If neither resolves, suggest recent committers as candidates and flag as unconfirmed.
- If nothing resolves, put the finding in an unowned queue with a visible count.
What to ask in an evaluation
- Can ownership come from more than one source, with a stated priority?
- Is the owner re-resolved on every scan, or copied once at first detection?
- What happens when a team is deleted? Do open findings reassign?
- Can you export unowned findings as a metric?
Related reading: Route monorepo vulnerability findings to the right team and Unowned vulnerability findings and the ownership coverage metric.
Safeguard's asset discovery and SBOM and dependency scanning feed findings into ownership aware views, and the free scan at gold.safeguard.sh/scan shows how a first inventory looks.
Quick check
Is CODEOWNERS enough on its own?
Rarely. It covers code paths in one repository branch, and invalid owners are skipped silently. Pair it with a catalog or team mapping.
Who should own a finding in a shared library?
The team that owns the library, with consuming teams notified. Route the fix to the owner, not to every consumer.
Sources
Last reviewed: 19 October 2026.