The Default Namespace Should Not Used
More Info:
Kubernetes provides a default namespace, where objects are placed if no namespace is specified for them. Placing objects in this namespace makes application of RBAC and other controls more difficult.
Risk Level
Low
Address
Security
Compliance Standards
- CIS Kubernetes
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
List objects currently in the
defaultnamespace- Run on: any machine with kubectl access
kubectl get all -n defaultkubectl get configmap,secret,serviceaccount,role,rolebinding,networkpolicy -n defaultReview whether any of these are application workloads or app-specific config, versus core/cluster-level components intentionally left in
default. -
Identify owners and usage of each non-system object in
default- Run on: any machine with kubectl access
kubectl get deploy,sts,ds,job,cronjob,cm,secret,svc,ingress,sa -n default -o widekubectl describe deploy -n defaultkubectl describe svc -n defaultFor each object, determine which team/application it belongs to and whether it should be isolated (e.g., by team, environment, or function).
-
Design or confirm appropriate target namespaces
- Decide, per application or team, which dedicated namespace should be used (for example:
team-a-prod,payments,monitoring). - If a needed namespace does not exist, create it:
kubectl create namespace <target-namespace>
- Ensure any required RBAC, NetworkPolicies, and quotas are or will be defined in that namespace.
- Decide, per application or team, which dedicated namespace should be used (for example:
-
Plan and execute migration of workloads from
defaultto target namespaces- Export existing manifests from
defaultand rewrite them to use the new namespace:kubectl get deploy,svc,cm,secret,ingress,sa,role,rolebinding -n default -o yaml > /tmp/default-ns-resources.yaml - Edit
/tmp/default-ns-resources.yaml:- Remove status fields and autogenerated metadata (
resourceVersion,uid,creationTimestamp, etc.). - Change
metadata.namespace: default(or addnamespace:) to the chosen<target-namespace>for each object.
- Remove status fields and autogenerated metadata (
- Apply into the new namespace:
kubectl apply -f /tmp/default-ns-resources.yaml
- After verifying the new objects run correctly, delete the originals from
default:kubectl delete -f /tmp/default-ns-resources.yaml --namespace=default --ignore-not-found
- Export existing manifests from
-
Harden processes so new resources aren’t created in
default- For cluster-wide defaults (contexts):
kubectl config view --minifykubectl config set-context --current --namespace=<preferred-namespace>
- Review CI/CD pipelines, Helm charts, and operators to ensure they explicitly set
metadata.namespaceor use a non-defaultnamespace in their configurations and release manifests.
- For cluster-wide defaults (contexts):
-
Verify that
defaultis no longer used for application resources- Run on: any machine with kubectl access
kubectl get all -n defaultkubectl get configmap,secret,serviceaccount,role,rolebinding,networkpolicy -n defaultConfirm that only intentionally-approved core objects (if any) remain in
default, and document any exceptions with justification.
Using kubectl
# 1) List all objects currently in the default namespace
# Run on: any machine with kubectl access
kubectl get all -n default
# 2) List *all* resource types that might exist in the default namespace
kubectl api-resources --verbs=list --namespaced -o name \
| xargs -n1 kubectl get -n default --ignore-not-found
# 3) Show any RoleBindings / Roles in the default namespace
kubectl get rolebindings,roles -n default -o wide
# 4) Show ServiceAccounts in the default namespace
kubectl get serviceaccounts -n default -o wide
# 5) Check which namespace is set as the default in your current kubectl context
kubectl config view --minify --output 'jsonpath={..namespace}'; echo
# 6) List all namespaces to see what alternatives exist
kubectl get namespaces
Interpretation / what indicates a problem:
-
From commands (1) and (2):
- Problematic: you see application workloads (Deployments, StatefulSets, DaemonSets, Pods, Services, Ingresses, Jobs, CronJobs, ConfigMaps, Secrets, etc.) that belong to specific apps/teams running in the
defaultnamespace. - Acceptable: only system- or bootstrap-related objects intentionally kept there (and preferably none; many orgs aim for an empty
defaultnamespace).
- Problematic: you see application workloads (Deployments, StatefulSets, DaemonSets, Pods, Services, Ingresses, Jobs, CronJobs, ConfigMaps, Secrets, etc.) that belong to specific apps/teams running in the
-
From command (3):
- Problematic: RoleBindings/Permissions clearly tied to an application or team defined in
defaultinstead of a dedicated namespace.
- Problematic: RoleBindings/Permissions clearly tied to an application or team defined in
-
From command (4):
- Problematic: application-specific ServiceAccounts (e.g.
payments-api-sa,frontend-sa) indefaultrather than in their application namespace.
- Problematic: application-specific ServiceAccounts (e.g.
-
From command (5):
- Problematic: the printed namespace is empty (meaning
default) while you normally create app resources from this context. This suggests new resources may be landing indefaultunintentionally.
- Problematic: the printed namespace is empty (meaning
-
From command (6):
- If there are no meaningful non-system namespaces for your apps (everything is effectively using
default), that indicates you have not implemented namespace-based segregation as recommended.
- If there are no meaningful non-system namespaces for your apps (everything is effectively using
Verification after you make changes (e.g., move workloads to dedicated namespaces and adjust your kubectl default namespace):
# Verify that the default namespace is no longer used for application workloads
kubectl api-resources --verbs=list --namespaced -o name \
| xargs -n1 kubectl get -n default --ignore-not-found
# Verify your current kubectl context is not defaulting to the 'default' namespace
kubectl config view --minify --output 'jsonpath={..namespace}'; echo
Automation
#!/usr/bin/env bash
#
# Report Kubernetes resources that are still using the "default" namespace.
# Run from any machine with kubectl access and current-context set.
# Requires: bash, kubectl
set -euo pipefail
echo "=== Cluster context ==="
kubectl config current-context
echo
echo "=== Namespaces in cluster (for reference) ==="
kubectl get namespaces
echo
echo "=== Workloads in the 'default' namespace ==="
echo
echo "--- Deployments ---"
kubectl get deploy -n default -o wide || echo "No deployments in default"
echo
echo "--- StatefulSets ---"
kubectl get statefulset -n default -o wide || echo "No statefulsets in default"
echo
echo "--- DaemonSets ---"
kubectl get daemonset -n default -o wide || echo "No daemonsets in default"
echo
echo "--- ReplicaSets ---"
kubectl get rs -n default -o wide || echo "No replicasets in default"
echo
echo "--- Jobs ---"
kubectl get job -n default -o wide || echo "No jobs in default"
echo
echo "--- CronJobs ---"
kubectl get cronjob -n default -o wide || echo "No cronjobs in default"
echo
echo "=== Services, Ingresses and Endpoints in 'default' ==="
echo
echo "--- Services ---"
kubectl get svc -n default -o wide || echo "No services in default"
echo
echo "--- Ingresses ---"
kubectl get ingress -n default -o wide || echo "No ingresses in default"
echo
echo "--- Endpoints ---"
kubectl get endpoints -n default -o wide || echo "No endpoints in default"
echo
echo "=== Config and Secrets in 'default' ==="
echo
echo "--- ConfigMaps ---"
kubectl get configmap -n default || echo "No configmaps in default"
echo
echo "--- Secrets ---"
kubectl get secret -n default || echo "No secrets in default"
echo
echo "=== ServiceAccounts and RBAC bindings in 'default' ==="
echo
echo "--- ServiceAccounts ---"
kubectl get sa -n default || echo "No serviceaccounts in default"
echo
echo "--- RoleBindings (namespace-scoped) ---"
kubectl get rolebinding -n default || echo "No rolebindings in default"
echo
echo "--- ClusterRoleBindings that reference 'default' namespace subjects ---"
kubectl get clusterrolebinding -o json \
| jq -r '.items[]
| select(.subjects != null)
| select([.subjects[]? | select(.namespace=="default")] | length > 0)
| .metadata.name' 2>/dev/null \
|| echo "jq not available or no clusterrolebindings referencing default namespace"
echo
echo "=== Pods in 'default' (including non-owned pods) ==="
kubectl get pods -n default -o wide || echo "No pods in default"
echo
echo "=== Summary: counts of key resources in 'default' ==="
# This section is intentionally simple; a non-zero count indicates default is in active use.
for kind in deployment statefulset daemonset job cronjob pod svc ingress configmap secret sa; do
count=$(kubectl get "$kind" -n default --no-headers 2>/dev/null | wc -l | tr -d ' ')
echo "default namespace $kind count: $count"
done
echo
echo "=== Interpretation ==="
echo "Any non-zero counts above, or non-empty tables of resources in the 'default'"
echo "namespace, indicate that the default namespace is in active use and should be"
echo "reviewed. According to the benchmark, workloads and other resources should be"
echo "moved into explicitly-created namespaces with appropriate segregation."
How to use and interpret this script
- Run on any machine with
kubectlaccess:
bash report-default-namespace-usage.sh - Problem indication:
- Any non-empty listings (Deployments, Pods, Services, ConfigMaps, Secrets, etc.) in the
defaultnamespace. - Any non-zero counts in the “Summary” section.
- Any
ClusterRoleBindingsubjects that referencenamespace: "default".
- Any non-empty listings (Deployments, Pods, Services, ConfigMaps, Secrets, etc.) in the
These outputs mean the default namespace is still being used and those resources should be reviewed and, where appropriate, migrated into purpose-built namespaces.