@@ -22,7 +22,7 @@ type DockerConfig struct {
2222type DockerAuth struct {
2323 Auth string `json:"auth,omitempty"`
2424 Username string `json:"username,omitempty"`
25- Password string `json:"password,omitempty"`
25+ Password string `json:"password,omitempty"` // #nosec G117 -- Required for Docker registry authentication
2626}
2727
2828// SetupConfig holds configuration for authentication setup
@@ -31,6 +31,38 @@ type SetupConfig struct {
3131 InsecureRegistry []string
3232}
3333
34+ // validateDockerConfigPath validates that a config path is within the expected Docker config directory
35+ func validateDockerConfigPath (configPath string ) error {
36+ // Clean the path
37+ cleanPath := filepath .Clean (configPath )
38+
39+ // Check for null bytes
40+ if strings .Contains (cleanPath , "\x00 " ) {
41+ return fmt .Errorf ("config path contains null bytes" )
42+ }
43+
44+ // Get expected base directory
45+ dockerConfigDir := GetDockerConfigDir ()
46+ expectedBase := filepath .Clean (dockerConfigDir )
47+
48+ // Ensure it's an absolute path
49+ if ! filepath .IsAbs (cleanPath ) {
50+ return fmt .Errorf ("config path must be absolute: %s" , cleanPath )
51+ }
52+
53+ // Check if path is within Docker config directory
54+ if ! strings .HasPrefix (cleanPath , expectedBase ) {
55+ return fmt .Errorf ("config path must be within Docker config directory (%s)" , expectedBase )
56+ }
57+
58+ // Additional check for path traversal
59+ if strings .Contains (configPath , ".." ) {
60+ return fmt .Errorf ("config path contains directory traversal" )
61+ }
62+
63+ return nil
64+ }
65+
3466// GetDockerConfigDir returns the Docker config directory
3567func GetDockerConfigDir () string {
3668 if dir := os .Getenv ("DOCKER_CONFIG" ); dir != "" {
@@ -107,7 +139,8 @@ func Setup(config SetupConfig) error {
107139 }
108140
109141 // Create the config directory if it doesn't exist
110- if err := os .MkdirAll (dockerConfigDir , 0755 ); err != nil {
142+ // Docker config directory should be restrictive (contains credentials)
143+ if err := os .MkdirAll (dockerConfigDir , 0700 ); err != nil {
111144 return fmt .Errorf ("failed to create Docker config directory: %v" , err )
112145 }
113146
@@ -128,6 +161,11 @@ func Setup(config SetupConfig) error {
128161 }
129162
130163 // Read and validate the config
164+ // Validate config path is within expected Docker config location
165+ if err := validateDockerConfigPath (configPath ); err != nil {
166+ return fmt .Errorf ("invalid Docker config path: %v" , err )
167+ }
168+ // #nosec G304 -- configPath validated to be within Docker config directory
131169 data , err := os .ReadFile (configPath )
132170 if err != nil {
133171 return fmt .Errorf ("failed to read Docker config: %v" , err )
@@ -187,6 +225,11 @@ func Setup(config SetupConfig) error {
187225
188226// ValidateDockerConfig validates a Docker config.json file
189227func ValidateDockerConfig (configPath string ) error {
228+ // Validate config path is within expected Docker config location
229+ if err := validateDockerConfigPath (configPath ); err != nil {
230+ return fmt .Errorf ("invalid Docker config path: %v" , err )
231+ }
232+ // #nosec G304 -- configPath validated to be within Docker config directory
190233 data , err := os .ReadFile (configPath )
191234 if err != nil {
192235 return fmt .Errorf ("failed to read config: %v" , err )
@@ -226,6 +269,7 @@ func CreateRegistriesConf(configDir string, insecureRegistries []string, destina
226269
227270 // Write registries.conf
228271 confPath := filepath .Join (configDir , "registries.conf" )
272+ // #nosec G306 -- registries.conf is configuration file, not credentials (0644 is appropriate)
229273 if err := os .WriteFile (confPath , []byte (sb .String ()), 0644 ); err != nil {
230274 return fmt .Errorf ("failed to write registries.conf: %v" , err )
231275 }
@@ -259,6 +303,11 @@ func GetRegistryAuth(registry string) (string, error) {
259303 dockerConfigDir := GetDockerConfigDir ()
260304 configPath := filepath .Join (dockerConfigDir , "config.json" )
261305
306+ // Validate config path is within expected Docker config location
307+ if err := validateDockerConfigPath (configPath ); err != nil {
308+ return "" , fmt .Errorf ("invalid Docker config path: %v" , err )
309+ }
310+ // #nosec G304 -- configPath validated to be within Docker config directory
262311 data , err := os .ReadFile (configPath )
263312 if err != nil {
264313 return "" , fmt .Errorf ("failed to read Docker config: %v" , err )
@@ -309,7 +358,8 @@ func CreateDockerConfig(outputPath string, auths map[string]DockerAuth) error {
309358
310359 // Ensure directory exists
311360 dir := filepath .Dir (outputPath )
312- if err := os .MkdirAll (dir , 0755 ); err != nil {
361+ // Docker config directory should be restrictive (contains credentials)
362+ if err := os .MkdirAll (dir , 0700 ); err != nil {
313363 return fmt .Errorf ("failed to create directory: %v" , err )
314364 }
315365
@@ -330,6 +380,11 @@ func AddCredentialHelper(registry, helper string) error {
330380 var config DockerConfig
331381
332382 // Read existing config if it exists
383+ // Validate config path is within expected Docker config location
384+ if err := validateDockerConfigPath (configPath ); err != nil {
385+ return fmt .Errorf ("invalid Docker config path: %v" , err )
386+ }
387+ // #nosec G304 -- configPath validated to be within Docker config directory
333388 if data , err := os .ReadFile (configPath ); err == nil {
334389 if err := json .Unmarshal (data , & config ); err != nil {
335390 logger .Warning ("Failed to parse existing config, creating new one" )
0 commit comments