Skip to content

Commit 14904a0

Browse files
committed
fix: handle server error messages and validate instance ID
- Check message type before parsing to handle 'error' responses - Add validation to prevent path traversal via instance ID
1 parent 30d438f commit 14904a0

File tree

1 file changed

+40
-0
lines changed

1 file changed

+40
-0
lines changed

lib/cp.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,22 @@ func copyFileToWs(ws WsConn, srcPath string, size int64, callbacks *CpCallbacks)
253253
return fmt.Errorf("read result: %w", err)
254254
}
255255

256+
// Check message type first - server may send error or result
257+
var msgType struct {
258+
Type string `json:"type"`
259+
}
260+
if err := json.Unmarshal(message, &msgType); err != nil {
261+
return fmt.Errorf("parse message type: %w", err)
262+
}
263+
264+
if msgType.Type == "error" {
265+
var errMsg cpError
266+
if err := json.Unmarshal(message, &errMsg); err != nil {
267+
return fmt.Errorf("parse error: %w", err)
268+
}
269+
return fmt.Errorf("copy failed: %s", errMsg.Message)
270+
}
271+
256272
var result cpResult
257273
if err := json.Unmarshal(message, &result); err != nil {
258274
return fmt.Errorf("parse result: %w", err)
@@ -285,6 +301,22 @@ func copyDirToWs(ctx context.Context, cfg CpConfig, ws WsConn, srcPath, dstPath,
285301
return fmt.Errorf("read result: %w", err)
286302
}
287303

304+
// Check message type first - server may send error or result
305+
var msgType struct {
306+
Type string `json:"type"`
307+
}
308+
if err := json.Unmarshal(message, &msgType); err != nil {
309+
return fmt.Errorf("parse message type: %w", err)
310+
}
311+
312+
if msgType.Type == "error" {
313+
var errMsg cpError
314+
if err := json.Unmarshal(message, &errMsg); err != nil {
315+
return fmt.Errorf("parse error: %w", err)
316+
}
317+
return fmt.Errorf("copy failed: %s", errMsg.Message)
318+
}
319+
288320
var result cpResult
289321
if err := json.Unmarshal(message, &result); err != nil {
290322
return fmt.Errorf("parse result: %w", err)
@@ -573,6 +605,14 @@ func sanitizePath(base, path string) (string, error) {
573605

574606
// buildWsURL builds the WebSocket URL for the cp endpoint
575607
func buildWsURL(baseURL, instanceID string) (string, error) {
608+
// Validate instanceID to prevent path traversal attacks
609+
if instanceID == "" {
610+
return "", fmt.Errorf("instance ID cannot be empty")
611+
}
612+
if strings.Contains(instanceID, "/") || strings.Contains(instanceID, "\\") || strings.Contains(instanceID, "..") {
613+
return "", fmt.Errorf("invalid instance ID: contains path separator or traversal sequence")
614+
}
615+
576616
u, err := url.Parse(baseURL)
577617
if err != nil {
578618
return "", fmt.Errorf("invalid base URL: %w", err)

0 commit comments

Comments
 (0)