diff pkg/imports/report.go @ 5377:d19fdf3d2099 extented-report

Add a string type that allows only runes that are safe of directory traversal.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Thu, 24 Jun 2021 22:13:48 +0200
parents e09e003948c7
children 8e30b926b94d
line wrap: on
line diff
--- a/pkg/imports/report.go	Thu Jun 24 19:24:21 2021 +0200
+++ b/pkg/imports/report.go	Thu Jun 24 22:13:48 2021 +0200
@@ -22,7 +22,6 @@
 	"log"
 	"os"
 	"path/filepath"
-	"regexp"
 	"strings"
 	"text/template"
 	"time"
@@ -39,7 +38,7 @@
 
 type Report struct {
 	models.QueueConfigurationType
-	Name string `json:"name"`
+	Name models.SafePath `json:"name"`
 }
 
 const ReportJobKind JobKind = "report"
@@ -88,7 +87,7 @@
 // RequiresRoles enforces to be a sys_admin to run this .
 func (*Report) RequiresRoles() auth.Roles { return auth.Roles{"sys_admin"} }
 
-func (r *Report) Description() (string, error) { return r.Name, nil }
+func (r *Report) Description() (string, error) { return string(r.Name), nil }
 
 func (*Report) CleanUp() error { return nil }
 
@@ -96,7 +95,7 @@
 	if err := r.QueueConfigurationType.MarshalAttributes(attrs); err != nil {
 		return err
 	}
-	attrs.Set("name", r.Name)
+	attrs.Set("name", string(r.Name))
 	return nil
 }
 
@@ -108,7 +107,10 @@
 	if !found {
 		return errors.New("missing 'name' attribute")
 	}
-	r.Name = name
+	r.Name = models.SafePath(name)
+	if !r.Name.Valid() {
+		return fmt.Errorf("'%s' is not a safe path", name)
+	}
 	return nil
 }
 
@@ -127,13 +129,8 @@
 		return nil, nil, fmt.Errorf("report dir '%s' is not a directory", path)
 	}
 
-	// TODO: Prevent this earlier.
-	if match, _ := regexp.MatchString(`^[a-zA-Z0-9_-]+$`, r.Name); !match {
-		return nil, nil, errors.New("invalid report name")
-	}
-
-	xlsxFilename := filepath.Join(path, r.Name+".xlsx")
-	yamlFilename := filepath.Join(path, r.Name+".yaml")
+	xlsxFilename := filepath.Join(path, string(r.Name)+".xlsx")
+	yamlFilename := filepath.Join(path, string(r.Name)+".yaml")
 
 	for _, check := range []string{xlsxFilename, yamlFilename} {
 		if _, err := os.Stat(check); err != nil {
@@ -230,7 +227,7 @@
 
 	now := start.UTC().Format("2006-01-02")
 
-	attached := r.Name + "-" + now + ".xlsx"
+	attached := string(r.Name) + "-" + now + ".xlsx"
 
 	body := func(u misc.EmailReceiver) (string, error) {
 		fill := struct {
@@ -243,7 +240,7 @@
 		}{
 			Receiver:   u.Name,
 			Attachment: attached,
-			Report:     r.Name,
+			Report:     string(r.Name),
 			When:       now,
 			Admin:      admin.Name,
 			AdminEmail: admin.Address,
@@ -264,7 +261,7 @@
 
 	if err := misc.SendMailToAll(
 		users,
-		"Report "+r.Name+" from "+now,
+		"Report "+string(r.Name)+" from "+now,
 		body,
 		[]misc.EmailAttachment{{
 			Name:    attached,