7
7
"fmt"
8
8
"log"
9
9
"os"
10
+ "path/filepath"
10
11
"strconv"
11
12
"strings"
12
13
"time"
@@ -24,16 +25,35 @@ const (
24
25
DefaultTimeout = 10 * time .Second
25
26
FollowRedirects = true
26
27
MaxRedirects = 10
28
+ ConfigFileExtension = ".json"
27
29
)
28
30
29
31
// LoadConfigFromFile loads configuration values from a JSON file into the ClientConfig struct.
30
32
// This function opens the specified configuration file, reads its content, and unmarshals the JSON data
31
33
// into the ClientConfig struct. It's designed to initialize the client configuration with values
32
34
// from a file, complementing or overriding defaults and environment variable settings.
33
- // LoadConfigFromFile loads configuration values from a JSON file into the ClientConfig struct.
34
35
func LoadConfigFromFile (filePath string ) (* ClientConfig , error ) {
36
+ // Clean up the file path to prevent directory traversal
37
+ cleanPath := filepath .Clean (filePath )
38
+
39
+ // Resolve the cleanPath to an absolute path to ensure it resolves any symbolic links
40
+ absPath , err := filepath .EvalSymlinks (cleanPath )
41
+ if err != nil {
42
+ return nil , fmt .Errorf ("unable to resolve the absolute path of the configuration file: %s, error: %w" , filePath , err )
43
+ }
44
+
45
+ // Check for suspicious patterns in the resolved path
46
+ if strings .Contains (absPath , ".." ) {
47
+ return nil , fmt .Errorf ("invalid path, path traversal patterns detected: %s" , filePath )
48
+ }
49
+
50
+ // Ensure the file has the correct extension
51
+ if filepath .Ext (absPath ) != ConfigFileExtension {
52
+ return nil , fmt .Errorf ("invalid file extension for configuration file: %s, expected .json" , filePath )
53
+ }
54
+
35
55
// Read the entire file
36
- fileBytes , err := os .ReadFile (filePath )
56
+ fileBytes , err := os .ReadFile (absPath )
37
57
if err != nil {
38
58
return nil , fmt .Errorf ("failed to read the configuration file: %s, error: %w" , filePath , err )
39
59
}
@@ -48,11 +68,9 @@ func LoadConfigFromFile(filePath string) (*ClientConfig, error) {
48
68
49
69
log .Printf ("Configuration successfully loaded from file: %s" , filePath )
50
70
51
- // Set default values if necessary
71
+ // Set default values if necessary and validate the configuration
52
72
setLoggerDefaultValues (& config )
53
73
setClientDefaultValues (& config )
54
-
55
- // Validate mandatory configuration fields
56
74
if err := validateMandatoryConfiguration (& config ); err != nil {
57
75
return nil , fmt .Errorf ("configuration validation failed: %w" , err )
58
76
}
0 commit comments