diff --git a/devcontainer/devcontainer.go b/devcontainer/devcontainer.go index ea07bfc..c0b79e1 100644 --- a/devcontainer/devcontainer.go +++ b/devcontainer/devcontainer.go @@ -227,7 +227,7 @@ func (s *Spec) compileFeatures(fs billy.Filesystem, devcontainerDir, scratchDir } featuresDir := filepath.Join(scratchDir, "features") - err := fs.MkdirAll(featuresDir, 0o644) + err := fs.MkdirAll(featuresDir, 0o755) if err != nil { return "", nil, fmt.Errorf("create features directory: %w", err) } @@ -277,8 +277,8 @@ func (s *Spec) compileFeatures(fs billy.Filesystem, devcontainerDir, scratchDir featureSha := md5.Sum([]byte(featureRefRaw)) featureName := filepath.Base(featureRef) featureDir := filepath.Join(featuresDir, fmt.Sprintf("%s-%x", featureName, featureSha[:4])) - if err := fs.MkdirAll(featureDir, 0o644); err != nil { - return "", nil, err + if err := fs.MkdirAll(featureDir, 0o755); err != nil { + return "", nil, fmt.Errorf("create feature directory for %s at %s: %w", featureRefRaw, featureDir, err) } spec, err := features.Extract(fs, devcontainerDir, featureDir, featureRefRaw) if err != nil { diff --git a/devcontainer/devcontainer_test.go b/devcontainer/devcontainer_test.go index 5b7fe03..2f20f5f 100644 --- a/devcontainer/devcontainer_test.go +++ b/devcontainer/devcontainer_test.go @@ -115,6 +115,15 @@ WORKDIR `+featureTwoDir+` ENV POTATO=example RUN VERSION="potato" _CONTAINER_USER="1000" _REMOTE_USER="1000" ./install.sh USER 1000`, params.DockerfileContent) + + // Verify feature directories are created with 0o755 (not + // 0o644) so non-root container users can traverse them. + for _, dir := range []string{workingDir + "/features", featureOneDir, featureTwoDir} { + info, err := fs.Stat(dir) + require.NoError(t, err, "stat %s", dir) + require.Equalf(t, os.FileMode(0o755), info.Mode()&os.ModePerm, + "directory %s should be 0o755, got %04o", dir, info.Mode()&os.ModePerm) + } }) t.Run("WithBuildContexts", func(t *testing.T) {