From 134c3aade4b62753a670ae987e2facbec2cc0a4b Mon Sep 17 00:00:00 2001 From: Miguel Martinez Trivino Date: Tue, 31 Mar 2026 00:14:10 +0200 Subject: [PATCH 1/3] fix: revert go-git to v5.16.5 and handle extension errors gracefully go-git v5.17.0 introduced strict repository extension validation (go-git/go-git#1861) with a case-sensitivity bug that rejects the worktreeConfig extension, breaking attestation init in repos using git worktree. Reverts to v5.16.5 and adds defensive handling in gracefulGitRepoHead so unsupported extension errors degrade gracefully instead of failing the attestation. Closes #2966 Signed-off-by: Miguel Martinez Trivino --- go.mod | 2 +- go.sum | 4 ++-- pkg/attestation/crafter/crafter.go | 17 +++++++++++++- pkg/attestation/crafter/crafter_unit_test.go | 24 ++++++++++++++++++++ 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index c98ff7334..ea3158710 100644 --- a/go.mod +++ b/go.mod @@ -353,7 +353,7 @@ require ( github.com/emicklei/go-restful/v3 v3.13.0 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fsouza/fake-gcs-server v1.47.6 - github.com/go-git/go-git/v5 v5.17.1 + github.com/go-git/go-git/v5 v5.16.5 github.com/go-kratos/aegis v0.2.0 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect diff --git a/go.sum b/go.sum index 1a171b5df..c61dd238c 100644 --- a/go.sum +++ b/go.sum @@ -449,8 +449,8 @@ github.com/go-git/go-billy/v5 v5.8.0/go.mod h1:RpvI/rw4Vr5QA+Z60c6d6LXH0rYJo0uD5 github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= -github.com/go-git/go-git/v5 v5.17.1 h1:WnljyxIzSj9BRRUlnmAU35ohDsjRK0EKmL0evDqi5Jk= -github.com/go-git/go-git/v5 v5.17.1/go.mod h1:pW/VmeqkanRFqR6AljLcs7EA7FbZaN5MQqO7oZADXpo= +github.com/go-git/go-git/v5 v5.16.5 h1:mdkuqblwr57kVfXri5TTH+nMFLNUxIj9Z7F5ykFbw5s= +github.com/go-git/go-git/v5 v5.16.5/go.mod h1:QOMLpNf1qxuSY4StA/ArOdfFR2TrKEjJiye2kel2m+M= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= diff --git a/pkg/attestation/crafter/crafter.go b/pkg/attestation/crafter/crafter.go index b55eaca20..66ba8baa6 100644 --- a/pkg/attestation/crafter/crafter.go +++ b/pkg/attestation/crafter/crafter.go @@ -312,6 +312,20 @@ type CommitRemote struct { // This error is not exposed by go-git var errBranchInvalidMerge = errors.New("branch config: invalid merge") +// isGitExtensionError returns true if the error is related to unsupported git +// repository format extensions (e.g. worktreeConfig). go-git v5.17.0 introduced +// strict validation that rejects repos with extensions it doesn't support. +// See https://github.com/go-git/go-git/pull/1861 +func isGitExtensionError(err error) bool { + if err == nil { + return false + } + msg := err.Error() + return strings.Contains(msg, "does not support extension") || + strings.Contains(msg, "unknown extension") || + strings.Contains(msg, "repositoryformatversion not supported") +} + // Returns the current directory git commit hash if possible // If we are not in a git repo it will return an empty string func gracefulGitRepoHead(path string) (*HeadCommit, error) { @@ -321,7 +335,8 @@ func gracefulGitRepoHead(path string) (*HeadCommit, error) { }) if err != nil { - if errors.Is(err, git.ErrRepositoryNotExists) { + if errors.Is(err, git.ErrRepositoryNotExists) || + isGitExtensionError(err) { return nil, nil } diff --git a/pkg/attestation/crafter/crafter_unit_test.go b/pkg/attestation/crafter/crafter_unit_test.go index bf2b39bc4..1980952f8 100644 --- a/pkg/attestation/crafter/crafter_unit_test.go +++ b/pkg/attestation/crafter/crafter_unit_test.go @@ -152,6 +152,30 @@ func (s *crafterUnitSuite) TestGitRepoHead() { name: "not a repository", wantNoCommit: true, }, + { + name: "repo with unsupported extension degrades gracefully", + repoProvider: func(repoPath string) (*HeadCommit, error) { + // Init a repo and add a worktreeConfig extension to trigger + // go-git's strict extension validation (added in v5.17.0) + if _, err := git.PlainInit(repoPath, false); err != nil { + return nil, err + } + + // Write the extension directly into the git config file + gitConfigPath := filepath.Join(repoPath, ".git", "config") + f, err := os.OpenFile(gitConfigPath, os.O_APPEND|os.O_WRONLY, 0o600) + if err != nil { + return nil, err + } + defer f.Close() + if _, err := f.WriteString("[extensions]\n\tworktreeConfig = true\n"); err != nil { + return nil, err + } + + return nil, nil + }, + wantNoCommit: true, + }, } for _, tc := range testCases { From 73b801dada0f1a80ddc9a0d5ce2023ac517ab04a Mon Sep 17 00:00:00 2001 From: Miguel Martinez Trivino Date: Tue, 31 Mar 2026 00:16:38 +0200 Subject: [PATCH 2/3] chore: add comment explaining go-git version pin Signed-off-by: Miguel Martinez Trivino --- go.mod | 3 +++ 1 file changed, 3 insertions(+) diff --git a/go.mod b/go.mod index ea3158710..1a2f05831 100644 --- a/go.mod +++ b/go.mod @@ -353,6 +353,9 @@ require ( github.com/emicklei/go-restful/v3 v3.13.0 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fsouza/fake-gcs-server v1.47.6 + // Pinned to v5.16.5: v5.17.x has a case-sensitivity bug in extension validation + // that breaks PlainOpen on repos using git worktree. + // https://github.com/chainloop-dev/chainloop/issues/2966 github.com/go-git/go-git/v5 v5.16.5 github.com/go-kratos/aegis v0.2.0 // indirect github.com/go-logr/logr v1.4.3 // indirect From 64e9bef361322f3079986c55fdf7d726a8fc087a Mon Sep 17 00:00:00 2001 From: Miguel Martinez Trivino Date: Tue, 31 Mar 2026 00:21:28 +0200 Subject: [PATCH 3/3] fix: keep go-git v5.17.1 and handle extension errors gracefully Switches from string-based error matching to using go-git's exported error variables now that we stay on v5.17.1. Signed-off-by: Miguel Martinez Trivino --- go.mod | 5 +---- go.sum | 4 ++-- pkg/attestation/crafter/crafter.go | 21 ++++++--------------- 3 files changed, 9 insertions(+), 21 deletions(-) diff --git a/go.mod b/go.mod index 1a2f05831..c98ff7334 100644 --- a/go.mod +++ b/go.mod @@ -353,10 +353,7 @@ require ( github.com/emicklei/go-restful/v3 v3.13.0 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fsouza/fake-gcs-server v1.47.6 - // Pinned to v5.16.5: v5.17.x has a case-sensitivity bug in extension validation - // that breaks PlainOpen on repos using git worktree. - // https://github.com/chainloop-dev/chainloop/issues/2966 - github.com/go-git/go-git/v5 v5.16.5 + github.com/go-git/go-git/v5 v5.17.1 github.com/go-kratos/aegis v0.2.0 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect diff --git a/go.sum b/go.sum index c61dd238c..1a171b5df 100644 --- a/go.sum +++ b/go.sum @@ -449,8 +449,8 @@ github.com/go-git/go-billy/v5 v5.8.0/go.mod h1:RpvI/rw4Vr5QA+Z60c6d6LXH0rYJo0uD5 github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= -github.com/go-git/go-git/v5 v5.16.5 h1:mdkuqblwr57kVfXri5TTH+nMFLNUxIj9Z7F5ykFbw5s= -github.com/go-git/go-git/v5 v5.16.5/go.mod h1:QOMLpNf1qxuSY4StA/ArOdfFR2TrKEjJiye2kel2m+M= +github.com/go-git/go-git/v5 v5.17.1 h1:WnljyxIzSj9BRRUlnmAU35ohDsjRK0EKmL0evDqi5Jk= +github.com/go-git/go-git/v5 v5.17.1/go.mod h1:pW/VmeqkanRFqR6AljLcs7EA7FbZaN5MQqO7oZADXpo= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= diff --git a/pkg/attestation/crafter/crafter.go b/pkg/attestation/crafter/crafter.go index 66ba8baa6..f8f6bb8b3 100644 --- a/pkg/attestation/crafter/crafter.go +++ b/pkg/attestation/crafter/crafter.go @@ -312,20 +312,6 @@ type CommitRemote struct { // This error is not exposed by go-git var errBranchInvalidMerge = errors.New("branch config: invalid merge") -// isGitExtensionError returns true if the error is related to unsupported git -// repository format extensions (e.g. worktreeConfig). go-git v5.17.0 introduced -// strict validation that rejects repos with extensions it doesn't support. -// See https://github.com/go-git/go-git/pull/1861 -func isGitExtensionError(err error) bool { - if err == nil { - return false - } - msg := err.Error() - return strings.Contains(msg, "does not support extension") || - strings.Contains(msg, "unknown extension") || - strings.Contains(msg, "repositoryformatversion not supported") -} - // Returns the current directory git commit hash if possible // If we are not in a git repo it will return an empty string func gracefulGitRepoHead(path string) (*HeadCommit, error) { @@ -335,8 +321,13 @@ func gracefulGitRepoHead(path string) (*HeadCommit, error) { }) if err != nil { + // go-git v5.17.0 introduced strict extension validation (go-git/go-git#1861) + // that rejects repos with extensions it doesn't fully support (e.g. worktreeConfig). + // Degrade gracefully instead of failing the attestation. if errors.Is(err, git.ErrRepositoryNotExists) || - isGitExtensionError(err) { + errors.Is(err, git.ErrUnsupportedExtensionRepositoryFormatVersion) || + errors.Is(err, git.ErrUnknownExtension) || + errors.Is(err, git.ErrUnsupportedRepositoryFormatVersion) { return nil, nil }