Headline
CVE-2022-29180: fix: clean path before accessing file store · charmbracelet/charm@3c90668
A vulnerability in which attackers could forge HTTP requests to manipulate the charm
data directory to access or delete anything on the server. This has been patched and is available in release v0.12.1. We recommend that all users running self-hosted charm
instances update immediately. This vulnerability was found in-house and we haven’t been notified of any potential exploiters. ### Additional notes * Encrypted user data uploaded to the Charm server is safe as Charm servers cannot decrypt user data. This includes filenames, paths, and all key-value data. * Users running the official Charm Docker images are at minimal risk because the exploit is limited to the containerized filesystem.
@@ -10,6 +10,7 @@ import (
“io/ioutil”
“log”
“net/http”
“path/filepath”
“strconv”
“strings”
@@ -279,7 +280,7 @@ func (s *HTTPServer) handlePostSeq(w http.ResponseWriter, r *http.Request) {
func (s *HTTPServer) handlePostFile(w http.ResponseWriter, r *http.Request) {
u := s.charmUserFromRequest(w, r)
path := pattern.Path(r.Context())
path := filepath.Clean(pattern.Path(r.Context()))
ms := r.URL.Query().Get(“mode”)
m, err := strconv.ParseUint(ms, 10, 32)
if err != nil {
@@ -316,7 +317,7 @@ func (s *HTTPServer) handlePostFile(w http.ResponseWriter, r *http.Request) {
func (s *HTTPServer) handleGetFile(w http.ResponseWriter, r *http.Request) {
u := s.charmUserFromRequest(w, r)
path := pattern.Path(r.Context())
path := filepath.Clean(pattern.Path(r.Context()))
f, err := s.cfg.FileStore.Get(u.CharmID, path)
if errors.Is(err, fs.ErrNotExist) {
s.renderCustomError(w, "file not found", http.StatusNotFound)
@@ -353,7 +354,7 @@ func (s *HTTPServer) handleGetFile(w http.ResponseWriter, r *http.Request) {
func (s *HTTPServer) handleDeleteFile(w http.ResponseWriter, r *http.Request) {
u := s.charmUserFromRequest(w, r)
path := pattern.Path(r.Context())
path := filepath.Clean(pattern.Path(r.Context()))
err := s.cfg.FileStore.Delete(u.CharmID, path)
if err != nil {
log.Printf("cannot delete file: %s", err)