MCPcopy
hub / github.com/docker/compose / collectEnvCheckFindings

Function collectEnvCheckFindings

pkg/compose/publish.go:473–517  ·  view source on GitHub ↗

collectEnvCheckFindings walks every compose file scheduled for publication (top-level files plus any local extends parents discovered along the way) and aggregates per-service and per-config findings. The walk mirrors processExtends so coverage matches what is actually serialized into the OCI artifa

(ctx context.Context, project *types.Project)

Source from the content-addressed store, hash-verified

471// processExtends so coverage matches what is actually serialized into the OCI
472// artifact.
473func collectEnvCheckFindings(ctx context.Context, project *types.Project) (*envCheckFindings, error) {
474 findings := &envCheckFindings{services: map[string]*serviceEnvFindings{}}
475 literalCfgs := map[string]struct{}{}
476 keywordDetector := keyword.NewDetector("0")
477
478 seen := map[string]struct{}{}
479 queue := slices.Clone(project.ComposeFiles)
480 for len(queue) > 0 {
481 file := queue[0]
482 queue = queue[1:]
483 if _, ok := seen[file]; ok {
484 continue
485 }
486 seen[file] = struct{}{}
487
488 unresolved, err := loadUnresolvedFile(ctx, project, file)
489 if err != nil {
490 return nil, fmt.Errorf("failed to load compose file %s: %w", file, err)
491 }
492
493 for _, service := range unresolved.Services {
494 recordServiceEnvFindings(findings.services, keywordDetector, service)
495 if parent := localExtendsParent(service); parent != "" {
496 queue = append(queue, parent)
497 }
498 }
499 for name, config := range unresolved.Configs {
500 // config.Environment is a variable *name* (only the name is
501 // published, not its resolved value) so it is not a leak. Inline
502 // config.Content is what ends up in the artifact. compose-go
503 // enforces that file, environment, and content are mutually
504 // exclusive. The map key is the name as written in the compose
505 // file; config.Name is the project-namespaced version, which is
506 // less helpful when surfaced to the user.
507 if config.Content != "" && configContentLooksLiteral(config.Content, keywordDetector) {
508 literalCfgs[name] = struct{}{}
509 }
510 }
511 }
512
513 if len(literalCfgs) > 0 {
514 findings.configsLiteralContent = sortedMapKeys(literalCfgs)
515 }
516 return findings, nil
517}
518
519func recordServiceEnvFindings(services map[string]*serviceEnvFindings, detector secrets.Detector, service types.ServiceConfig) {
520 envValues := map[string]string{}

Callers 2

Calls 5

loadUnresolvedFileFunction · 0.85
recordServiceEnvFindingsFunction · 0.85
localExtendsParentFunction · 0.85
sortedMapKeysFunction · 0.85

Tested by 1