Skip to content

Commit 0767f90

Browse files
committed
fix: prevent silent ancestor resolution from malformed YAML paths
When malformed YAML creates resource paths like `"../../base - ../../shared/prod"`, `FileLoader.New()` was silently resolving these to existing ancestor directories through path normalization instead of failing appropriately. This could cause resources to be loaded from unintended locations, which can be especially dangerous in CI/CD environments (#5979). Added validation in `FileLoader.New()` to check directory existence before allowing path normalization, preventing the silent "ancestor snapping" behavior. Before: ``` === RUN TestNewLoaderMalformedPath fileloader_test.go:223: Error Trace: /Users/wbuckner/dev/kustomize/api/internal/loader/fileloader_test.go:223 Error: "must build at directory: not a valid directory: '/shared/prod' doesn't exist" does not contain "does not exist" Test: TestNewLoaderMalformedPath --- FAIL: TestNewLoaderMalformedPath (0.00s) FAIL FAIL sigs.k8s.io/kustomize/api/internal/loader 0.757s FAIL ``` After: ``` === RUN TestNewLoaderMalformedPath --- PASS: TestNewLoaderMalformedPath (0.00s) PASS ok sigs.k8s.io/kustomize/api/internal/loader (cached) ```
1 parent cd30471 commit 0767f90

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

api/internal/loader/fileloader.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,15 @@ func (fl *FileLoader) New(path string) (ifc.Loader, error) {
167167
if filepath.IsAbs(path) {
168168
return nil, fmt.Errorf("new root '%s' cannot be absolute", path)
169169
}
170-
root, err := filesys.ConfirmDir(fl.fSys, fl.root.Join(path))
170+
171+
// Check if the intended directory exists before allowing normalization
172+
// to prevent silent resolution to ancestor directories from malformed paths
173+
intendedPath := fl.root.Join(path)
174+
if !fl.fSys.Exists(intendedPath) || !fl.fSys.IsDir(intendedPath) {
175+
return nil, fmt.Errorf("directory '%s' does not exist", path)
176+
}
177+
178+
root, err := filesys.ConfirmDir(fl.fSys, intendedPath)
171179
if err != nil {
172180
return nil, errors.WrapPrefixf(err, "%s", ErrRtNotDir.Error())
173181
}

api/internal/loader/fileloader_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,27 @@ func TestNewEmptyLoader(t *testing.T) {
207207
require.Error(t, err)
208208
}
209209

210+
func TestNewLoaderMalformedPath(t *testing.T) {
211+
require := require.New(t)
212+
l1, err := makeLoader().New("foo/project")
213+
require.NoError(err)
214+
215+
// Test malformed path that would previously resolve to an ancestor directory
216+
// This simulates the bug where malformed YAML like:
217+
// resources:
218+
// - ../../base
219+
// - ../../shared/prod
220+
// becomes: "../../base - ../../shared/prod"
221+
_, err = l1.New("../../base - ../../shared/prod")
222+
require.Error(err)
223+
require.Contains(err.Error(), "does not exist")
224+
225+
// Also test other malformed patterns that should fail
226+
_, err = l1.New("nonexistent/path")
227+
require.Error(err)
228+
require.Contains(err.Error(), "does not exist")
229+
}
230+
210231
func TestNewRemoteLoaderDoesNotExist(t *testing.T) {
211232
_, err := makeLoader().New("https://example.com/org/repo")
212233
require.ErrorContains(t, err, "fetch")

0 commit comments

Comments
 (0)