@@ -74,10 +74,15 @@ func (c *RouteCache) Delete(sessionID string) {
7474// DirectVMRoutingMiddleware rewrites allowlisted browser subresource requests to
7575// the browser VM using cached base_url and jwt data.
7676func DirectVMRoutingMiddleware (cache * RouteCache , subresources []string ) option.Middleware {
77- allowed := map [string ]struct {}{}
78- for _ , subresource := range subresources {
79- if trimmed := strings .TrimSpace (subresource ); trimmed != "" {
80- allowed [trimmed ] = struct {}{}
77+ // allowPrefixes are path prefixes (relative to browsers/{id}/) eligible for
78+ // direct-to-VM routing, e.g. "curl" or "telemetry/stream". Matching is
79+ // segment-boundary aware (see matchesDirectVMPrefix), so "telemetry/stream"
80+ // covers "telemetry/stream[/...]" but NOT "telemetry/events" (a control-plane
81+ // historical read served from S2) or "telemetry/streamfoo".
82+ allowPrefixes := make ([]string , 0 , len (subresources ))
83+ for _ , s := range subresources {
84+ if trimmed := strings .Trim (strings .TrimSpace (s ), "/" ); trimmed != "" {
85+ allowPrefixes = append (allowPrefixes , trimmed )
8186 }
8287 }
8388
@@ -88,7 +93,7 @@ func DirectVMRoutingMiddleware(cache *RouteCache, subresources []string) option.
8893 }
8994 sessionID , subresource , suffix , ok := parseDirectVMPath (req .URL .Path )
9095 if ok {
91- if _ , ok := allowed [ subresource ]; ok {
96+ if matchesDirectVMPrefix ( subresource + suffix , allowPrefixes ) {
9297 route , ok := cache .Load (sessionID )
9398 if ok {
9499 base , err := url .Parse (route .BaseURL )
@@ -313,6 +318,21 @@ func parseDirectVMPath(path string) (sessionID, subresource, suffix string, ok b
313318 return "" , "" , "" , false
314319}
315320
321+ // matchesDirectVMPrefix reports whether tail (the request path after
322+ // browsers/{id}/) is covered by an allow prefix, matching on segment boundaries:
323+ // "telemetry/stream" matches "telemetry/stream" and "telemetry/stream/...", but
324+ // not "telemetry/events" or "telemetry/streamfoo". This keeps historical
325+ // control-plane reads (e.g. telemetry/events, served from S2) off the VM.
326+ func matchesDirectVMPrefix (tail string , prefixes []string ) bool {
327+ tail = strings .Trim (tail , "/" )
328+ for _ , p := range prefixes {
329+ if tail == p || strings .HasPrefix (tail , p + "/" ) {
330+ return true
331+ }
332+ }
333+ return false
334+ }
335+
316336func joinURLPath (basePath , subresource , suffix string ) string {
317337 base := "/" + strings .Trim (strings .TrimSpace (basePath ), "/" )
318338 if base == "/" {
0 commit comments