How do I handle secrets and environment configuration?
← Security and Sanitization · Ref: Q271
EK9 handles secrets through the EnvVars type, which provides auto-sanitized access to environment variables. This aligns with the 12-factor app methodology and container practices.
ENVVARS API
The EnvVars type provides:
env <- EnvVars() env.get(name) Auto-sanitized: blocks SQL, XSS, command injection but allows system paths env.unsanitizedGet(name) Raw value with no sanitization env contains name Check if variable exists env.keys() Iterate all variable names
AUTO-SANITIZATION
The get() method runs InputSanitizer automatically. This blocks injection patterns in environment variable values while allowing legitimate system paths like /usr/bin. Use unsanitizedGet() only when you specifically need raw values.
GUARD PATTERN
Combine EnvVars with guard expressions for safe access:
env <- EnvVars() if apiKey <- env.get("API_KEY") processWithKey(apiKey) else stderr.println("API_KEY not configured")
The guard handles both missing variables and sanitization failures in one line.
SANITIZED FORWARDING
Pass secrets to functions via sanitized parameters to prevent accidental logging:
connectToService()
-> apiKey as sanitized String
The compiler tracks the tainted status through the call chain.
WHAT NOT TO DO
Never embed secrets in source code. Never log secret values (sanitized tracking helps prevent this). Never store secrets in the .ek9 build directory. Never use unsanitizedGet without a specific reason.
INDUSTRY ALIGNMENT
Environment variables are the industry standard for secrets. Docker and Kubernetes inject secrets as env vars. Vault and AWS Secrets Manager ultimately deliver values through env vars. The 12-factor app methodology specifies env vars for configuration. EK9's EnvVars type with auto-sanitization goes beyond what most languages provide.
See Q215 for sanitized parameters. See Q29 for unset variables and guard patterns. See Q74 for guard expressions. See Q268 for OWASP vulnerability prevention. See Q272 for defense in depth.
Example
defines module qa.security.secrets defines function // Accept sanitized secret for processing connectToService() as pure -> apiKey as sanitized String <- result as String: "No key provided" // Copy constructor for defensive copy safeKey <- String(apiKey) if safeKey? result: "Connected with key length: " + $length safeKey defines program SecretsAndEnvDemo() stdout <- Stdout() stderr <- Stderr() // === READ ENVIRONMENT VARIABLES === env <- EnvVars() // Auto-sanitized access with guard if path <- env.get("PATH") stdout.println("PATH available, length: " + $length path) else stdout.println("PATH not available") // === CHECK EXISTENCE === if env contains "HOME" stdout.println("HOME is configured") // === GUARD PATTERN FOR SECRETS === if apiKey <- env.get("API_KEY") // Pass as sanitized to maintain tracking result <- connectToService(apiKey) if result? stdout.println(result) else stderr.println("API_KEY not configured") // === ITERATE AVAILABLE KEYS === stdout.println("Environment variable access patterns:") stdout.println(" get() — auto-sanitized") stdout.println(" unsanitizedGet() — raw value") stdout.println(" contains — check existence") stdout.println(" keys() — iterate names")
Common mistakes
E50001 — Renaming the variable means later references to 'env' become unresolved, triggering E50001. Variable names must be consistent. See ek9 -h E50001 for details.
Incorrect:
envXYZ <- EnvVars()
Correct:
env <- EnvVars()
E50001 — Renaming the variable means later references to 'result' become unresolved, triggering E50001. Variable names must be consistent. See ek9 -h E50001 for details.
Incorrect:
resultXYZ <- connectToService(apiKey)
Correct:
result <- connectToService(apiKey)
Other ways to ask this
- How do I read environment variables in EK9?
- How does EK9 handle API keys and credentials?
- What is the best way to manage secrets in EK9?
Coming from another language?
Java: System.getenv() returns raw String, no sanitization. Python: os.environ with no safety. Go: os.Getenv returns raw string. Rust: std::env::var returns raw string. Kotlin: System.getenv() with no sanitization. EK9: EnvVars.get() auto-sanitizes blocking injection patterns, unsanitizedGet() for raw access, guard pattern for missing variables.
Keywords: env, variable, sensitive, secret, protect, config, password, api, credential, token, security, environment, safe, key