Security Overview
Environment variables often store sensitive information, making secure handling critical. This document outlines the security architecture and core features of the env library.
Security Architecture
┌──────────────────────────────────────────────────────────────┐
│ Application Layer │
├──────────────────────────────────────────────────────────────┤
│ SecureValue │ Masking │ Zeroing │ Memory Locking │
├──────────────────────────────────────────────────────────────┤
│ Loader Layer │
├──────────────────────────────────────────────────────────────┤
│ Key Validation │ Value Validation │ Forbidden Keys │ Size Limits │
├──────────────────────────────────────────────────────────────┤
│ Parsing Layer │
├──────────────────────────────────────────────────────────────┤
│ Format Detection │ Expansion Check │ Path Validation │
└──────────────────────────────────────────────────────────────┘Core Security Features
| Feature | Description | Documentation |
|---|---|---|
| SecureValue | Memory protection and auto-zeroing for sensitive values | SecureValue API |
| Forbidden keys | Prevents modification of system-critical variables | Constants & Errors |
| Sensitive key detection | Auto-identifies sensitive config keys, log masking tools | Data Masking |
| Value validation | Detects control characters, null bytes, etc. | Config API |
| Audit logging | Complete operation tracking | Component Factory |
SecureValue Overview
For sensitive data, use GetSecure instead of GetString:
// Not recommended
password := env.GetString("DB_PASSWORD")
// Recommended
secret := env.GetSecure("DB_PASSWORD")
defer secret.Close()
password := secret.Reveal() // Only call when plaintext is neededCore features:
- Memory locking - Prevents swapping to disk (Linux/macOS/Windows only; on other platforms
IsMemoryLockSupported()returns false with graceful degradation) - Auto-zeroing - Safely erases memory on
Close() - Masked display -
Masked()for log output - Thread safety - Supports concurrent reads
Full API
See SecureValue API.
Log Security
SecureValue protects sensitive values in memory, but logs, error messages, and debug output are equally prone to leaking keys. env provides a set of standalone masking utility functions that can be used without a Loader:
IsSensitiveKeyauto-detects sensitive key names like passwords, keys, and tokensMaskValue/MaskKeymask values and key names before outputSanitizeForLogscans log strings forkey=valuepatterns and masks them
// Safely output configuration in logs, avoiding plaintext leakage
log.Printf("Loading config: %s", env.MaskValue("DB_PASSWORD", password))
// Output: Loading config: [MASKED:12 chars]
log.Printf("Connection params: %s", env.SanitizeForLog("user=admin password=s3cret"))
// Output: Connection params: user=admin password=[MASKED]Full guide
For complete usage of masking tools, see Data Masking.
Key/Value Validation
Key Validation
Default key name rules: ^[A-Za-z][A-Za-z0-9_]*$
- Starts with a letter
- Contains only letters, numbers, and underscores
- Length does not exceed
MaxKeyLength
Forbidden Keys
Built-in forbidden keys prevent modification of system-critical variables:
| Category | Examples | Risk |
|---|---|---|
| System path | PATH, LD_LIBRARY_PATH | Command/library hijacking |
| Dynamic linking | LD_PRELOAD, DYLD_INSERT_LIBRARIES | Malicious library injection |
| Shell | SHELL, IFS, BASH_ENV | Shell hijacking |
| Language runtimes | PYTHONPATH, NODE_PATH | Module hijacking |
| Windows system | COMSPEC, PATHEXT, SYSTEMROOT, WINDIR | Command interpreter / system path hijacking |
Full list
See DefaultForbiddenKeys for the complete forbidden keys list.
Value Validation
Enable value validation to detect potential dangers:
cfg := env.ProductionConfig()
cfg.ValidateValues = true // Detect control characters, null bytes, etc.File Security Basics
File Permissions
# Readable/writable by owner only
chmod 600 .env
# Or stricter (read-only)
chmod 400 .envGit Ignore
.env
.env.local
.env.*.local
*.pem
*.keyConfiguration Security Levels
| Preset | Purpose | Characteristics |
|---|---|---|
DevelopmentConfig() | Development | Relaxed limits, YAML syntax support |
TestingConfig() | Testing | Overwrites existing variables, test isolation |
ProductionConfig() | Production | Strict validation + audit logging, no overwriting |
// Recommended production configuration
cfg := env.ProductionConfig()
cfg.RequiredKeys = []string{"DB_HOST", "API_KEY"}
cfg.AllowedKeys = []string{"APP_NAME", "PORT", "DB_HOST", "API_KEY"}Expansion Scope Isolation
Variable expansion resolves file-first, process-environment-second by default. For untrusted configuration sources, ExpansionScope: ExpansionFileOnly restricts references to inside the file, blocking a config file from probing and capturing process secrets (cloud credentials, tokens, etc.) (SEC-03). Configuration and attack scenarios are covered in Variable Expansion · Expansion Scope.
Related Documentation
- SecureValue API - Complete API for secure value handling
- Memory Locking - Complete mlock memory protection guide
- Constants & Errors - Complete forbidden keys list, sensitive key patterns
- Production Checklist - Pre-launch security checks