Skip to content

Instantly share code, notes, and snippets.

@Antonlovesdnb
Created March 28, 2026 17:16
Show Gist options
  • Select an option

  • Save Antonlovesdnb/e50dd046b221027f11c4973764d71047 to your computer and use it in GitHub Desktop.

Select an option

Save Antonlovesdnb/e50dd046b221027f11c4973764d71047 to your computer and use it in GitHub Desktop.
K8s RBAC Audit
argument-hint [context=<kubeconfig-context>] [namespace=all]
allowed-tools
Bash
Read
Write

K8s RBAC Audit — Find Overpermissioned Service Accounts

Audit a Kubernetes cluster's RBAC configuration to find overpermissioned service accounts, dangerous bindings, wildcard roles, and pre-staged escalation paths. Produces a visual Obsidian note with TUI flow diagrams and blast radius charts.

Input

$ARGUMENTS optionally contains:

  • context=<name> to specify a kubeconfig context (default: current context)
  • namespace=<name> to scope to a specific namespace (default: all — audit cluster-wide)

Configuration

CONTEXT -- from args, or current kubectl context
NAMESPACE -- from args, or "all"
VAULT=Obsidian Vault

Verify kubectl is available and can reach the cluster before proceeding. If a context is specified, use --context=<CONTEXT> on all kubectl commands.

Workflow

Step 1 — Collect RBAC objects (run all in parallel)

1a. ClusterRoleBindings

kubectl get clusterrolebindings -o json > /tmp/rbac_crbs.json

1b. RoleBindings (all namespaces)

kubectl get rolebindings --all-namespaces -o json > /tmp/rbac_rbs.json

1c. ClusterRoles

kubectl get clusterroles -o json > /tmp/rbac_clusterroles.json

1d. Roles (all namespaces)

kubectl get roles --all-namespaces -o json > /tmp/rbac_roles.json

1e. ServiceAccounts (all namespaces)

kubectl get serviceaccounts --all-namespaces -o json > /tmp/rbac_sas.json

1f. Pods (all namespaces) — to map SAs to running workloads

kubectl get pods --all-namespaces -o json > /tmp/rbac_pods.json

Step 2 — Parse and build the RBAC graph

Read all 6 JSON files. Build a mental model of:

Binding → Role → Rules resolution: For each ClusterRoleBinding and RoleBinding:

  1. Identify the subjects (ServiceAccounts, Users, Groups)
  2. Resolve the roleRef to the actual ClusterRole or Role
  3. Extract the rules (apiGroups, resources, verbs) from that role
  4. Determine the scope (cluster-wide for ClusterRoleBindings, namespace-scoped for RoleBindings)

ServiceAccount → Pod mapping: For each pod, record which ServiceAccount it uses and whether automountServiceAccountToken is true/false/unset (unset = true by default).

Step 3 — Flag findings

Analyze every binding+role combination. Flag these patterns:

CRITICAL findings:

  • Any non-system ServiceAccount bound to cluster-admin
  • Any role with verbs: ["*"] AND resources: ["*"] (cluster-admin equivalent)
  • The default ServiceAccount in any namespace bound to a privileged role (pods inherit this automatically)
  • ServiceAccounts with escalate, bind, or impersonate verbs (RBAC escalation primitives)

HIGH findings:

  • Roles with verbs: ["*"] on specific resources (full control over a resource type)
  • Roles with resources: ["secrets"] and verbs including get or list (secret exfiltration)
  • Roles with resources: ["pods/exec"] (remote code execution into pods)
  • automountServiceAccountToken: true on pods that don't need API access
  • ServiceAccounts that exist but are not used by any pod (pre-staged escalation paths)
  • Misnamed roles (name suggests limited scope but rules grant broader access)

MEDIUM findings:

  • Roles with wildcard apiGroups ("*") but scoped resources
  • Bindings to system: groups beyond the expected Kubernetes defaults
  • RoleBindings that grant cross-namespace access via ClusterRoles

For each finding, record:

  • The binding name and namespace
  • The subject (SA/User/Group)
  • The resolved role and its effective permissions
  • Which pods (if any) inherit this access
  • Whether tokens are auto-mounted
  • A specific remediation command

Step 4 — Identify attack paths

Trace exploitable chains:

  1. Pod → SA → Role → what can it do? For each running pod, trace what API access its SA token grants. Flag pods where compromising the container = gaining significant cluster access.

  2. Dormant escalation paths: SAs with powerful roles but no running pods — an attacker who can create a pod spec referencing this SA gets instant privilege escalation.

  3. Default SA abuse: Any namespace where the default SA has non-trivial permissions — every pod without an explicit SA inherits this.

  4. Lateral movement: SAs that can read secrets, exec into pods, or create pods in other namespaces.

Step 5 — Write Obsidian note

Note name: K8s RBAC Audit — <YYYY-MM-DD>

obsidian create vault="{VAULT}" name="K8s RBAC Audit — $(date +%Y-%m-%d)" overwrite content="..."

Note structure:

---
scan_date: <YYYY-MM-DD>
cluster: <context-name>
total_clusterrolebindings: <N>
total_rolebindings: <N>
total_serviceaccounts: <N>
critical_findings: <N>
high_findings: <N>
---

# K8s RBAC Audit — <YYYY-MM-DD>

> [!failure] Audit Summary
> **Cluster:** <name>  |  **ClusterRoleBindings:** <N>  |  **ServiceAccounts:** <N>
> **Critical findings:** <N>  |  **High findings:** <N>
> **<N> service accounts have cluster-admin or equivalent access**

## RBAC Attack Surface

(TUI Permission Flow diagram — see format below)

## Permission Blast Radius

(TUI bar chart — see format below)

## Findings

### CRITICAL

> [!failure] <Finding title>
> **Binding:** `<binding-name>`
> **Subject:** `<ServiceAccount:namespace/name>`
> **Role:** `<role-name>` (summary of effective permissions)
> **Impact:** <what an attacker gains, which pods inherit this>
> **Fix:**
> ```bash
> kubectl delete clusterrolebinding <name>
> ```

### HIGH

> [!warning] <Finding title>
> ...

## RBAC Overview

(Table of non-system ClusterRoleBindings — binding, role, subject, status)

## ServiceAccount Distribution

(Table by namespace — SA count, notes)

## Recommendations

1. **[CRITICAL]** <action> — <reason>
2. **[HIGH]** <action> — <reason>
...

TUI Permission Flow Diagram Format

Generate a Unicode box-drawing flow diagram showing overpermissioned RBAC paths. Use Python to guarantee alignment (all lines must be exactly the same character count):

╔════════════════════════════════════════════════════════════════════════════════════════╗
║                       RBAC PERMISSION FLOW — OVERPRIVILEGED PATHS                      ║
╠════════════════════════════════════════════════════════════════════════════════════════╣
║                                                                                        ║
║  SERVICE ACCOUNT          BINDING                  ROLE            EFFECTIVE ACCESS     ║
║                                                                                        ║
║  ┌──────────────────┐   ┌──────────────────────┐   ┌──────────────┐                    ║
║  │ <ns>/<sa-name>   │━━━│ <binding-name>       │━━━│ <role-name>  │━━▶ ████████ ALL    ║
║  │  └ <pod-name>    │   │                      │   │ <perms>      │    <scope>         ║
║  └──────────────────┘   └──────────────────────┘   └──────────────┘                    ║
║                                                                                        ║
║  ━━━ CRITICAL (cluster-admin equiv.)  ─── HIGH (overly broad)  ░░░ gap vs scope        ║
╚════════════════════════════════════════════════════════════════════════════════════════╝

Rules:

  • Use ━━━ (heavy lines) for CRITICAL paths, ─── (light lines) for HIGH
  • Use ┃ between CRITICAL blocks, ╏ before transitioning to HIGH blocks
  • Show pods that inherit each SA inside the SA box
  • The blast column uses █ for granted scope and ░ for expected scope
  • Generate with a Python script that pads all lines to the same width to guarantee ║ alignment

TUI Blast Radius Chart Format

  SERVICE ACCOUNT           ACTUAL SCOPE vs NEEDED SCOPE
  ────────────────────────────────────────────────────────────
  <ns>/<sa-name>          ████████████████████████████████████████  100%
                          ╰─ <role-name>    ╰─ <pod info>

Use 40-char bars: █ count = percentage of max possible permissions. Fill remainder with ░.

Step 6 — Summary

Report to the user:

  • Cluster name and total RBAC object counts
  • Finding counts by severity
  • Top findings with one-line descriptions
  • Most dangerous attack paths discovered
  • Confirm note written to Obsidian
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment