Helm Chart Security Audit Fail: Fixing Missing PodSecurityContext for Compliance
Quick Fix Summary
TL;DRAdd a `securityContext` block to your Pod spec and redeploy.
Security audits and Pod Security Standards (PSS) require a `securityContext` to be defined for Pods to enforce baseline security controls like non-root users and read-only root filesystems.
Diagnosis & Causes
Recovery Steps
Step 1: Verify the Missing Context in Deployed Pods
Identify which workloads are missing the PodSecurityContext by inspecting live Pod specs.
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"/"}{.metadata.name}{": "}{.spec.securityContext}{"\n"}{end}' | grep -v -E 'fsGroup|runAsGroup|runAsNonRoot|seccompProfile'
kubectl get pod <pod-name> -n <namespace> -o yaml | grep -A 10 '^spec:' Step 2: Inspect the Helm Chart Templates
Examine the chart's deployment template to locate where the Pod spec is defined and lacks securityContext.
helm template <release-name> <chart-path> --dry-run | grep -A 20 -B 5 'kind: Deployment'
cat <chart-path>/templates/deployment.yaml Step 3: Define a Baseline PodSecurityContext in values.yaml
Add a default security context configuration in your chart's values file. This is the recommended approach for configurable charts.
# Add to your values.yaml
podSecurityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
runAsUser: 1000
fsGroup: 2000 Step 4: Modify the Deployment Template to Use the Context
Update the deployment.yaml template to inject the `podSecurityContext` from values into the Pod spec.
# In templates/deployment.yaml, within the Pod spec template
spec:
securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
... Step 5: Apply a Test Upgrade in Dry-Run Mode
Simulate the Helm upgrade to verify the changes render correctly without deploying.
helm upgrade <release-name> <chart-path> --dry-run --debug --values ./values.yaml Step 6: Perform the Helm Upgrade
Deploy the fixed chart to your cluster.
helm upgrade <release-name> <chart-path> --values ./values.yaml --namespace <namespace> Step 7: Validate the Applied Security Context
Confirm the new Pods are created with the correct securityContext.
kubectl get pod -l app.kubernetes.io/instance=<release-name> -o jsonpath='{.items[*].spec.securityContext}'
kubectl describe pod <new-pod-name> | grep -A 5 Security Architect's Pro Tip
"If `runAsNonRoot: true` causes pods to crash, check the Dockerfile. The image may be configured to run as root (USER 0) or may not have a valid non-root user defined. Use `kubectl describe pod` to see the 'container has runAsNonRoot and image will run as root' error."
Frequently Asked Questions
Can I just add `securityContext` directly to the template without using values.yaml?
Yes, but it reduces configurability and is not best practice for shareable charts. For a quick internal fix, you can hardcode it in the deployment.yaml template.
My Pod fails with "container has runAsNonRoot and image will run as root". What now?
You must either: 1) Modify the application's Dockerfile to define and use a non-root user (e.g., `USER 1000`), or 2) If the container genuinely requires root, configure your Pod Security Admission (PSA) controller with an exemption or use a less restrictive Pod Security Standard (e.g., 'privileged' baseline).