validateEnvSecretsSection checks a single config map's "env" key for secrets. sectionName is used in log and error messages (e.g. "env" or "engine.env"). allowedEnvVarKeys is an optional set of env var key names whose secret values are permitted (used for engine.env to allow overriding engine env va
(config map[string]any, sectionName string, allowedEnvVarKeys map[string]struct {
})
| 88 | // allowedEnvVarKeys is an optional set of env var key names whose secret values are |
| 89 | // permitted (used for engine.env to allow overriding engine env vars). |
| 90 | func (c *Compiler) validateEnvSecretsSection(config map[string]any, sectionName string, allowedEnvVarKeys map[string]struct { |
| 91 | }) error { |
| 92 | envValue, exists := config["env"] |
| 93 | if !exists { |
| 94 | strictModeValidationLog.Printf("No %s section found, validation passed", sectionName) |
| 95 | return nil |
| 96 | } |
| 97 | |
| 98 | // Check if env is a map[string]any |
| 99 | envMap, ok := envValue.(map[string]any) |
| 100 | if !ok { |
| 101 | strictModeValidationLog.Printf("%s section is not a map, skipping validation", sectionName) |
| 102 | return nil |
| 103 | } |
| 104 | |
| 105 | // Convert to map[string]string for secret extraction, skipping keys whose secrets |
| 106 | // are explicitly allowed (e.g. engine env var overrides in engine.env). |
| 107 | envStrings := make(map[string]string) |
| 108 | for key, value := range envMap { |
| 109 | if allowedEnvVarKeys != nil && setutil.Contains(allowedEnvVarKeys, key) { |
| 110 | strictModeValidationLog.Printf("Skipping allowed engine env var key in %s: %s", sectionName, key) |
| 111 | continue |
| 112 | } |
| 113 | if strValue, ok := value.(string); ok { |
| 114 | envStrings[key] = strValue |
| 115 | } |
| 116 | } |
| 117 | |
| 118 | // Extract secrets from env values |
| 119 | secrets := ExtractSecretsFromMap(envStrings) |
| 120 | if len(secrets) == 0 { |
| 121 | strictModeValidationLog.Printf("No secrets found in %s section", sectionName) |
| 122 | return nil |
| 123 | } |
| 124 | |
| 125 | // Build list of secret references found |
| 126 | var secretRefs []string |
| 127 | for _, secretExpr := range secrets { |
| 128 | secretRefs = append(secretRefs, secretExpr) |
| 129 | } |
| 130 | |
| 131 | strictModeValidationLog.Printf("Found %d secret(s) in %s section: %v", len(secrets), sectionName, secretRefs) |
| 132 | |
| 133 | // In strict mode, this is an error |
| 134 | if c.strictMode { |
| 135 | return fmt.Errorf("strict mode: secrets detected in '%s' section will be leaked to the agent container. Found: %s. Use engine-specific secret configuration instead. See: https://github.github.com/gh-aw/reference/engines/", sectionName, strings.Join(secretRefs, ", ")) |
| 136 | } |
| 137 | |
| 138 | // In non-strict mode, emit a warning |
| 139 | warningMsg := fmt.Sprintf("Warning: secrets detected in '%s' section will be leaked to the agent container. Found: %s. Consider using engine-specific secret configuration instead.", sectionName, strings.Join(secretRefs, ", ")) |
| 140 | fmt.Fprintln(os.Stderr, console.FormatWarningMessage(warningMsg)) |
| 141 | c.IncrementWarningCount() |
| 142 | |
| 143 | return nil |
| 144 | } |
no test coverage detected