Skip to main content

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

Manual Steps
  1. Identify all resources currently in the default namespace

    • 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 default and group them logically by application/team/environment.
  2. 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-prod
      kubectl create namespace payments
      # ...repeat as required
  3. 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/v1
      kind: RoleBinding
      metadata:
      name: team-a-admins
      namespace: team-a-prod
      subjects:
      - kind: Group
      name: team-a
      apiGroup: rbac.authorization.k8s.io
      roleRef:
      kind: ClusterRole
      name: admin
      apiGroup: rbac.authorization.k8s.io
      EOF
    • Similarly review any NetworkPolicies, ResourceQuotas, PodSecurity policies/levels, etc., and prepare equivalents per namespace.
  4. Migrate workloads and supporting resources from default to the chosen namespaces

    • Export each object from default, edit metadata.namespace, and re-create it in the target namespace:
      # Example for a single deployment
      kubectl get deployment my-app -n default -o yaml > /tmp/my-app.yaml
      sed -i 's/namespace: default/namespace: team-a-prod/' /tmp/my-app.yaml
      # Remove fields not valid on create
      yq eval 'del(.metadata.uid, .metadata.resourceVersion, .metadata.creationTimestamp, .status)' -i /tmp/my-app.yaml
      kubectl delete deployment my-app -n default
      kubectl 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.
  5. Prevent new workloads from accidentally landing in default

    • Update CI/CD, Helm values, Kustomize overlays, and any scripts to always set metadata.namespace explicitly or use --namespace in kubectl/Helm commands.
    • Optionally, restrict use of default via admission controls (e.g., ValidatingAdmissionPolicy, OPA/Gatekeeper) so that new Pods/Deployments/etc. in default are denied unless explicitly allowed.
  6. Verify that default is 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 default and monitor periodically with the same commands.
Using kubectl

Using kubectl

Run these commands from any machine with kubectl access.

  1. List resources currently in the default namespace
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.

  1. Show all resource types in the default namespace, 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.

  1. Check which contexts default to the default namespace
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.

  1. Inspect RBAC bindings tied to the default namespace
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.

  1. Identify service accounts actively used in the default namespace
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.

  1. 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 default indicates a problem; these should be moved to dedicated namespaces.
  • Services, Ingresses, ConfigMaps, Secrets, and NetworkPolicies in default tied to those workloads are also problematic and should be migrated with the workloads.
  • RoleBindings in default and ClusterRoleBindings whose subjects reference namespace: default may be overly broad; review whether access should instead be scoped to specific application namespaces.
  • Webhook, PSP, or other policy configurations that special-case namespace: default should be reviewed to ensure they are not encouraging or relying on use of the default namespace.