chore: better path checks

This commit is contained in:
wwqgtxx 2025-04-30 23:21:13 +08:00
parent cad26ac6a8
commit b4fe669848
6 changed files with 23 additions and 7 deletions

View File

@ -136,7 +136,11 @@ func NewSsh(option SshOption) (*Ssh, error) {
if strings.Contains(option.PrivateKey, "PRIVATE KEY") {
b = []byte(option.PrivateKey)
} else {
b, err = os.ReadFile(C.Path.Resolve(option.PrivateKey))
path := C.Path.Resolve(option.PrivateKey)
if !C.Path.IsSafePath(path) {
return nil, fmt.Errorf("path is not subpath of home directory: %s", path)
}
b, err = os.ReadFile(path)
if err != nil {
return nil, err
}

View File

@ -81,7 +81,11 @@ func GetCertPool(customCA string, customCAString string) (*x509.CertPool, error)
var certificate []byte
var err error
if len(customCA) > 0 {
certificate, err = os.ReadFile(C.Path.Resolve(customCA))
path := C.Path.Resolve(customCA)
if !C.Path.IsSafePath(path) {
return nil, fmt.Errorf("path is not subpath of home directory: %s", path)
}
certificate, err = os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("load ca error: %w", err)
}

View File

@ -16,6 +16,7 @@ import (
type Path interface {
Resolve(path string) string
IsSafePath(path string) bool
}
// LoadTLSKeyPair loads a TLS key pair from the provided certificate and private key data or file paths, supporting fallback resolution.
@ -40,7 +41,12 @@ func LoadTLSKeyPair(certificate, privateKey string, path Path) (tls.Certificate,
certificate = path.Resolve(certificate)
privateKey = path.Resolve(privateKey)
cert, loadErr := tls.LoadX509KeyPair(certificate, privateKey)
var loadErr error
if path.IsSafePath(certificate) && path.IsSafePath(privateKey) {
cert, loadErr = tls.LoadX509KeyPair(certificate, privateKey)
} else {
loadErr = fmt.Errorf("path is not subpath of home directory")
}
if loadErr != nil {
return tls.Certificate{}, fmt.Errorf("parse certificate failed, maybe format error:%s, or path error: %s", painTextErr.Error(), loadErr.Error())
}

View File

@ -754,6 +754,9 @@ func parseGeneral(cfg *RawConfig) (*General, error) {
}
func parseController(cfg *RawConfig) (*Controller, error) {
if path := cfg.ExternalUI; path != "" && !C.Path.IsSafePath(path) {
return nil, fmt.Errorf("path is not subpath of home directory: %s", path)
}
return &Controller{
ExternalController: cfg.ExternalController,
ExternalUI: cfg.ExternalUI,

View File

@ -84,7 +84,7 @@ func (p *path) IsSafePath(path string) bool {
return false
}
return !strings.Contains(rel, "..")
return filepath.IsLocal(rel)
}
func (p *path) GetPathByHash(prefix, name string) string {

View File

@ -373,10 +373,9 @@ func updateConfigs(w http.ResponseWriter, r *http.Request) {
} else {
if req.Path == "" {
req.Path = C.Path.Config()
}
if !filepath.IsAbs(req.Path) {
} else if !filepath.IsLocal(req.Path) {
render.Status(r, http.StatusBadRequest)
render.JSON(w, r, newError("path is not a absolute path"))
render.JSON(w, r, newError("path is not a valid absolute path"))
return
}