4
4
"fmt"
5
5
"os"
6
6
"path/filepath"
7
+ "strings"
7
8
8
9
"gopkg.in/yaml.v3"
9
10
)
@@ -13,6 +14,24 @@ const (
13
14
yamlIndent int = 2
14
15
)
15
16
17
+ func ValidatePath (basePath , filePath string ) error {
18
+ absBasePath , err := filepath .Abs (basePath )
19
+ if err != nil {
20
+ return fmt .Errorf ("invalid base path %q: %v" , basePath , err )
21
+ }
22
+
23
+ absFilePath , err := filepath .Abs (filePath )
24
+ if err != nil {
25
+ return fmt .Errorf ("invalid file path %q: %v" , basePath , err )
26
+ }
27
+
28
+ if ! strings .HasPrefix (absFilePath , absBasePath ) {
29
+ return fmt .Errorf ("file path escapes destination: %q outside %q" , absFilePath , absBasePath )
30
+ }
31
+
32
+ return nil
33
+ }
34
+
16
35
// Save saves recipe to given destination
17
36
func (re * Recipe ) Save (dest string ) error {
18
37
err := os .MkdirAll (dest , defaultFileMode )
@@ -197,8 +216,13 @@ func saveFileMap(files map[string]File, dest string) error {
197
216
for path , file := range files {
198
217
destPath := filepath .Join (dest , path )
199
218
219
+ err := ValidatePath (dest , destPath )
220
+ if err != nil {
221
+ return err
222
+ }
223
+
200
224
// Create file's parent directories (if not already exist)
201
- err : = os .MkdirAll (filepath .Dir (destPath ), 0700 )
225
+ err = os .MkdirAll (filepath .Dir (destPath ), 0700 )
202
226
if err != nil {
203
227
return err
204
228
}
0 commit comments