Skip to main content

The Default Namespace Should Not Be 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

  • APRA CPS 234 (Australia)
  • BSI C5 (Germany)
  • Brazil LGPD
  • CCPA / CPRA (California)
  • CIS Critical Security Controls v8
  • CIS OKE
  • CMMC 2.0
  • CSA Cloud Controls Matrix v4
  • DPDPA
  • Digital Operational Resilience Act (EU)
  • Essential 8
  • ISO/IEC 27017
  • ISO/IEC 27018
  • ISO/IEC 27701
  • KSA PDPL
  • MAS Technology Risk Management (Singapore)
  • MITRE ATT&CK (Cloud)
  • NIS2 Directive
  • NIST SP 800-171
  • NYDFS 23 NYCRR 500
  • SWIFT Customer Security Controls Framework
  • Sarbanes-Oxley IT General Controls
  • UK NCSC Cyber Assessment Framework

Triage and Remediation

Remediation

Manual Steps
  1. List all objects currently in the default namespace

    • Run on: any machine with kubectl access
    • Command:
      kubectl api-resources --verbs=list --namespaced -o name \
      | xargs -n 1 kubectl get -n default --ignore-not-found
    • Review which workloads, services, config, and secrets are currently living in default.
  2. Identify which default-namespace objects are non-system and should be moved

    • Run on: any machine with kubectl access
    • Commands (examples for common types):
      kubectl get deploy,sts,ds,job,cronjob -n default -o wide
      kubectl get svc,ingress -n default -o wide
      kubectl get configmap,secret -n default
    • Decide, in coordination with application owners, which of these are user/application workloads (not temporary tests or intentionally shared infra) and should be isolated into their own namespace(s).
  3. Create or confirm appropriate target namespaces for each application or team

    • Run on: any machine with kubectl access
    • For each logical application/team you identified:
      kubectl create namespace <app-or-team-namespace-name>
    • If a namespace already exists for that application/team, skip creation and just record it as the target.
  4. Plan and apply namespace-specific RBAC and policies before moving workloads

    • Run on: any machine with kubectl access
    • Gather current RBAC and policy references that may rely on default:
      kubectl get role,rolebinding -A
      kubectl get clusterrole,clusterrolebinding
      kubectl get networkpolicy -A
      kubectl get resourcequota,limitrange -A
    • For each target namespace, define or update:
      • Role/RoleBinding (or ClusterRoleBinding subjects) for the right users/service accounts
      • ResourceQuota/LimitRange as needed
      • NetworkPolicy to enforce appropriate isolation
    • Apply these manifests to the target namespaces before moving the workloads.
  5. Migrate objects from default into their target namespaces

    • Run on: any machine with kubectl access
    • For each object selected for migration:
      1. Export manifest from default:
        kubectl get <kind> <name> -n default -o yaml > /tmp/<name>.yaml
      2. Edit /tmp/<name>.yaml:
        • Remove metadata.resourceVersion, metadata.uid, metadata.creationTimestamp, status, and any ownerReferences that would block recreation.
        • Change metadata.namespace: default to metadata.namespace: <target-namespace>.
      3. Apply to the target namespace:
        kubectl apply -f /tmp/<name>.yaml
      4. After confirming the new object is running and healthy, delete the old one from default:
        kubectl delete <kind> <name> -n default
    • For services and ingresses, coordinate any DNS or client impact and validate traffic after migration.
  6. Verify that default is no longer used for application resources

    • Run on: any machine with kubectl access
    • Re-run a comprehensive check:
      kubectl api-resources --verbs=list --namespaced -o name \
      | xargs -n 1 kubectl get -n default --ignore-not-found
    • Confirm that only objects you explicitly accept in default (if any) remain, and that new deployment processes specify non-default namespaces (e.g., by checking CI/CD manifests and Helm values).
Using kubectl

Using kubectl

Run these commands from any machine with kubectl access.

  1. List all objects in the default namespace

    kubectl get all -n default

    Problem indication: Any non‑system workloads (your applications, databases, jobs, etc.) appearing here suggest the default namespace is being used inappropriately.

  2. Enumerate all resource types in the default namespace

    # Workloads and services
    kubectl get deploy,sts,ds,po,svc,ing,job,cronjob -n default

    # Config and access-related objects
    kubectl get cm,secret,sa,role,rolebinding,pdb,hpa -n default

    Problem indication: Application deployments, services, ingresses, configmaps, secrets, roles/rolebindings, etc. in default (other than intentional exceptions you explicitly accept) indicate a policy issue.

  3. Identify which users/teams are using default

    kubectl get deploy -n default -o wide
    kubectl get po -n default -o yaml | grep -E 'ownerReferences:|name:|kind:' -n

    Problem indication: Objects clearly associated with specific applications or teams (by name or labels/annotations) show that these workloads should likely be moved into dedicated namespaces.

  4. Check for RBAC targeting the default namespace

    kubectl get role,rolebinding -n default -o wide

    Problem indication: Custom Role/RoleBinding objects in default (especially granting broad access) indicate that security controls are being applied directly to default instead of to dedicated namespaces.

  5. Confirm whether default is referenced in manifests (optional, if you have them locally)
    From your manifest repository or local directory:

    grep -Rni --include='*.yml' --include='*.yaml' 'namespace:\s*default' .

    Problem indication: Manifests explicitly setting namespace: default suggest an ongoing practice of deploying into the default namespace.

These commands only surface current usage. A human must decide which objects (if any) are acceptable in default and plan migration of others into purpose‑specific namespaces.

Automation
#!/usr/bin/env bash
#
# Report all resources currently using the "default" namespace
# Requires: kubectl, access to all relevant API groups

set -euo pipefail

# 1) Basic sanity check
kubectl get ns default >/dev/null 2>&1 || {
echo "default namespace not found; nothing to report."
exit 0
}

echo "=== Resources in the 'default' namespace (names only) ==="
kubectl get all -n default

echo
echo "=== ClusterRoles / Roles / RoleBindings / ClusterRoleBindings referencing 'default' ==="
echo "# Roles/RoleBindings scoped to the default namespace:"
kubectl get role,rolebinding -n default -o wide || true

echo
echo "# ClusterRoleBindings that reference ServiceAccounts in the default namespace:"
kubectl get clusterrolebinding -o json \
| jq -r '
.items[]
| select(.subjects != null)
| select(
any(.subjects[]?; .kind=="ServiceAccount" and .namespace=="default")
)
| [.metadata.name,
([.subjects[]? | select(.kind=="ServiceAccount" and .namespace=="default") | .name] | join(","))]
| @tsv
' 2>/dev/null \
| awk 'BEGIN{print "CLUSTERROLEBINDING\tSERVICEACCOUNTS_IN_DEFAULT_NS"}
{print}' || echo "jq not available or no matches."

echo
echo "=== NetworkPolicies in the 'default' namespace ==="
kubectl get networkpolicy -n default || true

echo
echo "=== Ingresses in the 'default' namespace ==="
kubectl get ingress -n default || true

echo
echo "=== ConfigMaps and Secrets in the 'default' namespace ==="
kubectl get configmap,secret -n default || true

echo
echo "=== Events in the 'default' namespace (for recent activity context) ==="
kubectl get events -n default --sort-by=.lastTimestamp | tail -n 50 || true

echo
echo "=== Summary: count of objects by kind in the 'default' namespace ==="
kubectl api-resources --namespaced=true --verbs=list -o name \
| while read -r r; do
count=$(kubectl get "$r" -n default --no-headers 2>/dev/null | wc -l | tr -d ' ')
if [ "$count" -gt 0 ]; then
printf "%-40s %s\n" "$r" "$count"
fi
done

echo
echo "=== Guidance: How to interpret this output ==="
cat <<'EOF'
Any non-system workload or configuration appearing above in the "default" namespace
should be reviewed. In particular, these indicate a problem with this control:

- Pods, Deployments, StatefulSets, DaemonSets, Jobs, CronJobs, or Services in the
default namespace that belong to application teams.
- ServiceAccounts in the default namespace that are bound via (Cluster)RoleBindings
and used by applications.
- ConfigMaps, Secrets, Ingresses, NetworkPolicies in the default namespace that
are part of application deployments.

Desired state: only temporary/test items (if allowed by policy) or explicitly
approved workloads should exist in the default namespace; all regular workloads
should be moved to dedicated, named namespaces.
EOF