mirror of
https://github.com/helm/helm.git
synced 2026-04-20 21:56:55 -04:00
Merge pull request #31041 from lrascao/backport-CVE-2025-53547
Updating link handling
This commit is contained in:
commit
595a05da61
2 changed files with 161 additions and 0 deletions
|
|
@ -852,6 +852,20 @@ func writeLock(chartpath string, lock *chart.Lock, legacyLockfile bool) error {
|
|||
lockfileName = "requirements.lock"
|
||||
}
|
||||
dest := filepath.Join(chartpath, lockfileName)
|
||||
|
||||
info, err := os.Lstat(dest)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return fmt.Errorf("error getting info for %q: %w", dest, err)
|
||||
} else if err == nil {
|
||||
if info.Mode()&os.ModeSymlink != 0 {
|
||||
link, err := os.Readlink(dest)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading symlink for %q: %w", dest, err)
|
||||
}
|
||||
return fmt.Errorf("the %s file is a symlink to %q", lockfileName, link)
|
||||
}
|
||||
}
|
||||
|
||||
return os.WriteFile(dest, data, 0644)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,11 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"helm.sh/helm/v3/pkg/chart"
|
||||
"helm.sh/helm/v3/pkg/chart/loader"
|
||||
|
|
@ -598,3 +602,146 @@ func TestKey(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteLock(t *testing.T) {
|
||||
fixedTime, err := time.Parse(time.RFC3339, "2025-07-04T00:00:00Z")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to parse fixed time: %v", err)
|
||||
}
|
||||
lock := &chart.Lock{
|
||||
Generated: fixedTime,
|
||||
Digest: "sha256:12345",
|
||||
Dependencies: []*chart.Dependency{
|
||||
{
|
||||
Name: "fantastic-chart",
|
||||
Version: "1.2.3",
|
||||
Repository: "https://example.com/charts",
|
||||
},
|
||||
},
|
||||
}
|
||||
expectedContent, err := yaml.Marshal(lock)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to marshal lock: %v", err)
|
||||
}
|
||||
|
||||
t.Run("v2 lock file", func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
err := writeLock(dir, lock, false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to write lock file: %v", err)
|
||||
}
|
||||
|
||||
lockfilePath := filepath.Join(dir, "Chart.lock")
|
||||
_, err = os.Stat(lockfilePath)
|
||||
if err != nil {
|
||||
t.Fatalf("Chart.lock should exist: %v", err)
|
||||
}
|
||||
|
||||
content, err := os.ReadFile(lockfilePath)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read Chart.lock: %v", err)
|
||||
}
|
||||
if !bytes.Equal(content, expectedContent) {
|
||||
t.Fatalf("Chart.lock content mismatch:\nExpected: %s\nGot: %s", expectedContent, content)
|
||||
}
|
||||
|
||||
// Check that requirements.lock does not exist
|
||||
_, err = os.Stat(filepath.Join(dir, "requirements.lock"))
|
||||
if err == nil {
|
||||
t.Fatal("requirements.lock should not exist")
|
||||
}
|
||||
if !os.IsNotExist(err) {
|
||||
t.Fatalf("requirements.lock should not exist, got error: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("v1 lock file", func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
err := writeLock(dir, lock, true)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to write lock file: %v", err)
|
||||
}
|
||||
|
||||
lockfilePath := filepath.Join(dir, "requirements.lock")
|
||||
_, err = os.Stat(lockfilePath)
|
||||
if err != nil {
|
||||
t.Fatalf("requirements.lock should exist: %v", err)
|
||||
}
|
||||
|
||||
content, err := os.ReadFile(lockfilePath)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read requirements.lock: %v", err)
|
||||
}
|
||||
if !bytes.Equal(content, expectedContent) {
|
||||
t.Fatalf("requirements.lock content mismatch:\nExpected: %s\nGot: %s", expectedContent, content)
|
||||
}
|
||||
|
||||
// Check that Chart.lock does not exist
|
||||
_, err = os.Stat(filepath.Join(dir, "Chart.lock"))
|
||||
if err == nil {
|
||||
t.Fatal("Chart.lock should not exist")
|
||||
}
|
||||
if !os.IsNotExist(err) {
|
||||
t.Fatalf("Chart.lock should not exist, got error: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("overwrite existing lock file", func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
lockfilePath := filepath.Join(dir, "Chart.lock")
|
||||
err := os.WriteFile(lockfilePath, []byte("old content"), 0644)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create initial Chart.lock: %v", err)
|
||||
}
|
||||
|
||||
err = writeLock(dir, lock, false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to overwrite lock file: %v", err)
|
||||
}
|
||||
|
||||
content, err := os.ReadFile(lockfilePath)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read overwritten Chart.lock: %v", err)
|
||||
}
|
||||
if !bytes.Equal(content, expectedContent) {
|
||||
t.Fatalf("Overwritten Chart.lock content mismatch:\nExpected: %s\nGot: %s", expectedContent, content)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("lock file is a symlink", func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
dummyFile := filepath.Join(dir, "dummy.txt")
|
||||
err := os.WriteFile(dummyFile, []byte("dummy"), 0644)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create dummy file: %v", err)
|
||||
}
|
||||
|
||||
lockfilePath := filepath.Join(dir, "Chart.lock")
|
||||
err = os.Symlink(dummyFile, lockfilePath)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create symlink for Chart.lock: %v", err)
|
||||
}
|
||||
|
||||
err = writeLock(dir, lock, false)
|
||||
if err == nil {
|
||||
t.Fatal("expected error when writing lock file to a symlink")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "the Chart.lock file is a symlink to") {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("chart path is not a directory", func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
filePath := filepath.Join(dir, "not-a-dir")
|
||||
err := os.WriteFile(filePath, []byte("file"), 0644)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create file: %v", err)
|
||||
}
|
||||
|
||||
err = writeLock(filePath, lock, false)
|
||||
if err == nil {
|
||||
t.Fatal("expected error when writing lock file to a non-directory path")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue