Skip to content

Commit 45275fb

Browse files
committed
Validate SPOG org-id query values
Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
1 parent a0bfc57 commit 45275fb

2 files changed

Lines changed: 46 additions & 8 deletions

File tree

connector.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,10 @@ func NewConnector(options ...ConnOption) (driver.Connector, error) {
139139

140140
// clusterPathOrgIDPattern matches the workspace ID inside an all-purpose-compute
141141
// Thrift path of the form [/]sql/protocolv1/o/<workspace-id>/<cluster-id>[/...].
142-
var clusterPathOrgIDPattern = regexp.MustCompile(`(?:^|/)sql/protocolv1/o/(\d+)/[^/?]+`)
142+
var (
143+
orgIDPattern = regexp.MustCompile(`^[0-9]+$`)
144+
clusterPathOrgIDPattern = regexp.MustCompile(`^/?sql/protocolv1/o/([0-9]+)/[^/?]+`)
145+
)
143146

144147
// extractSpogHeaders inspects httpPath for the workspace ID and returns it as an
145148
// x-databricks-org-id header dict for SPOG routing.
@@ -170,10 +173,15 @@ func extractSpogHeaders(httpPath string) map[string]string {
170173
"SPOG header extraction: malformed query string in httpPath, falling back to path inspection: %s",
171174
err)
172175
} else if orgID := params.Get("o"); orgID != "" {
173-
logger.Debug().Msgf(
174-
"SPOG header extraction: injecting x-databricks-org-id=%s (extracted from ?o= in httpPath)",
175-
orgID)
176-
return map[string]string{"x-databricks-org-id": orgID}
176+
if !orgIDPattern.MatchString(orgID) {
177+
logger.Debug().Msg(
178+
"SPOG header extraction: ignoring non-numeric ?o= value in httpPath, falling back to path inspection")
179+
} else {
180+
logger.Debug().Msgf(
181+
"SPOG header extraction: injecting x-databricks-org-id=%s (extracted from ?o= in httpPath)",
182+
orgID)
183+
return map[string]string{"x-databricks-org-id": orgID}
184+
}
177185
}
178186
}
179187

connector_spog_test.go

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,24 @@ func TestExtractSpogHeaders(t *testing.T) {
4848
want: map[string]string{"x-databricks-org-id": "12345"},
4949
},
5050
{
51-
name: "first o= wins when duplicated",
52-
httpPath: "/sql/1.0/warehouses/abc?o=first&o=second",
53-
want: map[string]string{"x-databricks-org-id": "first"},
51+
name: "first numeric o= wins when duplicated",
52+
httpPath: "/sql/1.0/warehouses/abc?o=111&o=222",
53+
want: map[string]string{"x-databricks-org-id": "111"},
54+
},
55+
{
56+
name: "non-numeric o= value returns nil",
57+
httpPath: "/sql/1.0/warehouses/abc?o=abc123",
58+
want: nil,
59+
},
60+
{
61+
name: "control-character o= value returns nil",
62+
httpPath: "/sql/1.0/warehouses/abc?o=123%0D%0AX-Injected:%20yes",
63+
want: nil,
64+
},
65+
{
66+
name: "invalid o= falls back to valid cluster path segment",
67+
httpPath: "sql/protocolv1/o/6051921418418893/0528-220959-uzmcn1qt?o=abc123",
68+
want: map[string]string{"x-databricks-org-id": "6051921418418893"},
5469
},
5570
{
5671
name: "just ? with nothing after returns nil",
@@ -75,6 +90,21 @@ func TestExtractSpogHeaders(t *testing.T) {
7590
httpPath: "sql/protocolv1/o/111/0528-220959-uzmcn1qt?o=222",
7691
want: map[string]string{"x-databricks-org-id": "222"},
7792
},
93+
{
94+
name: "nested cluster path prefix returns nil",
95+
httpPath: "evil/sql/protocolv1/o/999/0528-220959-uzmcn1qt",
96+
want: nil,
97+
},
98+
{
99+
name: "incomplete cluster path returns nil",
100+
httpPath: "sql/protocolv1/o/999/",
101+
want: nil,
102+
},
103+
{
104+
name: "warehouse path containing cluster-looking suffix returns nil",
105+
httpPath: "/sql/1.0/warehouses/sql/protocolv1/o/999/cluster-id",
106+
want: nil,
107+
},
78108
{
79109
// Regression guard: the new cluster-path regex must not match
80110
// warehouse paths (which never embed the workspace ID).

0 commit comments

Comments
 (0)