1717package compose
1818
1919import (
20+ "bytes"
2021 "context"
2122 "crypto/sha256"
2223 "errors"
2324 "fmt"
2425 "os"
2526
27+ "github.com/DefangLabs/secret-detector/pkg/scanner"
28+ "github.com/DefangLabs/secret-detector/pkg/secrets"
29+
2630 "github.com/compose-spec/compose-go/v2/loader"
2731 "github.com/compose-spec/compose-go/v2/types"
2832 "github.com/distribution/reference"
@@ -259,15 +263,37 @@ func (s *composeService) generateImageDigestsOverride(ctx context.Context, proje
259263 return override .MarshalYAML ()
260264}
261265
266+ //nolint:gocyclo
262267func (s * composeService ) preChecks (project * types.Project , options api.PublishOptions ) (bool , error ) {
263- if ok , err := s .checkOnlyBuildSection (project ); ! ok {
268+ if ok , err := s .checkOnlyBuildSection (project ); ! ok || err != nil {
269+ return false , err
270+ }
271+ if ok , err := s .checkForBindMount (project ); ! ok || err != nil {
272+ return false , err
273+ }
274+ if options .AssumeYes {
275+ return true , nil
276+ }
277+ detectedSecrets , err := s .checkForSensitiveData (project )
278+ if err != nil {
264279 return false , err
265280 }
281+ if len (detectedSecrets ) > 0 {
282+ fmt .Println ("you are about to publish sensitive data within your OCI artifact.\n " +
283+ "please double check that you are not leaking sensitive data" )
284+ for _ , val := range detectedSecrets {
285+ _ , _ = fmt .Fprintln (s .dockerCli .Out (), val .Type )
286+ _ , _ = fmt .Fprintf (s .dockerCli .Out (), "%q: %s\n " , val .Key , val .Value )
287+ }
288+ if ok , err := acceptPublishSensitiveData (s .dockerCli ); err != nil || ! ok {
289+ return false , err
290+ }
291+ }
266292 envVariables , err := s .checkEnvironmentVariables (project , options )
267293 if err != nil {
268294 return false , err
269295 }
270- if ! options . AssumeYes && len (envVariables ) > 0 {
296+ if len (envVariables ) > 0 {
271297 fmt .Println ("you are about to publish environment variables within your OCI artifact.\n " +
272298 "please double check that you are not leaking sensitive data" )
273299 for key , val := range envVariables {
@@ -276,17 +302,10 @@ func (s *composeService) preChecks(project *types.Project, options api.PublishOp
276302 _ , _ = fmt .Fprintf (s .dockerCli .Out (), "%s=%v\n " , k , * v )
277303 }
278304 }
279- return acceptPublishEnvVariables (s .dockerCli )
280- }
281-
282- for name , config := range project .Services {
283- for _ , volume := range config .Volumes {
284- if volume .Type == types .VolumeTypeBind {
285- return false , fmt .Errorf ("cannot publish compose file: service %q relies on bind-mount. You should use volumes" , name )
286- }
305+ if ok , err := acceptPublishEnvVariables (s .dockerCli ); err != nil || ! ok {
306+ return false , err
287307 }
288308 }
289-
290309 return true , nil
291310}
292311
@@ -332,6 +351,12 @@ func acceptPublishEnvVariables(cli command.Cli) (bool, error) {
332351 return confirm , err
333352}
334353
354+ func acceptPublishSensitiveData (cli command.Cli ) (bool , error ) {
355+ msg := "Are you ok to publish these sensitive data? [y/N]: "
356+ confirm , err := prompt .NewPrompt (cli .In (), cli .Out ()).Confirm (msg , false )
357+ return confirm , err
358+ }
359+
335360func envFileLayers (project * types.Project ) []ocipush.Pushable {
336361 var layers []ocipush.Pushable
337362 for _ , service := range project .Services {
@@ -367,3 +392,24 @@ func (s *composeService) checkOnlyBuildSection(project *types.Project) (bool, er
367392 }
368393 return true , nil
369394}
395+
396+ func (s * composeService ) checkForBindMount (project * types.Project ) (bool , error ) {
397+ for name , config := range project .Services {
398+ for _ , volume := range config .Volumes {
399+ if volume .Type == types .VolumeTypeBind {
400+ return false , fmt .Errorf ("cannot publish compose file: service %q relies on bind-mount. You should use volumes" , name )
401+ }
402+ }
403+ }
404+ return true , nil
405+ }
406+
407+ func (s * composeService ) checkForSensitiveData (project * types.Project ) ([]secrets.DetectedSecret , error ) {
408+ scan := scanner .NewDefaultScanner ()
409+
410+ input , err := project .MarshalYAML ()
411+ if err != nil {
412+ return nil , err
413+ }
414+ return scan .ScanReader (bytes .NewReader (input ))
415+ }
0 commit comments