SSH port 22 exposed in a production container provides a persistent shell entry point for brute-force and credential-stuffing attacks — every host scanner on the public internet probes port 22 continuously (CWE-284, NIST 800-53 CM-7). A container with sshd installed adds unnecessary attack surface: the application has no need for interactive sessions, and any credential compromise or key leak provides direct OS access bypassing all application-layer controls. CIS Docker 5.6 explicitly prohibits SSH in containers. Kubernetes provides kubectl exec as the authenticated, audited alternative for debugging.
Low because SSH exposure requires a credential or key compromise to pivot to shell access, but the port being open makes brute-force and credential-stuffing attacks automatic.
Remove all SSH-related packages and EXPOSE directives from production Dockerfiles. Audit with:
grep -r 'EXPOSE 22\|openssh\|sshd\|ssh-server' Dockerfile*
For debugging and interactive access use kubectl exec with RBAC controls:
# Requires 'pods/exec' verb in RBAC — scope to specific service accounts
kubectl exec -it <pod-name> -n production -- /bin/sh
If jump-host access to nodes is required, use AWS SSM Session Manager, GCP IAP tunneling, or Azure Bastion — these route through cloud IAM and produce audit logs without opening port 22. Remove the openssh-server package from base images: RUN apt-get remove --purge openssh-server.
ID: infrastructure-hardening.monitoring-incident-response.no-ssh-rdp-exposed
Severity: low
What to look for: Enumerate all EXPOSE directives across every Dockerfile and all port definitions in Kubernetes Service manifests. For each, check whether port 22 (SSH) or port 3389 (RDP) is exposed. Also check for sshd processes configured in Dockerfile RUN commands. Count the total exposed ports and flag any that match SSH or RDP.
Pass criteria: Fewer than 1 production Dockerfile exposes port 22 or port 3389, and no Kubernetes Service forwards traffic to these ports — 0% of services expose SSH/RDP. No sshd daemon is installed or started in any Dockerfile. Pod access is controlled via kubectl exec with RBAC restrictions. Report: "X Dockerfiles and Y Services scanned, 0 SSH/RDP ports exposed."
Fail criteria: Port 22 or 3389 is exposed in any Service or Dockerfile EXPOSE directive, or an sshd daemon is installed in any production Dockerfile.
Skip (N/A) when: SSH is required for the application (e.g., git server, build machine).
Detail on fail: Quote the file and port. Example: "Dockerfile exposes port 22 (EXPOSE 22). Container installs sshd in production." or "Kubernetes Service 'app-svc' forwards port 22 to pod container port 22"
Remediation: Remove SSH from production containers. For debugging, use kubectl exec:
kubectl exec -it <pod-name> /bin/sh
Delete EXPOSE directives and SSH daemons from Dockerfile. If SSH is required, restrict access via RBAC and network policies.