Skip to main content

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​

Manual Steps
  1. List objects currently in the default namespace

    • Run on: any machine with kubectl access
    kubectl get all -n default
    kubectl get configmap,secret,serviceaccount,role,rolebinding,networkpolicy -n default

    Review whether any of these are application workloads or app-specific config, versus core/cluster-level components intentionally left in default.

  2. 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 wide
    kubectl describe deploy -n default
    kubectl describe svc -n default

    For each object, determine which team/application it belongs to and whether it should be isolated (e.g., by team, environment, or function).

  3. 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.
  4. Plan and execute migration of workloads from default to target namespaces

    • Export existing manifests from default and 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 add namespace:) to the chosen <target-namespace> for each object.
    • 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
  5. Harden processes so new resources aren’t created in default

    • For cluster-wide defaults (contexts):
      kubectl config view --minify
      kubectl config set-context --current --namespace=<preferred-namespace>
    • Review CI/CD pipelines, Helm charts, and operators to ensure they explicitly set metadata.namespace or use a non-default namespace in their configurations and release manifests.
  6. Verify that default is no longer used for application resources

    • Run on: any machine with kubectl access
    kubectl get all -n default
    kubectl get configmap,secret,serviceaccount,role,rolebinding,networkpolicy -n default

    Confirm 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 default namespace.
    • Acceptable: only system- or bootstrap-related objects intentionally kept there (and preferably none; many orgs aim for an empty default namespace).
  • From command (3):

    • Problematic: RoleBindings/Permissions clearly tied to an application or team defined in default instead of a dedicated namespace.
  • From command (4):

    • Problematic: application-specific ServiceAccounts (e.g. payments-api-sa, frontend-sa) in default rather than in their application namespace.
  • 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 in default unintentionally.
  • 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.

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 kubectl access:
    bash report-default-namespace-usage.sh
  • Problem indication:
    • Any non-empty listings (Deployments, Pods, Services, ConfigMaps, Secrets, etc.) in the default namespace.
    • Any non-zero counts in the “Summary” section.
    • Any ClusterRoleBinding subjects that reference namespace: "default".

These outputs mean the default namespace is still being used and those resources should be reviewed and, where appropriate, migrated into purpose-built namespaces.