7979)
8080
8181// checkBindMountRestrictions checks if bind mounts in the request are allowed.
82- func checkBindMountRestrictions (r * http.Request ) error {
82+ func checkBindMountRestrictions (allowedBindMounts [] string , r * http.Request ) error {
8383 // Only check if bind mount restrictions are configured
84- if len (cfg . AllowBindMountFrom ) == 0 {
84+ if len (allowedBindMounts ) == 0 {
8585 return nil
8686 }
8787
@@ -94,23 +94,23 @@ func checkBindMountRestrictions(r *http.Request) error {
9494 switch {
9595 case len (pathParts ) >= 4 && pathParts [2 ] == "containers" && pathParts [3 ] == "create" :
9696 // Container creation: /vX.xx/containers/create
97- return checkContainer (r )
97+ return checkContainer (allowedBindMounts , r )
9898 case len (pathParts ) >= 5 && pathParts [2 ] == "containers" && pathParts [4 ] == "update" :
9999 // Container update: /vX.xx/containers/{id}/update
100- return checkContainer (r )
100+ return checkContainer (allowedBindMounts , r )
101101 case len (pathParts ) >= 4 && pathParts [2 ] == "services" && pathParts [3 ] == "create" :
102102 // Service creation: /vX.xx/services/create
103- return checkService (r )
103+ return checkService (allowedBindMounts , r )
104104 case len (pathParts ) >= 5 && pathParts [2 ] == "services" && pathParts [4 ] == "update" :
105105 // Service update: /vX.xx/services/{id}/update
106- return checkService (r )
106+ return checkService (allowedBindMounts , r )
107107 default :
108108 return nil
109109 }
110110}
111111
112112// checkContainer checks bind mounts in container creation requests.
113- func checkContainer (r * http.Request ) error {
113+ func checkContainer (allowedBindMounts [] string , r * http.Request ) error {
114114 body , err := readAndRestoreBody (r )
115115 if err != nil {
116116 return err
@@ -122,11 +122,11 @@ func checkContainer(r *http.Request) error {
122122 return nil // Don't block if we can't parse.
123123 }
124124
125- return checkHostConfigBindMounts (req .HostConfig )
125+ return checkHostConfigBindMounts (allowedBindMounts , req .HostConfig )
126126}
127127
128128// checkService checks bind mounts in service creation requests.
129- func checkService (r * http.Request ) error {
129+ func checkService (allowedBindMounts [] string , r * http.Request ) error {
130130 body , err := readAndRestoreBody (r )
131131 if err != nil {
132132 return err
@@ -141,28 +141,31 @@ func checkService(r *http.Request) error {
141141 if req .TaskTemplate .ContainerSpec == nil {
142142 return nil // No container spec, nothing to check.
143143 }
144- return checkHostConfigBindMounts (& containerHostConfig {
145- Mounts : req .TaskTemplate .ContainerSpec .Mounts ,
146- })
144+ return checkHostConfigBindMounts (
145+ allowedBindMounts ,
146+ & containerHostConfig {
147+ Mounts : req .TaskTemplate .ContainerSpec .Mounts ,
148+ },
149+ )
147150}
148151
149152// checkHostConfigBindMounts checks bind mounts in HostConfig.
150- func checkHostConfigBindMounts (hostConfig * containerHostConfig ) error {
153+ func checkHostConfigBindMounts (allowedBindMounts [] string , hostConfig * containerHostConfig ) error {
151154 if hostConfig == nil {
152155 return nil // No HostConfig, nothing to check
153156 }
154157
155158 // Check legacy Binds field
156159 for _ , bind := range hostConfig .Binds {
157- if err := validateBindMount (bind ); err != nil {
160+ if err := validateBindMount (allowedBindMounts , bind ); err != nil {
158161 return err
159162 }
160163 }
161164
162165 // Check modern Mounts field
163166 for _ , mountItem := range hostConfig .Mounts {
164167 if mountItem .Type == mountTypeBind {
165- if err := validateBindMountSource (mountItem .Source ); err != nil {
168+ if err := validateBindMountSource (allowedBindMounts , mountItem .Source ); err != nil {
166169 return err
167170 }
168171 }
@@ -172,23 +175,23 @@ func checkHostConfigBindMounts(hostConfig *containerHostConfig) error {
172175}
173176
174177// validateBindMount validates a bind mount string in the format "source:target:options".
175- func validateBindMount (bind string ) error {
178+ func validateBindMount (allowedBindMounts [] string , bind string ) error {
176179 parts := strings .Split (bind , ":" )
177180 if len (parts ) < 2 {
178181 return fmt .Errorf ("invalid bind mount format: %s" , bind )
179182 }
180- return validateBindMountSource (parts [0 ])
183+ return validateBindMountSource (allowedBindMounts , parts [0 ])
181184}
182185
183186// validateBindMountSource checks if the source directory is allowed.
184- func validateBindMountSource (source string ) error {
187+ func validateBindMountSource (allowedBindMounts [] string , source string ) error {
185188 // Skip if source is not an absolute path (i.e. bind mount).
186189 if ! strings .HasPrefix (source , "/" ) {
187190 return nil
188191 }
189192
190193 source = filepath .Clean (source ) // Clean the path to resolve .. and . components.
191- for _ , allowedDir := range cfg . AllowBindMountFrom {
194+ for _ , allowedDir := range allowedBindMounts {
192195 if allowedDir == "/" || source == allowedDir || strings .HasPrefix (source , allowedDir + "/" ) {
193196 return nil
194197 }
0 commit comments