Skip to main content

Overview

This checklist covers all critical security areas that should be audited before and during production deployment. Use this as a systematic guide to ensure your MCP Server deployment meets security best practices.
Do not deploy to production until all critical items are addressed. High and critical items must be resolved; medium items should be planned for resolution.

Authentication & Authorization

Keycloak Configuration

Critical:
  • Admin password changed from default
  • Admin console access restricted to internal network
  • HTTPS enabled for all Keycloak endpoints
  • Session timeout configured (max 24 hours)
  • Brute force detection enabled
  • Email verification required for new users
High:
  • MFA/2FA enabled for admin accounts
  • Password policy enforced (min 12 characters, complexity)
  • Account lockout after failed attempts
  • Security headers configured
  • CORS properly configured
Verification:
# Check admin password
kubectl exec -it keycloak-0 -n mcp-server-langgraph -- \
  /opt/keycloak/bin/kcadm.sh get users/admin

# Verify HTTPS
curl -I https://auth.yourdomain.com

# Check brute force settings
kubectl exec -it keycloak-0 -n mcp-server-langgraph -- \
  /opt/keycloak/bin/kcadm.sh get realms/mcp-agent | grep bruteForce
Critical:
  • JWT secret is cryptographically secure (>= 32 bytes)
  • JWT secret rotated from default value
  • JWT secret stored in secret management system
  • Token expiration set appropriately (< 1 hour)
  • Refresh token rotation enabled
  • Algorithm set to RS256 or ES256 (not HS256)
High:
  • JWK rotation configured
  • Token revocation mechanism implemented
  • Audience (aud) claim validated
  • Issuer (iss) claim validated
Verification:
# Check JWT secret length
kubectl get secret mcp-server-langgraph-secrets -n mcp-server-langgraph \
  -o jsonpath='{.data.JWT_SECRET}' | base64 -d | wc -c

# Verify token expiration
# Decode a JWT token and check 'exp' claim
Critical:
  • Authorization model defined and tested
  • Default deny policy in place
  • Admin access properly restricted
  • Permission checks on all sensitive operations
  • OpenFGA TLS enabled
High:
  • Authorization logging enabled
  • Regular audit of permission tuples
  • Least privilege principle enforced
  • Authorization tests in CI/CD
Verification:
# Test authorization
curl -X POST http://openfga:8080/stores/xxx/check \
  -H "Content-Type: application/json" \
  -d '{
    "tuple_key": {
      "user": "user:alice",
      "relation": "admin",
      "object": "organization:acme"
    }
  }'

# Check TLS
kubectl get svc openfga -n mcp-server-langgraph -o yaml | grep tls

Secrets Management

Infrastructure Secrets

Critical:
  • No secrets in code or git repository
  • All secrets in Infisical/Vault/Cloud Secret Manager
  • .env files in .gitignore
  • Container images don’t contain secrets
  • Kubernetes secrets encrypted at rest
High:
  • Secret rotation policy defined (90 days max)
  • Automated secret rotation configured
  • Secret access auditing enabled
  • Secrets have expiration dates
Verification:
# Check for secrets in git
git secrets --scan

# Check for hardcoded secrets
grep -r "ANTHROPIC_API_KEY\|sk-ant-" src/

# Verify Kubernetes encryption
kubectl get secret mcp-server-langgraph-secrets -n mcp-server-langgraph \
  -o yaml | grep -i encrypt
Critical:
  • LLM API keys rotated from initial values
  • API keys have usage limits configured
  • API keys scoped to minimum permissions
  • Backup API keys available
High:
  • API key usage monitoring enabled
  • Alerts on suspicious API usage
  • API keys rotated every 90 days
Verification:
# Check API key age
kubectl get secret mcp-server-langgraph-secrets -n mcp-server-langgraph \
  -o json | jq '.metadata.creationTimestamp'

# Monitor Anthropic usage
curl https://api.anthropic.com/v1/usage \
  -H "x-api-key: $ANTHROPIC_API_KEY"
Critical:
  • Database passwords changed from defaults
  • Database users have minimum required privileges
  • Production database not accessible from internet
  • SSL/TLS enforced for database connections
High:
  • Database password rotation configured
  • Connection pooling with authentication
  • Database audit logging enabled
Verification:
# Test database connection
PGPASSWORD=$DB_PASSWORD psql -h $DB_HOST -U $DB_USER -c "SELECT version();"

# Check SSL
PGPASSWORD=$DB_PASSWORD psql -h $DB_HOST -U $DB_USER \
  -c "SHOW ssl;" | grep on

Network Security

Network Configuration

Critical:
  • HTTPS enabled for all public endpoints
  • Valid TLS certificates (not self-signed)
  • TLS 1.2+ only (1.0/1.1 disabled)
  • Strong cipher suites configured
  • HSTS header enabled
High:
  • Certificate auto-renewal configured
  • Certificate expiry monitoring
  • OCSP stapling enabled
  • Perfect forward secrecy (PFS) enabled
Verification:
# Check TLS version
nmap --script ssl-enum-ciphers -p 443 api.yourdomain.com

# Test SSL configuration
testssl.sh https://api.yourdomain.com

# Check HSTS
curl -I https://api.yourdomain.com | grep Strict-Transport-Security
Critical:
  • Network policies defined for all namespaces
  • Default deny ingress/egress in place
  • Least privilege network access
  • Pods can’t access cluster API by default
High:
  • Network policies tested
  • Egress filtering configured
  • Service mesh for mTLS (optional)
Verification:
# List network policies
kubectl get networkpolicies -A

# Test connectivity
kubectl run test --rm -it --image=alpine -- sh
# Try to connect to restricted services
Critical:
  • Only required ports exposed
  • Admin interfaces not publicly accessible
  • Rate limiting configured
  • DDoS protection enabled
High:
  • WAF rules configured
  • IP whitelisting for admin access
  • Geographic restrictions (if applicable)
  • Load balancer health checks configured
Verification:
# Check exposed ports
nmap -p- api.yourdomain.com

# Test rate limiting
ab -n 1000 -c 100 https://api.yourdomain.com/

# Check firewall rules
gcloud compute firewall-rules list  # GCP
aws ec2 describe-security-groups    # AWS

Application Security

Code Security

Critical:
  • No critical vulnerabilities in dependencies
  • All dependencies from trusted sources
  • Lock files committed (requirements.txt, package-lock.json)
  • Dependency scanning in CI/CD
High:
  • Regular dependency updates
  • Automated vulnerability scanning
  • SBOM (Software Bill of Materials) generated
Verification:
# Scan Python dependencies
pip-audit

# Scan with safety
safety check

# Check for outdated packages
pip list --outdated
Critical:
  • All user input validated
  • SQL injection protection
  • XSS protection
  • Command injection prevention
  • File upload validation
High:
  • Input sanitization
  • Output encoding
  • CSRF protection
  • Rate limiting per endpoint
Verification:
# Review input validation
grep -r "request.query" src/
grep -r "request.body" src/

# Check for Pydantic models
find src/ -name "*.py" -exec grep -l "BaseModel" {} \;
Critical:
  • Security events logged
  • Sensitive data not logged (passwords, tokens)
  • Logs centralized and searchable
  • Log retention policy defined
High:
  • Structured logging (JSON)
  • Log tampering prevention
  • Alerting on security events
  • SIEM integration
Verification:
# Check for sensitive data in logs
kubectl logs deployment/mcp-server-langgraph -n mcp-server-langgraph | \
  grep -i "password\|secret\|token"

# Verify structured logging
kubectl logs deployment/mcp-server-langgraph -n mcp-server-langgraph | jq .

Container Security

Image Security

Critical:
  • Images from trusted registries only
  • Image vulnerability scanning enabled
  • No critical vulnerabilities in images
  • Images signed and verified
  • Non-root user in containers
High:
  • Minimal base images (distroless, alpine)
  • Multi-stage builds
  • Image scanning in CI/CD
  • Regular image updates
Verification:
# Scan image
trivy image mcp-server-langgraph:latest

# Check for root user
docker inspect mcp-server-langgraph:latest | grep -i "user"

# Verify image signature
cosign verify mcp-server-langgraph:latest
Critical:
  • Read-only root filesystem
  • Privilege escalation disabled
  • Capabilities dropped
  • seccomp profile applied
  • AppArmor/SELinux enabled
High:
  • Pod Security Standards enforced
  • Runtime security monitoring (Falco)
  • Resource limits defined
Verification:
# Check security context
kubectl get pod mcp-server-langgraph-${POD_ID} -n mcp-server-langgraph \
  -o yaml | grep -A 10 securityContext

# Verify Pod Security Standards
kubectl label namespace mcp-server-langgraph \
  pod-security.kubernetes.io/enforce=restricted

Data Protection

Data Security

Critical:
  • Data encrypted in transit (TLS)
  • Data encrypted at rest (database, Redis, volumes)
  • Encryption keys managed securely
  • Kubernetes secrets encrypted
High:
  • Key rotation configured
  • HSM or KMS for key management
  • Encryption for backups
Verification:
# Check database encryption
kubectl exec postgres-0 -n mcp-server-langgraph -- \
  psql -c "SHOW ssl;" | grep on

# Check Redis TLS
redis-cli -h redis-master --tls ping

# Verify Kubernetes encryption
kubectl get secret -n kube-system encryption-config
Critical:
  • Automated backups configured
  • Backups encrypted
  • Backup restoration tested
  • Backup retention policy defined
  • Off-site backup storage
High:
  • Point-in-time recovery available
  • Backup monitoring and alerts
  • DR plan documented
Verification:
# List backups
velero backup get

# Test restore (in staging)
velero restore create --from-backup backup-name

# Check backup encryption
aws s3api get-object --bucket backups --key latest \
  --server-side-encryption AES256
Critical:
  • PII handling documented
  • Data retention policy enforced
  • Right to deletion implemented
  • Data minimization practiced
  • Privacy policy published
High:
  • Consent management
  • Data portability
  • Privacy by design
  • GDPR/CCPA compliance (if applicable)
Verification:
# Check for PII logging
grep -r "email\|phone\|ssn" src/logs/

# Verify data deletion
# Test user deletion endpoint

Kubernetes Security

Cluster Security

Critical:
  • RBAC enabled
  • Principle of least privilege
  • No cluster-admin for apps
  • Service accounts for workloads
  • No default service account used
High:
  • Regular RBAC audit
  • Namespaced roles
  • RBAC testing
Verification:
# List cluster roles
kubectl get clusterrolebindings

# Check service account permissions
kubectl auth can-i --list --as=system:serviceaccount:mcp-server-langgraph:mcp-server-langgraph

# Audit RBAC
kubectl auth reconcile -f rbac.yaml --dry-run
Critical:
  • Pod Security Standards enforced
  • hostNetwork disabled
  • hostPID disabled
  • hostIPC disabled
  • Privileged pods not allowed
High:
  • SecurityContext on all pods
  • runAsNonRoot enforced
  • allowPrivilegeEscalation: false
Verification:
# Check Pod Security Admission
kubectl get ns mcp-server-langgraph -o yaml | grep pod-security

# Scan for privileged pods
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.securityContext.privileged}{"\n"}{end}'
Critical:
  • API server not publicly accessible
  • Anonymous auth disabled
  • Audit logging enabled
  • Admission controllers configured
  • API server TLS verified
High:
  • API rate limiting
  • Webhook timeout configured
  • Audit logs reviewed regularly
Verification:
# Check API server access
kubectl cluster-info

# Verify audit log
kubectl get pods -n kube-system | grep kube-apiserver

# Check admission controllers
kubectl -n kube-system get pod kube-apiserver-xxx \
  -o yaml | grep enable-admission-plugins

Compliance & Governance

Compliance

Critical:
  • Security policy documented
  • Incident response plan
  • Access control policy
  • Change management process
  • Security training for team
High:
  • Security champions assigned
  • Regular security reviews
  • Penetration testing scheduled
  • Bug bounty program (optional)
Verification:
  • Review policy documents
  • Check training records
  • Verify incident response tests
Critical:
  • Audit logs enabled everywhere
  • Compliance requirements identified
  • Regular compliance audits
  • Audit log retention (1 year min)
High:
  • SOC 2 / ISO 27001 certification
  • GDPR/CCPA compliance
  • Third-party audits
  • Compliance automation
Verification:
# Check audit logs
kubectl logs -n kube-system kube-apiserver-xxx | grep audit

# Verify log retention
kubectl get cm -n kube-system audit-policy -o yaml

Pre-Production Checklist

Use this before deploying to production:
### Critical Items (Must Fix)
- [ ] All authentication endpoints use HTTPS
- [ ] No default passwords in use
- [ ] All secrets in secret management system
- [ ] Database not publicly accessible
- [ ] TLS 1.2+ enforced
- [ ] Network policies implemented
- [ ] No critical vulnerabilities in images
- [ ] Backup and restore tested
- [ ] Audit logging enabled
- [ ] RBAC properly configured

### High Priority (Should Fix)
- [ ] MFA enabled for admin accounts
- [ ] Secret rotation configured
- [ ] API rate limiting enabled
- [ ] WAF configured
- [ ] Container images scanned
- [ ] Pod Security Standards enforced
- [ ] Monitoring and alerting set up
- [ ] Incident response plan documented

### Medium Priority (Plan to Fix)
- [ ] Automated security testing
- [ ] Regular penetration testing
- [ ] Security training completed
- [ ] Compliance certifications
- [ ] Bug bounty program

Automated Security Scanning

## Run security scan suite
./scripts/security-audit.sh
security-audit.sh:
#!/bin/bash
set -e

echo "=== Running Security Audit ==="

## 1. Check for secrets in code
echo "Checking for hardcoded secrets..."
git secrets --scan || true

## 2. Scan dependencies
echo "Scanning Python dependencies..."
pip-audit

## 3. Scan container images
echo "Scanning container images..."
trivy image mcp-server-langgraph:latest

## 4. Check Kubernetes configuration
echo "Checking Kubernetes configs..."
kubectl kustomize overlays/production | kubesec scan -

## 5. Network policy check
echo "Verifying network policies..."
kubectl get networkpolicies -A

## 6. RBAC audit
echo "Auditing RBAC..."
kubectl auth can-i --list --as=system:serviceaccount:mcp-server-langgraph:mcp-server-langgraph

## 7. Check for exposed secrets
echo "Checking for exposed secrets..."
kubectl get secrets -A -o json | grep -i "password\|token\|key" || true

echo "=== Security Audit Complete ==="

Next Steps


Security Audit Complete: Systematic security review for production readiness!