External security audit of KNEL-AIMiddleware before release: - FINAL-REPORT.md: Executive summary, risk assessment, remediation roadmap - 01-dockerfile-security.md: 38/40 containers run as root (HIGH) - 02-shell-script-security.md: 83 missing set -e/u directives (HIGH) - 03-docker-compose-security.md: 3 privileged services documented (MEDIUM) - 04-secrets-audit.md: PASS - no hardcoded secrets found - 05-vulnerability-scan.md: 14+ CVEs, 1 CRITICAL OpenSSL (golang:1.23-alpine) Assessment: CONDITIONAL PASS for release 💘 Generated with Crush Assisted-by: GLM-5 via Crush <crush@charm.land>
247 lines
5.8 KiB
Markdown
247 lines
5.8 KiB
Markdown
# Docker Compose Security Audit
|
|
|
|
**Date:** 2026-02-20
|
|
**Auditor:** External Security Review
|
|
**Scope:** `docker-compose.yml` and container orchestration
|
|
|
|
## Executive Summary
|
|
|
|
| Metric | Value |
|
|
|--------|-------|
|
|
| Total Services | 40+ |
|
|
| High Severity Issues | 3 |
|
|
| Medium Severity Issues | 1 |
|
|
| Low Severity Issues | 1 |
|
|
|
|
## Detailed Findings
|
|
|
|
### 1. Docker Socket Mount (HIGH)
|
|
|
|
**Severity:** HIGH
|
|
**Affected Services:** `docker-mcp`, `mcp-ansible`
|
|
**CWE:** CWE-250 (Execution with Unnecessary Privileges)
|
|
|
|
#### Description
|
|
Two services mount the Docker socket, granting full Docker daemon access:
|
|
|
|
```yaml
|
|
# docker-mcp
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
|
|
# mcp-ansible
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
```
|
|
|
|
This provides equivalent access to root on the host system.
|
|
|
|
#### Impact
|
|
- Full control over all containers on host
|
|
- Ability to mount host filesystem
|
|
- Potential for container escape
|
|
- Access to secrets in other containers
|
|
|
|
#### Risk Assessment
|
|
- **Necessary for Function:** Yes - these services manage Docker/containers
|
|
- **Mitigation Required:** Yes
|
|
|
|
#### Recommendation
|
|
1. Run these services with explicit user constraints where possible
|
|
2. Document the privilege requirement clearly
|
|
3. Consider socket proxy (docker-socket-proxy) for least privilege
|
|
4. Isolate on dedicated management nodes in production
|
|
|
|
```yaml
|
|
# Alternative with socket proxy
|
|
services:
|
|
docker-mcp:
|
|
environment:
|
|
- DOCKER_HOST=tcp://docker-proxy:2375
|
|
depends_on:
|
|
- docker-proxy
|
|
|
|
docker-proxy:
|
|
image: tecnativa/docker-socket-proxy
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
environment:
|
|
- CONTAINERS=1
|
|
- IMAGES=1
|
|
# Only allow specific operations
|
|
```
|
|
|
|
---
|
|
|
|
### 2. Kubernetes Config Mount (HIGH)
|
|
|
|
**Severity:** HIGH
|
|
**Affected Service:** `kubernetes-mcp`
|
|
**CWE:** CWE-250 (Execution with Unnecessary Privileges)
|
|
|
|
#### Description
|
|
The kubernetes-mcp service mounts kubeconfig:
|
|
|
|
```yaml
|
|
volumes:
|
|
- ~/.kube/config:/home/appuser/.kube/config:ro
|
|
```
|
|
|
|
This grants Kubernetes cluster admin access to the container.
|
|
|
|
#### Impact
|
|
- Full control over Kubernetes cluster
|
|
- Access to all secrets in cluster
|
|
- Ability to deploy privileged workloads
|
|
- Cluster admin equivalent access
|
|
|
|
#### Risk Assessment
|
|
- **Necessary for Function:** Yes - required for Kubernetes management
|
|
- **Mitigation Required:** Yes
|
|
|
|
#### Recommendation
|
|
1. Use read-only mount (`:ro` flag) - already implemented
|
|
2. Consider ServiceAccount tokens instead of kubeconfig
|
|
3. Implement RBAC with minimal required permissions
|
|
4. Document required permissions clearly
|
|
|
|
---
|
|
|
|
### 3. Privileged Access Pattern (MEDIUM)
|
|
|
|
**Severity:** MEDIUM
|
|
**Affected:** Multiple services requiring system access
|
|
**CWE:** CWE-269 (Improper Privilege Management)
|
|
|
|
#### Description
|
|
Several services require elevated privileges for their function:
|
|
|
|
| Service | Privilege Type | Justification |
|
|
|---------|---------------|---------------|
|
|
| docker-mcp | Docker socket | Container management |
|
|
| mcp-ansible | Docker socket | Container orchestration |
|
|
| kubernetes-mcp | kubeconfig | Cluster management |
|
|
| ssh-mcp | SSH keys | Remote server access |
|
|
|
|
#### Recommendation
|
|
Document each privileged service with:
|
|
- Required access level
|
|
- Business justification
|
|
- Mitigating controls
|
|
- Audit logging requirements
|
|
|
|
---
|
|
|
|
### 4. Default Credential Pattern (LOW)
|
|
|
|
**Severity:** LOW
|
|
**Affected Service:** `ghost-mcp`
|
|
**CWE:** CWE-1188 (Initialization with Hard-Coded Network Resource Configuration)
|
|
|
|
#### Description
|
|
Ghost MCP service shows a placeholder credential pattern:
|
|
|
|
```yaml
|
|
# Line 224
|
|
environment:
|
|
- GHOST_API_KEY=${GHOST_API_KEY:-your-api-key-here}
|
|
```
|
|
|
|
While this is a placeholder (not a real credential), it establishes a pattern that could lead to:
|
|
- Developers committing real credentials
|
|
- Default credentials being used in development
|
|
|
|
#### Recommendation
|
|
- Remove default values entirely
|
|
- Fail fast if required variables not set
|
|
- Use `${VAR:?VAR must be set}` pattern
|
|
|
|
```yaml
|
|
environment:
|
|
- GHOST_API_KEY=${GHOST_API_KEY:?GHOST_API_KEY must be set}
|
|
```
|
|
|
|
---
|
|
|
|
## Network Security Analysis
|
|
|
|
### Network Configuration
|
|
All services use default Docker networking (bridge). No custom networks defined.
|
|
|
|
#### Recommendations
|
|
1. Create isolated networks for service groups:
|
|
```yaml
|
|
networks:
|
|
mcp-servers:
|
|
driver: bridge
|
|
lsp-servers:
|
|
driver: bridge
|
|
```
|
|
|
|
2. Limit inter-service communication where not required
|
|
|
|
---
|
|
|
|
## Resource Limits
|
|
|
|
### Current State
|
|
No resource limits defined for any service.
|
|
|
|
#### Risk
|
|
- Resource exhaustion (memory/CPU)
|
|
- Noisy neighbor problems
|
|
- Potential denial of service
|
|
|
|
#### Recommendation
|
|
Add resource constraints:
|
|
```yaml
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: '0.5'
|
|
memory: 512M
|
|
reservations:
|
|
memory: 256M
|
|
```
|
|
|
|
---
|
|
|
|
## Health Checks
|
|
|
|
### Current State
|
|
No health checks defined.
|
|
|
|
#### Recommendation
|
|
Add health checks for monitoring:
|
|
```yaml
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 40s
|
|
```
|
|
|
|
---
|
|
|
|
## Positive Findings
|
|
|
|
1. **No host network mode** - Services use bridge networking
|
|
2. **No privileged mode** - No containers run with `privileged: true`
|
|
3. **Environment variables externalized** - Using `.env` file pattern
|
|
4. **Read-only mounts where appropriate** - kubeconfig mounted read-only
|
|
5. **Consistent container naming** - `kneldevstack-aimiddleware-` prefix
|
|
|
|
---
|
|
|
|
## Remediation Priority
|
|
|
|
| Priority | Finding | Effort | Impact |
|
|
|----------|---------|--------|--------|
|
|
| 1 | Document privileged services | Low | High |
|
|
| 2 | Add resource limits | Low | Medium |
|
|
| 3 | Implement socket proxy for Docker access | Medium | High |
|
|
| 4 | Remove default credential patterns | Low | Low |
|
|
| 5 | Add health checks | Medium | Medium |
|
|
| 6 | Create network segmentation | Medium | Medium |
|