Files
sxchnge/backend/internal/evidence/key.go
T

44 lines
1.1 KiB
Go

// Adapted from Sendico edge/shared/storage/s3key; see backend/PROVENANCE.md.
package evidence
import (
"errors"
"path"
"strings"
"unicode"
)
var ErrInvalidKey = errors.New("invalid evidence key")
// JoinKey confines a server-generated object reference to a relative prefix.
// It is not an ownership check or a local-filesystem path sanitizer. Inputs must
// not be URL-decoded or interpreted as filesystem paths after validation.
func JoinKey(prefix, reference string) (string, error) {
a, err := relative(prefix)
if err != nil {
return "", err
}
b, err := relative(reference)
if err != nil {
return "", err
}
return path.Join(a, b), nil
}
func relative(value string) (string, error) {
value = strings.TrimSpace(value)
if strings.ContainsAny(value, "\\%") || strings.ContainsFunc(value, unicode.IsControl) {
return "", ErrInvalidKey
}
for _, segment := range strings.Split(value, "/") {
if segment == ".." {
return "", ErrInvalidKey
}
}
clean := path.Clean(value)
if value == "" || clean == "." || path.IsAbs(clean) {
return "", ErrInvalidKey
}
return clean, nil
}