Skip to content

Commit 6f4378c

Browse files
committed
fix(baremetal): manage security issue
1 parent 269a444 commit 6f4378c

File tree

1 file changed

+42
-4
lines changed

1 file changed

+42
-4
lines changed

internal/services/baremetal/server.go

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import (
77
"errors"
88
"fmt"
99
"os"
10+
"path/filepath"
11+
"strings"
1012

1113
"github.com/hashicorp/go-cty/cty"
1214
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
@@ -382,6 +384,7 @@ func ResourceServerCreate(ctx context.Context, d *schema.ResourceData, m any) di
382384
if err != nil {
383385
return diag.FromErr(err)
384386
}
387+
385388
req.UserData = &userData
386389
}
387390

@@ -475,18 +478,51 @@ func ResourceServerCreate(ctx context.Context, d *schema.ResourceData, m any) di
475478
return ResourceServerRead(ctx, d, m)
476479
}
477480

478-
func LoadUserDataBase64(cloudInit interface{}) ([]byte, error) {
481+
func LoadUserDataBase64(cloudInit any) ([]byte, error) {
479482
value := cloudInit.(string)
483+
480484
var content []byte
481-
if data, err := os.ReadFile(value); errors.Is(err, os.ErrNotExist) {
482-
content = []byte(value)
483-
} else if err == nil {
485+
486+
// If value refers to an existing file, read it. Otherwise treat value as the content.
487+
if fi, err := os.Stat(value); err == nil {
488+
// Only allow regular files
489+
if !fi.Mode().IsRegular() {
490+
return nil, fmt.Errorf("cloud_init path is not a regular file: %s", value)
491+
}
492+
493+
// Resolve absolute path and ensure it is within the current working directory
494+
absPath, err := filepath.Abs(value)
495+
if err != nil {
496+
return nil, err
497+
}
498+
499+
cwd, err := os.Getwd()
500+
if err != nil {
501+
return nil, err
502+
}
503+
504+
absPath = filepath.Clean(absPath)
505+
cwd = filepath.Clean(cwd)
506+
507+
if absPath != cwd && !strings.HasPrefix(absPath, cwd+string(os.PathSeparator)) {
508+
return nil, fmt.Errorf("reading cloud_init from outside working directory is disallowed: %s", value)
509+
}
510+
511+
data, err := os.ReadFile(absPath)
512+
if err != nil {
513+
return nil, err
514+
}
515+
484516
content = data
517+
} else if errors.Is(err, os.ErrNotExist) {
518+
content = []byte(value)
485519
} else {
486520
return nil, err
487521
}
522+
488523
encoded := base64.StdEncoding.EncodeToString(content)
489524
userData := []byte(encoded)
525+
490526
return userData, nil
491527
}
492528

@@ -732,10 +768,12 @@ func ResourceServerUpdate(ctx context.Context, d *schema.ResourceData, m any) di
732768

733769
if d.HasChange("cloud_init") {
734770
cloudInit := d.Get("cloud_init").(string)
771+
735772
userData, err := LoadUserDataBase64(cloudInit)
736773
if err != nil {
737774
return diag.FromErr(err)
738775
}
776+
739777
req.UserData = &userData
740778
hasChanged = true
741779
}

0 commit comments

Comments
 (0)