security: reject traversal segments before permission checks

This commit is contained in:
OpenClaw Agent
2026-09-21 20:50:51 +08:00
parent bf98df490c
commit f99e735966
+26
View File
@@ -123,6 +123,16 @@ func writeJSONError(w http.ResponseWriter, status int, message string) {
w.WriteHeader(status)
_ = json.NewEncoder(w).Encode(map[string]string{"error": message})
}
func unsafePath(p string) bool {
p = strings.ReplaceAll(p, "\\", "/")
for _, part := range strings.Split(p, "/") {
if part == ".." {
return true
}
}
return false
}
func qpath(r *http.Request) string {
return strings.Trim(strings.ReplaceAll(r.URL.Query().Get("filepath"), "\\", "/"), "/")
}
@@ -167,6 +177,10 @@ func writeCreated(w http.ResponseWriter) { w.WriteHeader(http.StatusCreated) }
func (s *Server) files(w http.ResponseWriter, r *http.Request) {
a := account(r, s)
if unsafePath(r.URL.Query().Get("filepath")) {
writeJSONError(w, http.StatusBadRequest, "invalid parameter")
return
}
p := qpath(r)
m := a.MaskFor(p)
if !m.HasRead() {
@@ -213,6 +227,10 @@ func (s *Server) newdir(w http.ResponseWriter, r *http.Request) {
_ = r.ParseMultipartForm(16 << 20)
_ = r.ParseForm()
p := qpath(r)
if unsafePath(r.URL.Query().Get("filepath")) || unsafePath(r.FormValue("filepath")) {
writeJSONError(w, http.StatusBadRequest, "invalid parameter")
return
}
if p == "" {
p = strings.Trim(strings.ReplaceAll(r.FormValue("filepath"), "\\", "/"), "/")
}
@@ -536,6 +554,10 @@ func (s *Server) shared(w http.ResponseWriter, r *http.Request) {
return
}
p := strings.Trim(strings.TrimPrefix(r.URL.Path, "/chfs/shared/"), "/")
if unsafePath(p) {
http.NotFound(w, r)
return
}
fi, err := s.Store.Stat(p)
if err != nil {
http.NotFound(w, r)
@@ -716,6 +738,10 @@ func (s *Server) webdav(w http.ResponseWriter, r *http.Request) {
return
}
vp := strings.Trim(strings.TrimPrefix(r.URL.Path, "/webdav"), "/")
if unsafePath(vp) {
writeJSONError(w, http.StatusBadRequest, "invalid parameter")
return
}
old := r.URL.Path
r.URL.Path = "/" + vp
defer func() { r.URL.Path = old }()