Problem
Go microservices commonly include API keys in configuration structs that get logged at startup or included in error messages:
// Config logged at startup:
cfg := Config{
OpenAIKey: os.Getenv("OPENAI_API_KEY"),
Port: "8080",
}
log.Printf("Starting service with config: %+v", cfg)
// Output: Starting service with config: {OpenAIKey:sk-xxx... Port:8080}
Or embedded as string constants:
const OPENAI_KEY = "sk-proj-..." // committed to git
Proposed Fix
- Never log structs containing secrets. Use a custom
String() method that redacts sensitive fields:
type Config struct {
OpenAIKey string
Port string
}
// Prevents accidental logging of the key:
func (c Config) String() string {
return fmt.Sprintf("{Port:%s OpenAIKey:[REDACTED]}", c.Port)
}
// Safe to log:
log.Printf("Starting service with config: %s", cfg)
- Fail fast if key is missing:
func loadConfig() Config {
key := os.Getenv("OPENAI_API_KEY")
if key == "" {
log.Fatal("OPENAI_API_KEY environment variable is required")
}
return Config{OpenAIKey: key, Port: os.Getenv("PORT")}
}
- Add
.env to .gitignore and run git log --all -S 'sk-' --source to check for past leaks.
Acceptance Criteria
Problem
Go microservices commonly include API keys in configuration structs that get logged at startup or included in error messages:
Or embedded as string constants:
Proposed Fix
String()method that redacts sensitive fields:.envto.gitignoreand rungit log --all -S 'sk-' --sourceto check for past leaks.Acceptance Criteria
String()method that redacts all secret fieldstrufflehogorgitleaksto detect accidental secret commits.env.exampledocuments all required secrets without values