From 72f9c73e7b9a8c4c6bb5d7812374ad01e0b95902 Mon Sep 17 00:00:00 2001 From: Rada Kamysheva Date: Tue, 21 Jul 2026 09:08:17 +0000 Subject: [PATCH 1/2] Reject invalid dashboard parent_path in test server The fake DashboardCreate stored any parent_path verbatim unless it began with /Workspace/, so a value that isn't a real workspace folder (e.g. a path-traversal string like /etc/passwd) round-tripped through GET and surfaced as spurious drift under the direct engine. Validate parent_path the way cloud does: require an absolute, canonical path free of control characters and rooted under a real workspace directory (/Users, /Repos, /Shared), returning 400 otherwise. Existence alone is not sufficient, since such a directory may have been created earlier. --- libs/testserver/dashboards.go | 40 ++++++++++++++++++++++++++++ libs/testserver/dashboards_test.go | 42 ++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 libs/testserver/dashboards_test.go diff --git a/libs/testserver/dashboards.go b/libs/testserver/dashboards.go index aa7f102849d..63f5f5e1a0f 100644 --- a/libs/testserver/dashboards.go +++ b/libs/testserver/dashboards.go @@ -14,6 +14,34 @@ import ( "github.com/databricks/databricks-sdk-go/service/workspace" ) +// workspaceRoots are the only top-level directories the real workspace +// filesystem exposes. Cloud rejects a parent_path outside them. +var workspaceRoots = []string{"/Users/", "/Repos/", "/Shared/"} + +// isValidWorkspaceParentPath reports whether p is a parent_path the real Lakeview +// API would accept: an absolute, canonical path (no traversal or control +// characters) rooted under a real workspace directory. A "/Workspace" mount +// prefix is optional and ignored for the root check. +func isValidWorkspaceParentPath(p string) bool { + if !strings.HasPrefix(p, "/") || p != path.Clean(p) { + return false + } + for _, r := range p { + if r < 0x20 || r == 0x7f { + return false + } + } + if p == "/Workspace" || strings.HasPrefix(p, "/Workspace/") { + p = strings.TrimPrefix(p, "/Workspace") + } + for _, root := range workspaceRoots { + if strings.HasPrefix(p, root) { + return true + } + } + return false +} + // Generate 32 character hex string for dashboard ID func generateDashboardId() (string, error) { randomBytes := make([]byte, 16) @@ -109,6 +137,18 @@ func (s *FakeWorkspace) DashboardCreate(req Request) Response { dashboard.ParentPath = "/Users/" + s.CurrentUser().UserName } + // Cloud rejects a parent_path that isn't a valid workspace folder (e.g. a + // traversal value like "/etc/passwd"). Mirror that instead of storing it + // verbatim, which otherwise surfaces as spurious drift after round-tripping. + if !isValidWorkspaceParentPath(dashboard.ParentPath) { + return Response{ + StatusCode: 400, + Body: map[string]string{ + "message": fmt.Sprintf("Invalid parent path: %s", dashboard.ParentPath), + }, + } + } + if _, ok := s.directories[dashboard.ParentPath]; !ok { return Response{ StatusCode: 404, diff --git a/libs/testserver/dashboards_test.go b/libs/testserver/dashboards_test.go new file mode 100644 index 00000000000..9c62bced6a4 --- /dev/null +++ b/libs/testserver/dashboards_test.go @@ -0,0 +1,42 @@ +package testserver_test + +import ( + "net/http" + "strings" + "testing" + + "github.com/databricks/cli/libs/testserver" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func createDashboard(t *testing.T, baseURL, parentPath string) int { + t.Helper() + body := `{"display_name":"d","parent_path":"` + parentPath + `","warehouse_id":"w"}` + req, _ := http.NewRequest(http.MethodPost, baseURL+"/api/2.0/lakeview/dashboards", strings.NewReader(body)) + req.Header.Set("Authorization", "Bearer test-token") + resp, err := http.DefaultClient.Do(req) + require.NoError(t, err) + defer resp.Body.Close() + return resp.StatusCode +} + +// Cloud rejects a parent_path outside a real workspace folder. The fake mirrors +// that so a fuzzer value like "/etc/passwd" is a 400 rather than a stored path +// that later shows up as spurious drift. Existence alone is not enough: even an +// existing "/etc/passwd" directory is rejected because it isn't a workspace root. +func TestDashboardCreateRejectsInvalidParentPath(t *testing.T) { + server := testserver.New(t) + testserver.AddDefaultHandlers(server) + + mkdirs(t, server.URL, "/Users/dev") + mkdirs(t, server.URL, "/Workspace/Users/dev") + assert.Equal(t, 200, createDashboard(t, server.URL, "/Users/dev")) + assert.Equal(t, 200, createDashboard(t, server.URL, "/Workspace/Users/dev")) + + mkdirs(t, server.URL, "/etc/passwd") + assert.Equal(t, 400, createDashboard(t, server.URL, "/etc/passwd")) + assert.Equal(t, 400, createDashboard(t, server.URL, "/Users/../etc")) + assert.Equal(t, 400, createDashboard(t, server.URL, "relative/path")) + assert.Equal(t, 400, createDashboard(t, server.URL, "/Users/\x01dev")) +} From c98199ff6a445c984b1c75040a059fa53d8ac163 Mon Sep 17 00:00:00 2001 From: Rada Kamysheva Date: Tue, 21 Jul 2026 09:51:02 +0000 Subject: [PATCH 2/2] Shorten dashboard parent_path comments --- libs/testserver/dashboards.go | 14 +++++--------- libs/testserver/dashboards_test.go | 6 ++---- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/libs/testserver/dashboards.go b/libs/testserver/dashboards.go index 63f5f5e1a0f..9e0b1cdbd63 100644 --- a/libs/testserver/dashboards.go +++ b/libs/testserver/dashboards.go @@ -14,14 +14,12 @@ import ( "github.com/databricks/databricks-sdk-go/service/workspace" ) -// workspaceRoots are the only top-level directories the real workspace -// filesystem exposes. Cloud rejects a parent_path outside them. +// workspaceRoots are the top-level directories the real workspace exposes. var workspaceRoots = []string{"/Users/", "/Repos/", "/Shared/"} -// isValidWorkspaceParentPath reports whether p is a parent_path the real Lakeview -// API would accept: an absolute, canonical path (no traversal or control -// characters) rooted under a real workspace directory. A "/Workspace" mount -// prefix is optional and ignored for the root check. +// isValidWorkspaceParentPath reports whether p is a parent_path cloud accepts: +// an absolute, canonical path (no traversal or control chars) under a workspace +// root. The optional "/Workspace" mount prefix is ignored for the root check. func isValidWorkspaceParentPath(p string) bool { if !strings.HasPrefix(p, "/") || p != path.Clean(p) { return false @@ -137,9 +135,7 @@ func (s *FakeWorkspace) DashboardCreate(req Request) Response { dashboard.ParentPath = "/Users/" + s.CurrentUser().UserName } - // Cloud rejects a parent_path that isn't a valid workspace folder (e.g. a - // traversal value like "/etc/passwd"). Mirror that instead of storing it - // verbatim, which otherwise surfaces as spurious drift after round-tripping. + // Reject non-workspace paths like cloud does; storing them verbatim surfaces as drift. if !isValidWorkspaceParentPath(dashboard.ParentPath) { return Response{ StatusCode: 400, diff --git a/libs/testserver/dashboards_test.go b/libs/testserver/dashboards_test.go index 9c62bced6a4..81d76bcce75 100644 --- a/libs/testserver/dashboards_test.go +++ b/libs/testserver/dashboards_test.go @@ -21,10 +21,8 @@ func createDashboard(t *testing.T, baseURL, parentPath string) int { return resp.StatusCode } -// Cloud rejects a parent_path outside a real workspace folder. The fake mirrors -// that so a fuzzer value like "/etc/passwd" is a 400 rather than a stored path -// that later shows up as spurious drift. Existence alone is not enough: even an -// existing "/etc/passwd" directory is rejected because it isn't a workspace root. +// A non-workspace parent_path is a 400, even when the directory exists: "/etc/passwd" +// isn't under a workspace root, so it's rejected rather than stored as drift. func TestDashboardCreateRejectsInvalidParentPath(t *testing.T) { server := testserver.New(t) testserver.AddDefaultHandlers(server)