The Default Namespace Should Not Be Used
More Info:
Placing resources in the default namespace makes it harder to apply access controls and segregation. Create dedicated namespaces and create all new resources within a specific namespace.
Risk Level
Low
Address
Security
Compliance Standards
- CIS OKE
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
Identify all resources currently in the
defaultnamespace- Run on: any machine with kubectl access
- Command:
kubectl api-resources --verbs=list --namespaced -o name \| xargs -n1 kubectl get -n default --ignore-not-found
- Review which workloads, services, and other objects are using
defaultand group them logically by application/team/environment.
-
Decide target namespaces and create them if needed
- For each logical group identified in step 1, decide a dedicated namespace name (e.g.
team-a-prod,payments,logging). - Create missing namespaces:
kubectl create namespace team-a-prodkubectl create namespace payments# ...repeat as required
- For each logical group identified in step 1, decide a dedicated namespace name (e.g.
-
Plan RBAC and policy for the new namespaces
- For each new namespace, define who should access it and at what level (view, edit, admin).
- Example (adjust subjects and roles before applying):
kubectl apply -f - <<'EOF'apiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata:name: team-a-adminsnamespace: team-a-prodsubjects:- kind: Groupname: team-aapiGroup: rbac.authorization.k8s.ioroleRef:kind: ClusterRolename: adminapiGroup: rbac.authorization.k8s.ioEOF
- Similarly review any NetworkPolicies, ResourceQuotas, PodSecurity policies/levels, etc., and prepare equivalents per namespace.
-
Migrate workloads and supporting resources from
defaultto the chosen namespaces- Export each object from
default, editmetadata.namespace, and re-create it in the target namespace:# Example for a single deploymentkubectl get deployment my-app -n default -o yaml > /tmp/my-app.yamlsed -i 's/namespace: default/namespace: team-a-prod/' /tmp/my-app.yaml# Remove fields not valid on createyq eval 'del(.metadata.uid, .metadata.resourceVersion, .metadata.creationTimestamp, .status)' -i /tmp/my-app.yamlkubectl delete deployment my-app -n defaultkubectl apply -f /tmp/my-app.yaml - Repeat for Services, ConfigMaps, Secrets, Jobs/CronJobs, Ingresses, etc.
- For workloads created by higher-level tools (Helm, GitOps, operators), update those tools’ configuration to deploy into the chosen namespaces instead of
default.
- Export each object from
-
Prevent new workloads from accidentally landing in
default- Update CI/CD, Helm values, Kustomize overlays, and any scripts to always set
metadata.namespaceexplicitly or use--namespacein kubectl/Helm commands. - Optionally, restrict use of
defaultvia admission controls (e.g., ValidatingAdmissionPolicy, OPA/Gatekeeper) so that new Pods/Deployments/etc. indefaultare denied unless explicitly allowed.
- Update CI/CD, Helm values, Kustomize overlays, and any scripts to always set
-
Verify that
defaultis no longer in active use for application resources- Re-run the discovery and confirm only minimal/system objects (if any) remain:
kubectl api-resources --verbs=list --namespaced -o name \| xargs -n1 kubectl get -n default --ignore-not-found
- Confirm your target namespaces now hold the expected resources:
kubectl get all -A
- Decide and document your policy on what (if anything) is allowed to remain in
defaultand monitor periodically with the same commands.
- Re-run the discovery and confirm only minimal/system objects (if any) remain:
Using kubectl
Using kubectl
Run these commands from any machine with kubectl access.
- List resources currently in the
defaultnamespace
kubectl get all -n default
Problem indication: Any non-system workloads (apps, deployments, jobs, services, etc. that are part of normal application stacks) appearing here suggest the default namespace is being used inappropriately.
- Show all resource types in the
defaultnamespace, including non-pod objects
kubectl api-resources --verbs=list --namespaced -o name \
| xargs -n 1 kubectl get -n default --ignore-not-found
Problem indication: Application-related objects (ConfigMaps, Secrets, Ingresses, RBAC bindings, etc.) in default indicate mixed or unclear segregation of resources.
- Check which contexts default to the
defaultnamespace
kubectl config get-contexts
Focus on the NAMESPACE column.
Problem indication: Contexts with an empty NAMESPACE column default to default. If these contexts are used by humans or automation (CI/CD), they likely create resources in default unless explicitly overridden.
- Inspect RBAC bindings tied to the
defaultnamespace
kubectl get rolebindings,roles -n default
kubectl get clusterrolebindings -o wide | grep '\bdefault\b' || true
Problem indication: Broad roles (e.g., edit, admin, or custom high-privilege roles) in the default namespace, or cluster role bindings referencing default service accounts, indicate that default may be carrying security-significant workloads or permissions.
- Identify service accounts actively used in the
defaultnamespace
kubectl get serviceaccounts -n default
kubectl get pods -n default -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.serviceAccountName}{"\n"}{end}'
Problem indication: Multiple custom service accounts or pods using them in default often mean real applications are deployed there instead of in dedicated namespaces.
- Verify whether key applications are running in non-default namespaces
If you know app labels (example: app=frontend), check where they run:
kubectl get pods --all-namespaces -l app=frontend -o wide
Problem indication: If important applications only appear in the default namespace, that application team has not been segregated into a dedicated namespace.
These commands only surface the current state. Deciding which resources should move to dedicated namespaces and how to redesign access controls requires human review of:
- Which objects are system/cluster-critical vs. app workloads.
- Which teams/owners should have separate namespaces.
- How RBAC and network policies will map to the new namespace structure.
Automation
#!/usr/bin/env bash
# Report resources still using the "default" namespace
# Run on: any machine with kubectl access and appropriate RBAC
set -euo pipefail
echo "=== Context ==="
kubectl config current-context || true
echo
echo "=== Workloads in the 'default' namespace ==="
echo
echo "-- Pods (non-daemon, non-static) --"
kubectl get pods -n default -o wide || true
echo
echo "-- Deployments --"
kubectl get deploy -n default -o wide || true
echo
echo "-- StatefulSets --"
kubectl get statefulset -n default -o wide || true
echo
echo "-- DaemonSets --"
kubectl get daemonset -n default -o wide || true
echo
echo "-- Jobs --"
kubectl get jobs -n default -o wide || true
echo
echo "-- CronJobs --"
kubectl get cronjobs -n default -o wide || true
echo
echo "=== Services, Ingresses, and Endpoints in 'default' ==="
echo
echo "-- Services --"
kubectl get svc -n default -o wide || true
echo
echo "-- Ingresses --"
kubectl get ingress -n default -o wide || true
echo
echo "-- Endpoints --"
kubectl get endpoints -n default -o wide || true
echo
echo "=== RBAC references to the 'default' namespace ==="
echo
echo "-- RoleBindings in 'default' --"
kubectl get rolebinding -n default -o wide || true
echo
echo "-- ClusterRoles/ClusterRoleBindings mentioning 'default' in subjects --"
kubectl get clusterrolebinding -o json \
| jq -r '.items[]
| select(.subjects != null)
| select([.subjects[]?.namespace] | any(. == "default"))
| .metadata.name' 2>/dev/null || true
echo
echo "=== Config and policy resources in 'default' ==="
echo
echo "-- ConfigMaps --"
kubectl get configmap -n default -o wide || true
echo
echo "-- Secrets --"
kubectl get secret -n default -o wide || true
echo
echo "-- NetworkPolicies --"
kubectl get networkpolicy -n default -o wide || true
echo
echo "-- PodSecurityPolicies referencing 'default' (if PSP is enabled) --"
kubectl get psp -o yaml 2>/dev/null \
| grep -n "namespace: default" || true
echo
echo "=== Admission / Policy configurations that may treat 'default' specially ==="
echo
echo "-- ValidatingWebhookConfiguration mentioning 'default' --"
kubectl get validatingwebhookconfiguration -o yaml 2>/dev/null \
| grep -n "namespace: default" || true
echo
echo "-- MutatingWebhookConfiguration mentioning 'default' --"
kubectl get mutatingwebhookconfiguration -o yaml 2>/dev/null \
| grep -n "namespace: default" || true
echo
echo "=== Summary hint ==="
echo "Any non-system workload, service, config, or RBAC object listed above in the 'default'"
echo "namespace should be reviewed. In general, only temporary test resources or carefully"
echo "justified exceptions should appear in 'default'."
Explanation of problematic output:
- Any long-lived or production workload (Deployments, StatefulSets, DaemonSets, Jobs/CronJobs) listed under
defaultindicates a problem; these should be moved to dedicated namespaces. - Services, Ingresses, ConfigMaps, Secrets, and NetworkPolicies in
defaulttied to those workloads are also problematic and should be migrated with the workloads. - RoleBindings in
defaultand ClusterRoleBindings whosesubjectsreferencenamespace: defaultmay be overly broad; review whether access should instead be scoped to specific application namespaces. - Webhook, PSP, or other policy configurations that special-case
namespace: defaultshould be reviewed to ensure they are not encouraging or relying on use of the default namespace.