This document explores how git-pkgs and gittuf could integrate to enable dependency-aware security policies for Git repositories. The goal: let gittuf enforce policies like "adding new runtime dependencies requires two approvals" or "block dependencies with critical CVEs" by leveraging git-pkgs' understanding of package ecosystems.
git-pkgs is a Git subcommand for tracking package dependencies across git history. It answers questions like "when was this dependency added?", "who added it?", and "what changed between these two commits?" with a unified interface across 40+ package ecosystems.
git-pkgs was recently rewritten from Ruby into Go, partly to enable this kind of integration (importable as a Go library) and partly to simplify deployment as a single binary. It's in early development and can be adapted to work well with gittuf based on feedback.
Core capabilities:
-
Manifest parsing - Recognizes and parses dependency manifests and lockfiles (package.json, Gemfile, Cargo.toml, go.mod, requirements.txt, etc.). Extracts package name, version, scope (runtime/dev/test), direct vs transitive, and integrity hashes.
-
History tracking - Walks git history to build a timeline of dependency changes. Stores results in a SQLite database at
.git/pkgs.sqlite3. Can also operate statelessly by parsing manifests directly from git objects. -
Change detection - Diffs dependency sets between commits, branches, or tags. Classifies changes as added, updated, or removed.
-
Metadata enrichment - Fetches extrinsic data from package registries and the ecosyste.ms API: licenses (SPDX identifiers and categories), vulnerabilities (CVEs from OSV with severity), version info (latest available, how far behind), package metadata (maintainers, repository URL, publish dates), and sigstore attestations (build provenance, SLSA levels).
-
PURLs - Normalizes all dependencies to the Package URL spec for cross-ecosystem consistency (
pkg:npm/[email protected]).
Supported ecosystems include npm, gem, cargo, go, pip, maven, gradle, nuget, composer, cocoapods, swift, hex, pub, and 25+ more.
Architecture: Go codebase with git-pkgs/manifests (parsers), git-pkgs/registries (registry API clients), internal/enrichment/ (metadata fetching), internal/analyzer/ (change detection), internal/database/ (SQLite), and internal/git/ (git operations).
gittuf is a platform-agnostic Git security system that removes the forge (GitHub, GitLab, etc.) as a single point of trust. Maintainers define policies specifying who can modify what, and any developer can independently verify that changes followed those policies.
Policies live at refs/gittuf/policy and define rules about who can modify branches, tags, and files. Each rule specifies patterns to match, authorized principals (signing keys), and a signature threshold.
Reference State Log (RSL) at refs/gittuf/reference-state-log is a hash-chained log tracking all ref changes, signed by actors.
Attestations at refs/gittuf/attestations record claims about changes using in-toto format.
gittuf supports file-based rules (file:package.json) with fnmatch patterns, but can only say "this file needs N signatures from these principals." It can't evaluate the content of changes.
git-pkgs knows things gittuf doesn't:
- Which files are dependency manifests/lockfiles (across 40+ ecosystems)
- What dependencies exist at any commit
- When dependencies were added, updated, or removed
- Extrinsic metadata: licenses, vulnerabilities, outdatedness, maintainers, sigstore attestations
This enables policies gittuf can't express alone:
- Manifest protection - Auto-detect and protect all manifest/lockfile paths
- Change-type rules - Require extra approval for adding new dependencies vs updating existing
- Scope-based rules - Stricter policies for runtime dependencies than devDependencies
- License policies - Block copyleft licenses, require review for unknown licenses
- Vulnerability policies - Block dependencies with critical CVEs
- Freshness policies - Flag significantly outdated dependencies
- Supply chain policies - Flag single-maintainer packages or recent ownership changes
- Provenance policies - Require dependencies have sigstore attestations or meet SLSA build levels
Approach 1: Policy generation - git-pkgs outputs gittuf rule fragments (git pkgs gittuf-rules) that maintainers include in their policy. Loose coupling, maintainers control adoption.
Approach 2: Ref-based metadata storage - git-pkgs stores enriched dependency metadata at refs/git-pkgs/metadata. gittuf's Lua hooks read this via gitReadBlob to check licenses/vulnerabilities. Keeps data out of working tree, travels with repo on push/pull.
Approach 3: Attestations - git-pkgs generates in-toto attestations about dependency changes and policy compliance. gittuf requires these attestations exist before allowing merge. A CI service or bot runs git-pkgs, creates signed attestations.
Approach 4: Go API - git-pkgs exposes a Go package that gittuf calls directly: AnalyzeCommitRange(), ListManifests(), EnrichDependencies(), CheckVulnerabilities(), CheckLicenses(). Supports stateless operation for verification scenarios.
The attestation approach (3) is probably cleanest - it matches gittuf's existing model and their GitHub app pattern. git-pkgs handles analysis, generates attestations with pass/fail results, gittuf verifies attestations exist and are signed by trusted principals.
gittuf's Lua hooks can read git blobs but can't call external tools or make network requests. So "does this dependency have an approved license?" requires either:
- Pre-computed metadata - git-pkgs writes enriched data to a ref that hooks can read
- External validator - CI runs git-pkgs, creates attestation, gittuf requires attestation
For working tree files (compliance, other tools), use CycloneDX/SPDX SBOM format rather than custom JSON.
gittuf exported pkg/gitinterface (PR #1169) partly with git-pkgs integration in mind. git-pkgs could use this instead of its own git wrapper, ensuring both projects interact with git consistently and making ref-based storage more natural.
Separately, git-pkgs is being integrated into Forgejo (the platform used by Codeberg) to provide dependency graph features. This could be a path for gittuf to integrate with Forgejo as well, with git-pkgs providing the dependency awareness layer.
git-pkgs also provides Dependabot-like features via the git-pkgs/managers library, which wraps package manager commands across ecosystems. This could hook into gittuf policies to decide whether a package should be installed at all, enforcing policies at install time rather than just at commit/push time.
- Granularity - Policies per-file, per-dependency, or per-change-type?
- Timing - Analysis at commit time, push time, or verification time?
- Policy language - Extend gittuf's format or separate git-pkgs policy file?
- Attestation schema - Coordinate predicate type with in-toto/SLSA community?
- Discuss this proposal with gittuf maintainers
- Agree on integration approach (attestations seem most promising)
- Define attestation predicate schema
- Evaluate git-pkgs using
pkg/gitinterface - Build proof-of-concept