CRITICAL security fixes for pulse-sensor-proxy:
1. Strengthened hostname validation regex:
- Now requires hostnames to start with alphanumeric character
- Prevents SSH option injection via hostnames starting with '-'
- Pattern: ^[a-zA-Z0-9][a-zA-Z0-9._-]{0,63}$ (1-64 chars total)
- Added IPv4 and IPv6 validation regexes for future use
2. Added validation to vulnerable V1 RPC handlers:
- handleGetTemperature: Now validates node parameter before SSH
- handleRegisterNodes: Now validates discovered cluster nodes
- Previously these handlers passed unsanitized input directly to SSH
3. Defense in depth:
- V2 handlers already had validation (now using improved regex)
- Multiple layers of protection against malicious node identifiers
- Validation prevents container from passing SSH options as hostnames
Without these fixes, a compromised container could potentially inject SSH
options by providing malicious node names, though the 'root@' prefix
provided some mitigation.
Addresses high-severity finding from security audit.
40 lines
1 KiB
Go
40 lines
1 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
var (
|
|
// nodeNameRegex validates node names (alphanumeric, dots, underscores, hyphens, 1-64 chars)
|
|
// Must not start with hyphen to prevent SSH option injection
|
|
nodeNameRegex = regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9._-]{0,63}$`)
|
|
|
|
// ipv4Regex validates IPv4 addresses
|
|
ipv4Regex = regexp.MustCompile(`^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$`)
|
|
|
|
// ipv6Regex validates IPv6 addresses (simplified)
|
|
ipv6Regex = regexp.MustCompile(`^[0-9a-fA-F:]+$`)
|
|
)
|
|
|
|
// sanitizeCorrelationID validates and sanitizes a correlation ID
|
|
// Returns a valid UUID, generating a new one if input is missing or invalid
|
|
func sanitizeCorrelationID(id string) string {
|
|
if id == "" {
|
|
return uuid.NewString()
|
|
}
|
|
if _, err := uuid.Parse(id); err != nil {
|
|
return uuid.NewString()
|
|
}
|
|
return id
|
|
}
|
|
|
|
// validateNodeName checks if a node name is in valid format
|
|
func validateNodeName(name string) error {
|
|
if !nodeNameRegex.MatchString(name) {
|
|
return fmt.Errorf("invalid node name")
|
|
}
|
|
return nil
|
|
}
|