The Default Namespace Should Not Be Used
More Info:
Placing resources in the default namespace prevents proper segregation and access control. Use purpose-specific namespaces instead.
Risk Level
Low
Address
Security
Compliance Standards
- CIS Kubernetes
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
List all workloads and core resources in the
defaultnamespace- Run on: any machine with
kubectlaccess
kubectl get all,cm,secret,sa,role,rolebinding,networkpolicy -n defaultkubectl get ingress -n defaultkubectl get pvc -n defaultReview whether each object is intentionally in
defaultor just there by habit/convenience. - Run on: any machine with
-
Identify ownership and required segregation for each object
- Run on: any machine with
kubectlaccess
kubectl get deploy,sts,ds,job,cronjob -n default -o widekubectl get svc -n default -o widekubectl get sa,role,rolebinding -n default -o yamlFor each application or component, decide:
- Which team/tenant owns it.
- What security or lifecycle boundaries it needs.
- What namespace(s) should exist instead (e.g.,
team-a-prod,shared-infra,monitoring).
- Run on: any machine with
-
Create or confirm purpose-specific namespaces
- Run on: any machine with
kubectlaccess
For each logical grouping you identified:
kubectl create namespace team-a-prodkubectl create namespace shared-infra(Adjust names as decided; skip if already present:
kubectl get nsto check.)
Optionally add labels/annotations to express purpose/ownership:kubectl label namespace team-a-prod owner=team-a env=prod --overwrite - Run on: any machine with
-
Plan and migrate resources out of
defaultto their target namespaces- Run on: any machine with
kubectlaccess
For each object to move:
- Export its manifest:
kubectl get deployment my-app -n default -o yaml > my-app.yaml
- Edit the file:
- Change
metadata.namespace: defaultto the target namespace. - Update references (serviceAccountName, ConfigMap/Secret names, RoleBindings, NetworkPolicies) if they change.
- Change
- Apply to the new namespace and delete from
default:kubectl apply -f my-app.yamlkubectl delete deployment my-app -n default
Repeat this pattern for Services, ConfigMaps, Secrets, ServiceAccounts, Roles/RoleBindings, NetworkPolicies, Jobs/CronJobs, PVCs (being careful with data and StorageClass constraints).
- Run on: any machine with
-
Harden RBAC and defaults to discourage future use of
default- Run on: any machine with
kubectlaccess
Consider: - Removing broad bindings in
default:kubectl get rolebinding,clusterrolebinding -A | grep defaultkubectl delete rolebinding <name> -n default - Creating least-privilege RoleBindings only in intended namespaces and ensuring users’ kubeconfigs specify a non-default namespace:
kubectl config set-context $(kubectl config current-context) --namespace=team-a-prod
- Run on: any machine with
-
Verify that
defaultis no longer used for application resources- Run on: any machine with
kubectlaccess
kubectl get all,cm,secret,sa,role,rolebinding,networkpolicy,ingress,pvc -n defaultConfirm that:
- Only objects you explicitly want there remain (often just system bootstrap artifacts, if any).
- All application, team, or environment-specific resources have been moved to purpose-specific namespaces.
- Run on: any machine with
Using kubectl
Using kubectl
Run these commands from any machine with kubectl access.
1. List all namespaces and spot obvious mis-use of default
kubectl get ns
What to look for (potential problems):
- Only
default,kube-system, and other system namespaces exist, and no clearly purpose-specific namespaces for apps or teams. - Application names suggest they should have their own namespaces, but do not (e.g., you see
payments,frontendas Deployments indefaultlater).
2. See what is currently running in the default namespace
kubectl get all -n default
If you also use other workload types:
kubectl get deploy,sts,ds,job,cronjob,svc,ingress,cm,secret -n default
What to look for (potential problems):
- Business applications (e.g.,
orders-api,payments-db,frontend) running indefault. - Shared infrastructure components (e.g., logging, monitoring, CI/CD agents) running in
default. - Any long-lived workloads or services that clearly belong to a specific team, environment (dev/test/prod), or function, but are not in a dedicated namespace.
Using default for:
- Only temporary/manual testing objects, clearly named as such and cleaned up regularly, is usually acceptable.
- Anything production-like is a concern.
3. Check RBAC bindings that reference the default namespace
kubectl get rolebindings,roles -n default
What to look for (potential problems):
- Broad roles (e.g., with
*verbs or many resources) attached indefault, especially if:defaultcontains many or critical workloads.- ServiceAccounts in
defaultare used by multiple apps/teams.
This indicates access control is being applied to a “catch-all” namespace instead of segregated namespaces.
4. Check what is using the default ServiceAccount
kubectl get pods -n default -o custom-columns='POD:.metadata.name,SA:.spec.serviceAccountName'
What to look for (potential problems):
- Many or critical pods using the implicit
defaultServiceAccount (<none>ordefaultin the output), especially if:- Those pods belong to distinct applications that should have isolated privileges.
- There are no app-specific ServiceAccounts/roles/namespaces.
This suggests both namespace and identity segregation are not being used.
5. Review cluster-wide workloads that omit a namespace (using default implicitly)
To spot resources that may be created without specifying -n or metadata.namespace:
kubectl get deploy,sts,ds,job,cronjob,svc,ingress,cm,secret --all-namespaces | grep ' default '
What to look for (potential problems):
- Any production or shared system component appearing in
default. - Patterns showing that most application resources land in
defaultinstead of in dedicated namespaces.
Use these observations to decide:
- Which applications or components currently in
defaultshould be moved into dedicated namespaces. - What namespace structure (per app, per team, per environment) best supports your access control and segregation requirements.
Automation
#!/usr/bin/env bash
#
# Report all workload and access-control resources that are using the "default" namespace.
# Run on: any machine with kubectl access and current-context set to the target cluster.
# Requirements: kubectl, jq
set -euo pipefail
# Helper: safe kubectl get with nice headers
kget() {
local ns="$1"; shift
local kind="$1"; shift
echo
echo "=== ${kind} in namespace '${ns}' ==="
kubectl get "${kind}" -n "${ns}" -o wide --ignore-not-found
}
echo "Cluster context: $(kubectl config current-context)"
echo "Reporting use of the 'default' namespace..."
echo
# 1. Basic inventory of the 'default' namespace
echo "=== Namespaces summary (showing if 'default' exists) ==="
kubectl get ns default || true
echo
echo "=== Resource counts by namespace (workloads, services, secrets, configmaps) ==="
kubectl get deploy,ds,sts,cronjob,job,po,svc,cm,secret --all-namespaces \
-o json \
| jq -r '
.items[]
| .metadata.namespace as $ns
| $ns // "default"
' 2>/dev/null \
| sort \
| uniq -c \
| sort -nr
echo
# 2. Detailed listing of all common resource types in 'default'
kget default deploy
kget default daemonset
kget default statefulset
kget default cronjob
kget default job
kget default pod
kget default svc
kget default ingress
kget default configmap
kget default secret
kget default pvc
kget default role
kget default rolebinding
kget default serviceaccount
kget default networkpolicy
kget default hpa
kget default pdb
# 3. ClusterRoles / ClusterRoleBindings that reference the default namespace explicitly
echo
echo "=== ClusterRoleBindings referencing ServiceAccounts in 'default' namespace ==="
kubectl get clusterrolebinding -o json \
| jq -r '
.items[]
| {
name: .metadata.name,
subjects: (.subjects // [])
}
| select([.subjects[]? | select(.kind=="ServiceAccount" and .namespace=="default")] | length > 0)
| .name
' 2>/dev/null \
| sed 's/^/clusterrolebinding\//'
echo
# 4. (Optional) Detect namespaces with no resources at all (for comparison)
echo "=== Namespaces with zero Deployments, StatefulSets, DaemonSets, or Services (for context) ==="
all_ns=$(kubectl get ns -o jsonpath='{.items[*].metadata.name}')
for ns in $all_ns; do
cnt=$(kubectl get deploy,ds,sts,svc -n "$ns" --ignore-not-found -o json \
| jq '.items | length')
if [ "$cnt" -eq 0 ]; then
echo "$ns"
fi
done
echo
echo "Report complete."
cat <<'EOF'
HOW TO INTERPRET THIS OUTPUT
----------------------------
This benchmark expects the "default" namespace not to be used for application or
tenant workloads. It is typically acceptable only for:
- Minimal bootstrap/system objects (if absolutely required by your platform/tooling).
- Temporary/testing resources in non-production clusters (by explicit policy).
Indicators of a problem:
- Any application Deployments/DaemonSets/StatefulSets/Jobs/CronJobs listed under:
=== * in namespace 'default' ===
- Any user-facing Services or Ingresses in the 'default' namespace.
- ConfigMaps/Secrets in 'default' that belong to real applications (e.g. database creds).
- ServiceAccounts, Roles, or RoleBindings in 'default' that are used by production apps.
- ClusterRoleBindings that grant powerful roles to ServiceAccounts in the 'default' namespace.
Use this report to:
1. Identify which teams/owners have workloads in 'default'.
2. Decide whether each resource must be migrated into a purpose-specific namespace.
3. Define a policy (e.g., admission control) to prevent future creation of resources
in the 'default' namespace, once migration is complete.
Note: This script does NOT change the cluster; it only reports current usage so
you can make manual, policy-driven decisions consistent with the benchmark.
EOF