15 KiB
Security Audit: Configuration Files and Environment Handling
Audit Date: 2026-02-08 Auditor: Security Engineer Scope: mcp-server/ configuration files, environment handling, secrets management Risk Rating: HIGH - Multiple insecure defaults and secret exposure risks identified
Executive Summary
This audit identified 11 security issues across configuration files, with severity ranging from Critical to Low. The primary concerns are insecure default values that could lead to production deployments without proper security hardening, and potential secret exposure in container environments.
Risk Distribution
- CRITICAL: 2 issues
- HIGH: 3 issues
- MEDIUM: 4 issues
- LOW: 2 issues
Critical Issues
1. Database SSL Disabled by Default in Compose
File: /mnt/ollama/git/agent-guardrails-template/mcp-server/deploy/podman-compose.yml:144
Risk: CRITICAL
- DB_SSLMODE=${DB_SSLMODE:-disable}
Security Risk:
- Database connections default to unencrypted communication
- Credentials and data transmitted in plaintext
- Susceptible to man-in-the-middle attacks
- Compliance violations (PCI-DSS, HIPAA, SOC2)
Recommendation:
# Change default to require minimum
- DB_SSLMODE=${DB_SSLMODE:-require}
# For production, use verify-full
- DB_SSLMODE=${DB_SSLMODE:-verify-full}
Remediation Priority: IMMEDIATE
2. Redis Authentication Disabled by Default in Compose
File: /mnt/ollama/git/agent-guardrails-template/mcp-server/deploy/podman-compose.yml:149
Risk: CRITICAL
- REDIS_USE_TLS=${REDIS_USE_TLS:-false}
Security Risk:
- Redis connections default to unencrypted communication
- Session data and cached secrets transmitted in plaintext
- Redis password exposed in environment variables
Recommendation:
# Enable TLS by default
- REDIS_USE_TLS=${REDIS_USE_TLS:-true}
# Add certificate verification
- REDIS_TLS_VERIFY=${REDIS_TLS_VERIFY:-true}
Remediation Priority: IMMEDIATE
High Issues
3. Permissive CORS Default
File: /mnt/ollama/git/agent-guardrails-template/mcp-server/.env.example:39
File: /mnt/ollama/git/agent-guardrails-template/mcp-server/deploy/podman-compose.yml:174
Risk: HIGH
# .env.example
CORS_ALLOWED_ORIGINS=*
# podman-compose.yml
CORS_ALLOWED_ORIGINS=${CORS_ALLOWED_ORIGINS:-*}
Security Risk:
- Allows cross-origin requests from any domain
- Enables CSRF attacks against the API
- Session hijacking via malicious websites
- Violates principle of least privilege
Recommendation:
# .env.example - No default, must be explicitly configured
CORS_ALLOWED_ORIGINS= # REQUIRED: Set to your domain(s)
# In config.go validation, reject wildcard in production
func (c *Config) Validate() error {
if c.ProductionMode && len(c.CORSAllowedOrigins) == 1 && c.CORSAllowedOrigins[0] == "*" {
return fmt.Errorf("CORS_ALLOWED_ORIGINS cannot be '*' in production mode")
}
// ...
}
Remediation Priority: HIGH
4. Redis Password Exposure in Health Check
File: /mnt/ollama/git/agent-guardrails-template/mcp-server/deploy/podman-compose.yml:39
Risk: HIGH
healthcheck:
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
Security Risk:
- Password visible in
docker inspectoutput - Password appears in container logs if health check fails
- Process listing may expose command with password
- Container runtime history stores password in plain text
Recommendation:
# Use Redis ACL file or environment file instead
healthcheck:
test: ["CMD", "redis-cli", "--raw", "incr", "ping"]
# Configure requirepass in redis.conf, not command line
Or use a health check script:
healthcheck:
test: ["CMD", "sh", "-c", "redis-cli -a \"$REDIS_PASSWORD\" ping | grep PONG"]
Remediation Priority: HIGH
5. Placeholder Secrets Could Be Used in Production
File: /mnt/ollama/git/agent-guardrails-template/mcp-server/.env.example:102-109
Risk: HIGH
MCP_API_KEY=generate_a_32_byte_random_key_here
IDE_API_KEY=generate_a_different_32_byte_random_key_here
JWT_SECRET=generate_a_64_byte_random_secret_here_for_jwt_signing
Security Risk:
- Placeholder values may be accidentally used in production
- No runtime validation to detect placeholder secrets
- Weak entropy in placeholder strings
- Predictable secrets enable authentication bypass
Recommendation:
Add validation in /mnt/ollama/git/agent-guardrails-template/mcp-server/internal/config/config.go:
func ValidateAPIKey(key, name string) error {
// Existing validation...
// Check for placeholder patterns
placeholders := []string{
"generate_a_",
"change_me",
"placeholder",
"example",
"test",
"demo",
"secret_here",
}
lowerKey := strings.ToLower(key)
for _, placeholder := range placeholders {
if strings.Contains(lowerKey, placeholder) {
return fmt.Errorf("%s appears to be a placeholder value", name)
}
}
return nil
}
Remediation Priority: HIGH
Medium Issues
6. Production Mode Defaults to False
File: /mnt/ollama/git/agent-guardrails-template/mcp-server/.env.example:182
File: /mnt/ollama/git/agent-guardrails-template/mcp-server/deploy/podman-compose.yml:130
Risk: MEDIUM
PRODUCTION_MODE=false
Security Risk:
- Stricter security checks disabled by default
- Debug features may be enabled unintentionally
- Security headers not enforced
- Rate limiting may be relaxed
Recommendation:
Make PRODUCTION_MODE required with no default:
# .env.example
PRODUCTION_MODE= # REQUIRED: Set to 'true' for production, 'false' for development
Add validation:
func (c *Config) Validate() error {
if !c.ProductionMode {
slog.Warn("Running in development mode - security features relaxed")
}
// ...
}
Remediation Priority: MEDIUM
7. TLS Minimum Version Allows 1.2
File: /mnt/ollama/git/agent-guardrails-template/mcp-server/internal/config/config.go:75
Risk: MEDIUM
TLSMinVersion string `env:"TLS_MIN_VERSION" envDefault:"1.3"`
File: /mnt/ollama/git/agent-guardrails-template/mcp-server/internal/config/config.go:214-216
if c.TLSMinVersion != "1.2" && c.TLSMinVersion != "1.3" {
return fmt.Errorf("TLS_MIN_VERSION must be 1.2 or 1.3, got %s", c.TLSMinVersion)
}
Security Risk:
- TLS 1.2 has known vulnerabilities (POODLE, BEAST)
- Allows downgrade attacks
- TLS 1.3 should be minimum for production
Recommendation:
func (c *Config) Validate() error {
if c.TLSEnabled {
// ...
if c.ProductionMode && c.TLSMinVersion != "1.3" {
return fmt.Errorf("TLS_MIN_VERSION must be 1.3 in production mode")
}
if c.TLSMinVersion != "1.2" && c.TLSMinVersion != "1.3" {
return fmt.Errorf("TLS_MIN_VERSION must be 1.2 or 1.3, got %s", c.TLSMinVersion)
}
}
// ...
}
Remediation Priority: MEDIUM
8. Database Password in .env.example Uses Weak Placeholder
File: /mnt/ollama/git/agent-guardrails-template/mcp-server/.env.example:62
Risk: MEDIUM
DB_PASSWORD=change_me_in_production
Security Risk:
- Weak placeholder may be used accidentally
- No validation prevents this value in production
- Common pattern that attackers test for
Recommendation:
# Leave empty to force configuration
DB_PASSWORD= # REQUIRED: Generate strong password with: openssl rand -base64 32
Add validation in config.go:
func (c *Config) Validate() error {
weakPasswords := []string{
"change_me_in_production",
"password",
"admin",
"123456",
"guardrail",
}
for _, weak := range weakPasswords {
if c.DBPassword == weak {
return fmt.Errorf("DB_PASSWORD is using a weak/placeholder value")
}
}
// ...
}
Remediation Priority: MEDIUM
9. JWT Rotation Period Too Long
File: /mnt/ollama/git/agent-guardrails-template/mcp-server/.env.example:112
Risk: MEDIUM
JWT_ROTATION_HOURS=168 # 7 days
Security Risk:
- Long rotation period increases exposure window
- Compromised tokens valid for extended period
- No mechanism for emergency rotation
Recommendation:
# Reduce default to 24 hours
JWT_ROTATION_HOURS=24
# Add maximum validation
func ValidateTimeout(name string, value, min, max time.Duration) error {
// Add maximum JWT rotation check
if name == "JWT_ROTATION_HOURS" && value > 168*time.Hour {
return fmt.Errorf("JWT_ROTATION_HOURS should not exceed 168 hours (7 days)")
}
// ...
}
Remediation Priority: MEDIUM
Low Issues
10. Secrets Passed via Environment Variables in Compose
File: /mnt/ollama/git/agent-guardrails-template/mcp-server/deploy/podman-compose.yml:117-179
Risk: LOW
Security Risk:
- Secrets visible in
docker inspectoutput - Environment variables may be logged by orchestration tools
- Process listing (
ps e) exposes environment
Recommendation: Use Docker secrets or external secret management:
services:
mcp-server:
secrets:
- db_password
- redis_password
- jwt_secret
- mcp_api_key
- ide_api_key
environment:
- DB_PASSWORD_FILE=/run/secrets/db_password
# ...
secrets:
db_password:
file: ./secrets/db_password.txt
redis_password:
file: ./secrets/redis_password.txt
# Or use external secrets manager
Update config.go to support _FILE suffix:
func loadSecretFromFile(envVar string) string {
fileVar := envVar + "_FILE"
if path := os.Getenv(fileVar); path != "" {
data, err := os.ReadFile(path)
if err != nil {
slog.Warn("Failed to read secret file", "file", path, "error", err)
return ""
}
return strings.TrimSpace(string(data))
}
return os.Getenv(envVar)
}
Remediation Priority: LOW
11. No Cipher Suite Configuration for TLS
File: /mnt/ollama/git/agent-guardrails-template/mcp-server/internal/config/config.go:70-76
Risk: LOW
Security Risk:
- Default cipher suites may include weak ciphers
- No protection against SWEET32 or other cipher-based attacks
- Missing forward secrecy enforcement
Recommendation: Add cipher suite configuration:
// Config struct addition
TLSCipherSuites []string `env:"TLS_CIPHER_SUITES" envDefault:"TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256,TLS_AES_128_GCM_SHA256"`
// Validation
func (c *Config) Validate() error {
if c.TLSEnabled {
weakCiphers := []string{
"TLS_RSA_WITH_RC4_128_SHA",
"TLS_RSA_WITH_3DES_EDE_CBC_SHA",
"TLS_RSA_WITH_AES_128_CBC_SHA",
"TLS_RSA_WITH_AES_256_CBC_SHA",
}
// Validate no weak ciphers selected
}
// ...
}
Remediation Priority: LOW
Positive Security Findings
The following security controls are properly implemented:
1. Secret Masking in Config
File: /mnt/ollama/git/agent-guardrails-template/mcp-server/internal/config/config.go:391-400
func (c *Config) Masked() *Config {
masked := *c
masked.DBPassword = "***"
masked.RedisPassword = "***"
masked.MCPAPIKey = "***"
masked.IDEAPIKey = "***"
masked.JWTSecret = "***"
return &masked
}
Status: GOOD - Proper secret masking for logging
2. Kubernetes Secrets Usage
File: /mnt/ollama/git/agent-guardrails-template/mcp-server/deploy/k8s-deployment.yaml:64-122
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: guardrail-db-credentials
key: password
Status: GOOD - Proper Kubernetes secrets integration
3. Security Context in Kubernetes
File: /mnt/ollama/git/agent-guardrails-template/mcp-server/deploy/k8s-deployment.yaml:29-33,146-151
securityContext:
runAsNonRoot: true
runAsUser: 65532
runAsGroup: 65532
fsGroup: 65532
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
Status: GOOD - Proper security hardening
4. Network Policies
File: /mnt/ollama/git/agent-guardrails-template/mcp-server/deploy/k8s-deployment.yaml:218-260
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
Status: GOOD - Network segmentation properly configured
5. Non-root Container User
File: /mnt/ollama/git/agent-guardrails-template/mcp-server/deploy/Dockerfile:31-38
FROM gcr.io/distroless/static:nonroot
USER 65532:65532
Status: GOOD - Principle of least privilege followed
Compliance Mapping
| Issue | PCI-DSS | SOC2 | ISO 27001 | NIST 800-53 |
|---|---|---|---|---|
| Database SSL disabled | 4.1, 4.2 | CC6.7 | A.13.2.1 | SC-8, SC-13 |
| Redis TLS disabled | 4.1, 4.2 | CC6.7 | A.13.2.1 | SC-8, SC-13 |
| Permissive CORS | 6.5.9 | CC6.6 | A.14.1.2 | AC-2, AC-3 |
| Placeholder secrets | 8.2.1 | CC6.1 | A.9.2.1 | IA-5 |
| Password exposure | 8.2.1 | CC6.1 | A.9.4.3 | SC-28 |
Remediation Checklist
- Change
DB_SSLMODEdefault fromdisabletorequirein podman-compose.yml - Change
REDIS_USE_TLSdefault fromfalsetotruein podman-compose.yml - Remove
CORS_ALLOWED_ORIGINS=*default, make it required - Fix Redis health check to not expose password in command
- Add placeholder detection to config validation
- Make
PRODUCTION_MODErequired with no default - Enforce TLS 1.3 minimum in production mode
- Add
_FILEsuffix support for Docker secrets - Document secret generation procedures
- Add pre-deployment security validation script
Appendix A: Secure Configuration Template
# Production-ready .env file template
PRODUCTION_MODE=true
# Server
MCP_PORT=8080
WEB_PORT=8081
LOG_LEVEL=warn
# Database (SSL required)
DB_HOST=postgres.example.com
DB_PORT=5432
DB_NAME=guardrails
DB_USER=guardrail
DB_PASSWORD=<GENERATE_STRONG_PASSWORD>
DB_SSLMODE=verify-full
# Redis (TLS required)
REDIS_HOST=redis.example.com
REDIS_PORT=6379
REDIS_PASSWORD=<GENERATE_STRONG_PASSWORD>
REDIS_USE_TLS=true
# TLS (Required for production)
TLS_ENABLED=true
TLS_CERT_PATH=/etc/ssl/certs/server.crt
TLS_KEY_PATH=/etc/ssl/private/server.key
TLS_CA_PATH=/etc/ssl/certs/ca.crt
TLS_MIN_VERSION=1.3
# Secrets (Generate with: openssl rand -hex 32)
MCP_API_KEY=<64_CHAR_HEX_STRING>
IDE_API_KEY=<64_CHAR_HEX_STRING>
JWT_SECRET=<128_CHAR_HEX_STRING>
# CORS (Explicit origins only)
CORS_ALLOWED_ORIGINS=https://app.example.com,https://admin.example.com
# Security
PPROF_ENABLED=false
RATE_LIMIT_MCP=1000
RATE_LIMIT_IDE=500
End of Security Audit Report