Skip to content

Instantly share code, notes, and snippets.

@dims
Last active July 20, 2026 13:23
Show Gist options
  • Select an option

  • Save dims/e7e55d375149d0c3b4d38f85c8cea172 to your computer and use it in GitHub Desktop.

Select an option

Save dims/e7e55d375149d0c3b4d38f85c8cea172 to your computer and use it in GitHub Desktop.
Kubernetes dependency security analysis (latest: 2026-07-20) + regeneration prompt

Prompt: Kubernetes Dependency Security Analysis

Use this prompt verbatim to generate a security analysis of the current Kubernetes dependency version gaps. Feed it to a capable model (Claude Opus or equivalent) with web access and filesystem access to the kubernetes/kubernetes source tree.

Last updated 2026-07-20: added malformed-compare-URL corrections (grpc→wrong repo, /vN and submodule-path bugs), repo-level security-advisory check (new GHSAs lag OSV/global index), refreshed reference outputs.


Prompt

You are a Kubernetes security engineer. Your task is to produce a deep, prioritized security analysis of Kubernetes dependency version gaps. Start by fetching the live package list from the Prow CI job, then analyze each package.


Step 0 — Fetch the current package list

  1. Fetch the job history page to find the most recent successful run:

    https://prow.k8s.io/job-history/gs/kubernetes-ci-logs/logs/ci-kubernetes-e2e-kind-dependencies
    

    Find the first entry with status SUCCESS and extract its job ID from the URL (a large integer, e.g. 2047409810214752256).

  2. Fetch the differences file directly:

    https://storage.googleapis.com/kubernetes-ci-logs/logs/ci-kubernetes-e2e-kind-dependencies/{JOB_ID}/artifacts/differences.md
    
  3. Parse the table in that file:

    • Skip any row where the first non-whitespace character is ~ — those packages are already at latest and need no analysis.
    • The remaining rows are the packages with version gaps. Each row has: Package | Current | Latest | URL
    • The URL column already contains the GitHub compare URL for each package. Use those directly.
  4. That parsed list is your complete package table. Count the packages and proceed.


Step 1 — Analyze each package

For every package in the list:

  1. Fetch the compare URL from the table. Read the full commit list and changed files. Look specifically for:

    • Commit messages mentioning CVE, security, panic, overflow, DoS, bypass, injection, race, crash, nil deref, OOB, escape, or auth
    • Changes to parsing, serialization, cryptographic, authentication, or network code
    • Changes to error-handling paths that previously panicked
    • Dependency bumps inside the package's own go.mod (transitive CVE fixes)
  2. Check the Go Vulnerability Database at https://pkg.go.dev/vuln/list and https://osv.dev for advisories covering the package in the version range. Also search https://github.com/advisories?query= for GHSA entries. Additionally check repo-level advisories (gh api repos/<owner>/<repo>/security-advisories) — freshly published GHSAs can take days to propagate to OSV and the global GitHub advisory index, so an OSV-empty result is not proof of a clean range (the 2026-07-20 run found two swag GHSAs published the day before that were repo-level only).

  3. Check NVD at https://nvd.nist.gov/vuln/search for CVEs mentioning the package.

  4. Determine Kubernetes-specific reachability. For each security-relevant change, answer:

    • Is this package a direct or indirect dep in the k8s go.mod?
    • Which k8s binary uses it: kube-apiserver, kubelet, kube-controller-manager, kube-proxy, kubectl, kubeadm, or only test code?
    • Is the vulnerable/fixed code path reachable from untrusted external input (unauthenticated network, authenticated API request body, pod stdout, etc.) or only from trusted/privileged input?
    • What is the blast radius if exploited?

    Key k8s source locations to grep for reachability:

    • staging/src/k8s.io/apimachinery/ — core API types and serialization
    • staging/src/k8s.io/apiserver/ — kube-apiserver logic
    • staging/src/k8s.io/client-go/ — client library
    • pkg/ — kubelet, controllers, scheduler
    • cmd/ — binary entrypoints
    • test/ — test-only code (not shipped in production binaries)
    • vendor/ — check vendor/modules.txt for direct vs indirect
  5. Assign a priority:

    • CRITICAL — actively exploited or trivially exploitable without authentication, high impact (RCE, auth bypass, data exfiltration)
    • HIGH — remotely exploitable by an authenticated user OR exploitable by a lower-privilege actor; significant impact (DoS of core component, data integrity compromise)
    • MEDIUM — security-relevant fix but not directly exploitable in standard k8s deployments (e.g., not exploitable because k8s does not use etcd's built-in auth, or fix is in transitive dep k8s already pins), OR correctness fix that affects data integrity on the kube-apiserver storage path
    • LOW — defense-in-depth hardening, fix is in test-only code path, or Windows-only, or indirect dep where the attack surface is privileged
    • NONE — zero security content; only CI, docs, go directive bumps, or dev tooling changes

Step 2 — Parallelize by risk tier

Group the packages from your fetched list into tiers and analyze them concurrently with parallel agents:

  • Tier 1 (crypto/auth/networking): packages matching x/crypto, x/net, golang-jwt, go-pathrs, cachecontrol, oauth2
  • Tier 2 (storage/infrastructure): packages matching etcd (all modules together), container-storage-interface, ttrpc, sctp
  • Tier 3 (serialization/parsing): packages matching cbor, easyjson, go-openapi, yaml, go-errors
  • Tier 4 (infra/golang stdlib): packages matching grpc-gateway, caddy, genproto, x/sys, x/text, x/tools, x/mod, x/time, x/term, x/exp
  • Tier 5 (lower-risk mixed): everything else

Merge the tier results before writing output.


Step 3 — Produce the output markdown

Produce a single markdown file with this exact structure:

# Kubernetes Dependency Security Analysis
**Date:** <today>
**Prow job:** <job URL used>
**Packages analyzed:** <count of non-~ rows>
**Method:** GitHub diff inspection, [Go Vulnerability Database](https://pkg.go.dev/vuln/list), CVE/GHSA search, K8s source grep for reachability

---

## Executive Summary

<2-3 sentence summary: how many packages need action, how many have no delta, any already-patched CVEs to call out>

---

## Priority 1 — UPGRADE PROMPTLY
<All HIGH/CRITICAL packages, one subsection each>

### [`package/name`](compare-url) vX.Y.Z → vA.B.C
**CVE:** [CVE-XXXX-XXXXX](nvd link) [or "None filed"]
**Type:** <short description>
**Fix commit/PR:** [`shortsha`](full commit url) — "commit message"

**What it does:** <1-2 sentences on the vulnerability>

**K8s reachability (<LOW/MEDIUM/HIGH/VERY HIGH>):**
- <bullet per binary or code path that is affected>

**Attack scenario:** <concrete description of how an attacker would trigger this in a k8s cluster>

**Action:** `./hack/pin-dependency.sh <module> <version>` then `./hack/update-vendor.sh`

---

## Priority 2 — MEDIUM (upgrade in next dep sweep)
<All MEDIUM packages, one subsection each>

## Priority 3 — LOW (batch in next routine dep PR)
<All LOW packages, shorter entries>

## Priority 4 — NONE (no action needed)
<Table of all NONE packages with one-line reason>

| Package | Diff | Reason no action needed |
|---|---|---|
| [`pkg`](compare-url) | vX → vY | <one line> |

---

## Action Plan (ordered)
<Shell commands in priority order using hack/pin-dependency.sh>

---

## CVEs Already Patched (verify current vendor is sufficient)
<Table of CVEs that were already fixed before the current vendor pin>

| CVE | GHSA | Package | Fixed in | Current k8s pin | Status |
|---|---|---|---|---|---|

Rules — links

  • Every package name in headers must be a hyperlink to the compare URL from the differences.md table.
  • CVE IDs: Link to https://nvd.nist.gov/vuln/detail/CVE-XXXX-XXXXX only after fetching the page to confirm it exists — very new CVEs may be RESERVED and the NVD page will say "CVE ID Not Found." For RESERVED CVEs, link to the upstream issue tracker (e.g., https://github.com/golang/go/issues/XXXXX) or the GHSA instead.
  • GHSA IDs: Link to https://github.com/advisories/GHSA-XXXX-XXXX-XXXX — fetch to verify before linking.
  • Go vuln IDs (GO-XXXX-XXXX): Link to https://pkg.go.dev/vuln/GO-XXXX-XXXX — fetch to verify.
  • PR links: Link to the full GitHub PR URL. Verify the PR number before linking — do not guess.
  • Commit SHAs: ALWAYS use the full 40-character SHA, not an abbreviation. Fetch the commit URL to verify it exists before including it. Abbreviated or guessed SHAs are wrong more often than not.
  • Vanity compare URLs in the differences.md (e.g., https://cyphar.com/go-pathrs/compare/..., https://go.etcd.io/etcd/.../compare/...) redirect to pkg.go.dev, not GitHub diffs. For these, find the real GitHub repo:
    • cyphar.com/go-pathrshttps://github.com/cyphar/libpathrs/compare/go-pathrs%2Fv<OLD>...go-pathrs%2Fv<NEW>
    • go.etcd.io/etcd/*https://github.com/etcd-io/etcd/compare/<OLD>...<NEW> (one compare covers all etcd sub-modules)
    • For any other vanity domain, do go get -v <module> or check the go-import meta tag to find the canonical GitHub repo.
  • Malformed GitHub compare URLs in the differences.md — the generator naively appends the Go module path to github.com/, which breaks whenever module path ≠ repo path. Correct these before fetching (all seen in the 2026-07-20 run):
    • Wrong repo entirely: the google.golang.org/grpc row points at protocolbuffers/protobuf-go — use https://github.com/grpc/grpc-go/compare/v<OLD>...v<NEW>.
    • /vN major-version suffix is not a repo path: Masterminds/semver/v3, cpuguy83/go-md2man/v2, fxamacker/cbor/v2 → drop the /vN (e.g. https://github.com/Masterminds/semver/compare/v3.4.0...v3.5.0).
    • Submodules tag with a path prefix: containerd/containerd/apihttps://github.com/containerd/containerd/compare/api%2Fv<OLD>...api%2Fv<NEW>; google/cadvisor/libhttps://github.com/google/cadvisor/compare/lib%2Fv<OLD>...lib%2Fv<NEW> (if the lib/* tag is missing upstream, fall back to the release tags v<OLD>...v<NEW> and note it); go-openapi/swag/<sub> submodules are covered by the root go-openapi/swag compare.
    • google.golang.org/genproto/googleapis/{api,rpc} → both map to one repo: https://github.com/googleapis/go-genproto/compare/<OLD>...<NEW>.
  • go.yaml.in/yaml/v2: The github.com/go-yaml/yaml repo may not have newer v2.4.x tags; if the compare 404s, link to https://pkg.go.dev/go.yaml.in/yaml/v2?tab=versions instead.
  • OSS-Fuzz URLs (https://issues.oss-fuzz.com/issues/XXXXXX) are login-gated. Include when you have the real ID; note they require Google login.
  • Packages with no security content (CI only, go directive bumps, doc fixes) go in the Priority 4 table — do not give them a full subsection.
  • Verify k8s reachability by grepping — do not assume a package is used in production just because it appears in go.mod. Check vendor/modules.txt for direct vs indirect. Check whether imports are in test/ vs pkg//cmd//staging/.
  • When a CVE is already fixed in the current k8s vendor pin, call it out in "CVEs Already Patched" — do not list it as something that needs upgrading.
  • For etcd CVEs: check whether the upstream advisory says "Kubernetes not affected" (etcd maintainers do this when the CVE requires etcd's built-in RBAC/auth, which k8s bypasses). If so, note it but still recommend upgrading for any data-correctness or linearizability fixes in the same release.

Reference: Sample output

The latest reference output lives in this gist (older runs — 2026-04-23, 2026-06-06 — are in the gist's revision history): https://gist.github.com/dims/e7e55d375149d0c3b4d38f85c8cea172

Key findings from the most recent run, 2026-07-20 (Prow job 2079173402668568576) — use as a sanity check for your methodology:

  • MEDIUM: go-openapi/swag family (12 modules) v0.25.4→v0.27.1 — GHSA-xh24-9qpg-8w28 (jsonutils stack-exhaustion DoS) + GHSA-hwp8-w8pv-xq8f (yamlutils billion-laughs), published 2026-07-19 against the then-current pin, repo-level only (absent from OSV/global index on run day); unreachable from untrusted input in k8s (kube-openapi uses only ConcatJSON/name-provider/conv + one struct-gated call), and the bump MVS-forces jsonpointer v1.0.0
  • MEDIUM: google.golang.org/grpc v1.81.1→v1.82.1 — upstream security release: HTTP/2 control-frame-flood mitigation (grpc/grpc-go#9236, no CVE, no v1.81.x backport) + removal of the GRPC_GO_EXPERIMENTAL_DISABLE_STRICT_PATH_CHECKING kill switch that could re-open CVE-2026-33186
  • LOW: opencontainers/cgroups v0.0.6→v0.0.7 — eBPF fd-leak fix unreachable twice over (k8s vendors only devices/config; kubelet sets SkipDevices: true)
  • NONE despite scary name: cyphar/filepath-securejoin v0.6.1→v0.7.0 — entire delta sits behind the //go:build libpathrs tag k8s never sets; pure-Go SecureJoin byte-identical
  • Earlier-run sanity anchors: 2026-04-23 found HIGH golang.org/x/net CVE-2026-33814 and HIGH fxamacker/cbor/v2 v2.9.1 (both since adopted); 2026-06-06 found zero HIGH/MEDIUM and flagged etcd's latest as a do-not-bump pre-release alpha

Kubernetes Dependency Security Analysis

Date: 2026-07-20 Prow job: ci-kubernetes-e2e-kind-dependencies #2079173402668568576 (SUCCESS, started 2026-07-20T11:56:11Z) — differences.md Packages analyzed: 44 (non-~ rows; 32 logical units after grouping swag ×12 and genproto ×2) Method: GitHub diff inspection (gh api compare), Go Vulnerability Database/OSV, CVE/GHSA search including repo-level security advisories, K8s source grep for reachability (master @ 9f6a7610f66, identical to origin/master; all pins verified against the differences table)


Executive Summary

Of 44 gapped packages, two logical units are MEDIUM and should land in the next dependency PR — the first time since the 2026-04-23 baseline that published advisories exist against current k8s pins. (1) The go-openapi/swag family (12 modules): upstream published two GHSAs on 2026-07-19 affecting the pinned v0.25.4 — a jsonutils stack-exhaustion DoS (upstream-labeled HIGH) and a yamlutils billion-laughs — fixed only in v0.27.1; grep evidence shows no untrusted-input path reaches the vulnerable entry points in any k8s binary, but the advisories will start tripping scanners as they propagate (they were still absent from OSV and the global GHSA index on run day). The bump MVS-forces jsonpointer v1.0.0. (2) grpc v1.81.1→v1.82.1 is an upstream security release: server-side HTTP/2 control-frame-flood mitigation (absent from the pin; no v1.81.x backport exists) plus removal of the env-var kill switch that could re-open CVE-2026-33186. Beyond those: 0 CRITICAL, 0 HIGH, 8 LOW, 22 NONE. Every headline item from June (x/net, x/crypto, etcd) has been adopted and left the gap list.


What changed since the 2026-06-06 run

June finding Status today
golang.org/x/net, golang.org/x/crypto, go.etcd.io/etcd/* gaps Adopted/resolved — all now ~ at latest (etcd landed v3.7.0 GA, past June's do-not-bump alpha).
LOW fxamacker/cbor/v2 v2.9.1→v2.9.2, selinux v1.13.1→v1.15.1, coredns/caddy v1.1.1→v1.1.4, sctp, gettext-go Still open, unchanged ranges — re-verified, conclusions stand (see Priority 3).
LOW go-openapi/swag v0.25.4→v0.26.0 (opt-in provider only) Escalated to MEDIUM — latest is now v0.27.1, and two GHSAs published 2026-07-19 affect the current pin (see Priority 2).
LOW otel-contrib 0.68→0.69 (3 modules) Partially adopted — the June k8s bump (defb4c53cd6) moved otelhttp/otelrestful but missed otelgrpc (declared direct only in staging go.mods, root-// indirect). Hygiene fix, no security delta.
containerd/typeurl/v2, corefile-migration, hnslib, ginkgo gaps Adopted — gone from the list.
New gaps since June opencontainers/cgroups v0.0.7, cadvisor/lib v0.60.5, filepath-securejoin v0.7.0 + go-pathrs v0.2.5, grpc v1.82.1, httpsnoop v1.1.0, go-openapi jsonpointer/jsonreference v1.0.0 majors, genproto pseudo-version, prometheus/common →v0.70.0, prometheus/procfs →v0.21.1, gomega →v1.42.1, x/{exp,mod,tools} heads.

Priority 1 — UPGRADE PROMPTLY

None this cycle. No CRITICAL or HIGH finding: no gapped package carries a vulnerability reachable from untrusted input at the current pins.


Priority 2 — MEDIUM (upgrade in next dep sweep)

github.com/go-openapi/swag (+ 11 submodules) v0.25.4 → v0.27.1

(cmdutils, conv, fileutils, jsonname, jsonutils, loading, mangling, netutils, stringutils, typeutils, yamlutils — all move v0.25.4→v0.27.1 from this repo; submodule tags verified.) CVE: None assigned yet. Two repo-published GHSAs (2026-07-19), both affecting the current pin (<= 0.27.0, patched v0.27.1):

  • GHSA-xh24-9qpg-8w28HIGH (upstream label) — uncontrolled recursion in ordered JSON marshal/unmarshal (jsonutils): swag's own lexer bypasses stdlib's 10000-depth guard; a ~6 MB payload of ~3M nested [ causes a non-recoverable fatal error: stack overflow.
  • GHSA-hwp8-w8pv-xq8fMEDIUM (upstream label) — uncontrolled resource consumption via YAML anchor/alias expansion in yamlutils.YAMLToJSON ("billion laughs").
  • Neither was in OSV or the global GHSA index as of 2026-07-20 (repo-level links above are the verified ones; global github.com/advisories/... URLs will work once they propagate). Type: Security-fix release — recursion-depth bounds on ordered-JSON marshal/unmarshal and YAML↔JSON transforms, YAML anchor/alias expansion caps with cycle detection, plus an opt-in loading.WithRoot sandbox. Fix commit/PR: PR #220 (merged 2026-07-18) — 0c24346c (jsonutils recursion bound), d0b90a81 (yamlutils recursion bound), bba3dcff (anchor/alias expansion bound). Also in range: eefaba13 (PR #203) — opt-in loading.WithRoot sandbox for LoadFromFileOrHTTP file-read confinement.

What it does: Utility toolkit behind the go-openapi ecosystem; in k8s it backs vendored k8s.io/kube-openapi, which serves/validates OpenAPI in kube-apiserver and kubectl.

K8s reachability (LOW for the vulnerable entry points; the module links into kube-apiserver and kubectl):

  • Only consumer in the entire build is vendored kube-openapi importing the root facade — zero non-vendor imports (grep -rn '"github.com/go-openapi/swag' pkg/ cmd/ staging/ plugin/ test/ = 0 hits).
  • kube-openapi's full facade usage: swag.ConcatJSON (byte-level concatenation — not an advisory entry point; jsonutils/concat.go untouched in range), swag.DefaultJSONNameProvider.GetJSONNames (name-provider code relocated into jsonpointer v1.0.0 in-range, behavior identical), swag.Convert*/Format*/IsFloat64AJSONInteger scalar helpers, and exactly one recursive-path call: swag.ToDynamicJSON(data) at vendor/k8s.io/kube-openapi/pkg/validation/validate/schema.go:150.
  • That one call is gated if kind == reflect.Struct; its only importers are apiextensions-apiserver CR validation (staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/validation/{validation.go,ratcheting.go}), which always pass unstructured map[string]interface{} — the struct branch never executes, so attacker-controlled depth never reaches swag's recursive lexer (inbound CR bodies are also depth-capped by the JSON decoder before validation).
  • Zero callers anywhere (tree + vendor) of the advisory entry points ReadJSON/WriteJSON/JSONMapSlice/YAMLToJSON/BytesToYAMLDoc/YAMLDoc/JSONDoc/LoadFromFileOrHTTP — k8s YAML handling is sigs.k8s.io/yaml, not swag.

Attack scenario: None reachable today — it would require a k8s code path feeding attacker-controlled deeply-nested JSON/YAML into swag's ordered-JSON or YAML entry points, and none exists. The concrete risk is published-advisory exposure on pinned modules: vuln scanners will flag kube-apiserver/kubectl once the GHSAs reach OSV/the global index, and future kube-openapi drift could add a reachable call site.

Action:

./hack/pin-dependency.sh github.com/go-openapi/swag v0.27.1
# repeat for the 11 swag/* submodules (cmdutils conv fileutils jsonname jsonutils loading mangling netutils stringutils typeutils yamlutils)
./hack/pin-dependency.sh github.com/go-openapi/jsonpointer v1.0.0    # MVS-forced: swag v0.27.1's go.mod requires it
./hack/pin-dependency.sh github.com/go-openapi/jsonreference v1.0.0  # set consistency
./hack/update-vendor.sh   # adds new indirect github.com/go-openapi/swag/pools v0.27.1

google.golang.org/grpc v1.81.1 → v1.82.1

CVE: None filed for the v1.82.1 items (they appear only in the release-notes Security section). No advisory affects v1.81.1 itself (all grpc-go advisories fixed ≤ v1.79.3 — see "CVEs Already Patched"). Note: the differences.md URL for this row wrongly points at protocolbuffers/protobuf-go; the compare above is the correct repo/range (57 commits). Type: Upstream security patch release: server-side HTTP/2 control-frame-flood mitigation + removal of the CVE-2026-33186 kill switch + a gzip-bomb OOM fix in a legacy API. Fix commit/PR:

  • 4ea465d4 (PR #9236) — "server: Stop reading from the connection when flooded by HTTP/2 frames": caps queued non-DATA/non-HEADERS control frames (default 100, tunable via GRPC_GO_EXPERIMENTAL_CONTROL_BUFFER_THROTTLE_LIMIT). Absent from the current pin — vendored vendor/google.golang.org/grpc/internal/transport/controlbuf.go has only the old throttle() that blocks reads at 50 queued transport-response frames, and no v1.81.2 backport exists (releases: v1.82.1 → v1.82.0 → v1.81.1).
  • 1c63fa5f (PR #9112) — removes GRPC_GO_EXPERIMENTAL_DISABLE_STRICT_PATH_CHECKING. At the current pin the kill switch still exists (vendor/google.golang.org/grpc/internal/envconfig/envconfig.go:107-121) and, if an operator set it, would re-open CVE-2026-33186 (:path authz bypass, CVSS 9.1). v1.82 makes strict path checking unconditional.
  • 761e655b (PR #9114) — bounds decompression in the legacy gzip Decompressor (gzip bomb → OOM before MaxRecvMsgSize). Unreachable in k8s: zero callers of NewGZIPDecompressor/WithDecompressor outside vendored grpc; the modern encoding path k8s uses was already io.LimitReader-bounded.

What it does: The gRPC stack under every k8s RPC surface.

K8s reachability (VERY HIGH surface; flood fix is server-side, k8s gRPC servers are local-socket only):

  • Servers (the party the flood fix protects): kubelet podresources + pods API (pkg/kubelet/server/server.go:253,274 on util.LocalEndpoint unix sockets), device-plugin registration (pkg/kubelet/cm/devicemanager/plugin/v1beta1/server.go:115), DRA kubelet-plugin helper (staging/src/k8s.io/dynamic-resource-allocation/kubeletplugin/nonblockinggrpcserver.go:75).
  • Clients (trusted peers): apiserver→etcd (staging/src/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd3.go), apiserver→KMS, konnectivity egress, kubelet→CRI (staging/src/k8s.io/cri-client/pkg/remote_runtime.go), CSI, DRA.
  • xds/rbac fixes in range are dead code (k8s uses no grpc-xds).

Attack scenario: A node-local process with access to kubelet's plugin/podresources unix sockets (already root/hostPath-privileged) floods non-DATA/HEADERS HTTP/2 frames to burn kubelet memory/CPU faster than the old throttle contains. Not exploitable by an unprivileged or remote actor in standard deployments — but upstream shipped it as a dedicated security release, there is no backport for the pinned minor, and the strict-path kill-switch removal is defense-in-depth for a 9.1-severity bypass.

Action: ./hack/pin-dependency.sh google.golang.org/grpc v1.82.1 then ./hack/update-vendor.sh


Priority 3 — LOW (batch in next routine dep PR)

github.com/opencontainers/cgroups v0.0.6 → v0.0.7 (new gap)

CVE: None filed (OSV/GHSA empty) Type: fd-leak fixes in the eBPF device-filter loader + new opt-in per-controller Stats(opts) API + omitemptyomitzero JSON-tag churn. Fix: PR #607bbbeee9. K8s reachability (LOW): kubelet's cgroup manager imports it in 14 production files (root on every Linux node), but the eBPF fix is unreachable twice over — k8s vendors only devices/config (no devices/), and kubelet sets SkipDevices: true (pkg/kubelet/cm/cgroup_manager_linux.go:286). The compiled hot path (GetStatsStats(nil) refactor) preserves every collector and error path (full patches read); the JSON-tag churn is inert (no importer serializes the structs). Action: batch — ./hack/pin-dependency.sh github.com/opencontainers/cgroups v0.0.7 (co-bump cadvisor/lib below; cadvisor consumes this Manager interface).

github.com/opencontainers/selinux v1.13.1 → v1.15.1 (unchanged from June — re-verified)

CVE: No advisory in range (historical CVE-2025-52881, CVE-2019-16884 fixed below the pin — see Already-Patched table). Type: SEUserByName infinite-loop fix (1eb98c40, PR #251) — uncalled by k8s (grep re-verified) — and a label.InitLabels spurious-ErrMCSAlreadyExists regression fix (89b039b4, PR #267). K8s reachability (MEDIUM surface): label.InitLabels called at pkg/volume/util/selinux.go:73 with pod v1.SELinuxOptions-derived args — kubelet volume manager on SELinux-enforcing nodes; worst pre-fix case is a spurious mount failure, no crash/OOB/escape. Action: batch — ./hack/pin-dependency.sh github.com/opencontainers/selinux v1.15.1

github.com/fxamacker/cbor/v2 v2.9.1 → v2.9.2 (unchanged from June — re-verified)

CVE: None filed (OSV empty) Type: Streaming-encoder hardening (281203ee: reject odd-count indefinite-length map encoding, validate chunk major types) + TagSet.Remove(nil) no-op (8191a0db). K8s reachability (LOW for this delta): this is the kube-apiserver application/cbor codec, but the hardened APIs are unreachable — the k8s encoder sets IndefLength: cbor.IndefLengthForbidden (staging/src/k8s.io/apimachinery/pkg/runtime/serializer/cbor/internal/modes/encode.go:62) and nothing calls StartIndefinite*/EndIndefinite (0 hits, re-grepped); the untrusted-input decoder is unchanged in this release. Action: batch — ./hack/pin-dependency.sh github.com/fxamacker/cbor/v2 v2.9.2 (keep the apiserver codec current).

cyphar.com/go-pathrs v0.2.2 → v0.2.5 (extended range; co-bump with filepath-securejoin v0.7.0)

CVE: None filed (OSV/GHSA empty) Type: Rust-core resolver hardening (fail-closed /proc fallback 7a00b28b, procfs fstype checks 24504068) + a breaking Go-binding flags rework (u64). K8s reachability (LOW): re-verified — the only importers are three //go:build libpathrs-gated files in vendored filepath-securejoin, and k8s never sets that tag (no libpathrs in hack/, build/, Makefile); not compiled into any k8s binary. filepath-securejoin v0.7.0 keeps the tag split, so this stays opt-in. Action: batch — co-bump: ./hack/pin-dependency.sh github.com/cyphar/filepath-securejoin v0.7.0 && ./hack/pin-dependency.sh cyphar.com/go-pathrs v0.2.5 (securejoin v0.7.0's go.mod requires go-pathrs ≥ v0.2.5).

github.com/coredns/caddy v1.1.1 → v1.1.4 (unchanged from June — re-verified)

CVE: None filed (the "caddy" GHSAs belong to caddyserver/caddy, a different module) Type: Corefile-parser DoS guards: NextBlock() infinite loop (15135a99, PR #10), snippet import cycles (fabd98a6), expansion caps (543b91ba), nested-block parse fix (32b690fa, PR #12). K8s reachability (LOW): kubeadm only (via corefile-migration), parsing the kube-system CoreDNS ConfigMap during kubeadm upgrade — cluster-admin-controlled input, one-shot CLI; worst case a hang for the admin who authored it. Action: batch with the next CoreDNS/kubeadm refresh.

github.com/prometheus/common v0.67.5 → v0.70.0 (new delta since June)

CVE: None filed — including for the credential fix below (shipped without an advisory). Type: expfmt text-parser nil-deref panic fix on {} input (a1600af9, PR #922) + credential-stripping on cross-host redirects in config (0d8de871). K8s reachability (LOW): k8s vendors only expfmt + model; the credential fix is in un-vendored config (zero importers — dead for k8s). All expfmt parse sites consume k8s's own gathered /metrics output in test/testutil code; runtime use is encoder/content-negotiation only (untouched by the panic fix). Action: batch — ./hack/pin-dependency.sh github.com/prometheus/common v0.70.0

github.com/ishidawataru/sctp ae8eb7fa7995 → 19ddcbc6aae2 (unchanged from June — re-verified, description corrected)

CVE: None filed (OSV/GHSA empty) Type: SyscallConn/FileListener FD-passing features + always-set SOCK_CLOEXEC hardening (1989182a). (Correction to the June note: there is no "PPID byte-order fix" in this range.) K8s reachability (LOW): test-images only (test/images/agnhost/{netexec,porter,connect}); kube-proxy SCTP is native netlink, not this library (0 hits in pkg/proxy, cmd/kube-proxy). Action: batch with the next agnhost test-image refresh.

github.com/chai2010/gettext-go v1.0.2 → v1.0.3 (unchanged from June — re-verified)

CVE: None filed (OSV/GHSA empty) Type: .po parser \r handling (bdc72a5f) + plural-formula fix (846be827). K8s reachability (LOW): kubectl i18n only (staging/src/k8s.io/kubectl/pkg/util/i18n/i18n.go:29); catalogs are first-party //go:embed-ded assets selected by the user's own LANG — never attacker-supplied. Action: batch with the next kubectl-deps refresh.


Priority 4 — NONE (no action needed)

Package Diff Reason no action needed
github.com/cyphar/filepath-securejoin v0.6.1 → v0.7.0 Whole delta is a go.mod floor raise + a 1-line uint64 cast inside a //go:build libpathrs file k8s never compiles; the pure-Go SecureJoin/pathrs-lite paths kubelet uses (pkg/kubelet/kubelet_pods.go:958) are byte-identical. Co-bump with go-pathrs (P3).
github.com/felixge/httpsnoop v1.0.4 → v1.1.0 Feature/perf release (StringWriter, FlushError, ResponseController deadlines); the in-range PR #33 hook-bypass regression was fixed by PR #35 before the tag. Wraps every apiserver request via otelhttp (kubelet uses otelrestful, not this) — sanity-check exec/attach (Hijack) when batching since wrap_generated.go is fully regenerated.
github.com/pquerna/cachecontrol v0.1.0 → v0.2.0 Adds RFC 5861 stale-if-error request-directive parsing; the sole k8s path (go-oidc JWKS fetch from the admin-trusted IdP) never sets or reads it.
github.com/google/cadvisor/lib v0.60.4 → v0.60.5 Opt-in DisableContainerDiscovery flag kubelet never sets (default preserves old behavior; pkg/kubelet/cadvisor/cadvisor_linux.go:116 uses named fields) + CI scripts. lib/v0.60.5 tag exists upstream this time. Co-bump with opencontainers/cgroups.
github.com/container-storage-interface/spec v1.9.0 → v1.12.0 Generated proto stubs + additive RPCs over the trusted local kubelet↔CSI socket; all transitive floors (grpc v1.57.1, protobuf v1.33.0, x/net v0.38.0) far below k8s pins. Feature-only adopt.
github.com/containerd/containerd/api v1.11.0 → v1.11.1 Two additive generated proto fields on CreateTaskRequest (e44f5f9e), a message k8s's only consumer (vendored cadvisor, Get-only) never sends; kubelet CRI uses k8s.io/cri-api.
github.com/go-openapi/jsonpointer v0.22.4 → v1.0.0 Feature/correctness major (absorbs jsonname, RFC 6901 "-" token, Offset fix) with zero security content and zero direct k8s call sites (reached only via jsonreference $ref parsing). MVS-forced by swag v0.27.1 — adopt in the same PR (same import path, API preserved).
github.com/go-openapi/jsonreference v0.21.4 → v1.0.0 Major re-tag whose only non-test source change is one doc comment; the $ref URL normalizer (internal/normalize_url.go) is byte-identical. Bump alongside swag/jsonpointer for set consistency.
github.com/google/gnostic-models v0.7.0 → v0.7.1 .proto go_package Bazel metadata fix only (289d7b49); zero .go changes — vendored parsers byte-identical.
cel.dev/expr v0.25.1 → v0.25.2 Proto-types-only module (evaluator is cel-go); diff is conformance testdata + docs + Bazel-registry CI, zero Go delta.
google.golang.org/genproto/googleapis/{api,rpc} 3dc84a4a5aaa → e75dac1f907d Not one of the 16 vendored files changes: delta is un-vendored chromeos/dialogflow regeneration + go.mod floors k8s already exceeds; googleapis/rpc/ has zero changed files (pseudo-version tracks repo HEAD).
go.opentelemetry.io/contrib/.../otelgrpc v0.68.0 → v0.69.0 semconv v1.41 import swap + deprecated-API removal (k8s calls none of it) + alloc-avoidance; June's k8s bump missed this module because it's root-// indirect (direct only in staging go.mods). Align to v0.69.0 as hygiene — all floors already satisfied, semconv/v1.41.0 already vendored.
go.uber.org/zap v1.27.1 → v1.28.0 Only source change is an opt-in zapcore.PreWriteHook k8s never installs (0ab0d5aa); yaml dep swap is go.mod-only.
github.com/prometheus/procfs v0.19.2 → v0.21.1 Every changed file is a /proc//sysfs parser k8s never calls; the two runtime callers (component-base process-start-time, client_golang process collector) read own-PID stat/fd/limits, untouched across the whole range.
golang.org/x/exp 746e56fc → 764159d7 Only vendored package is slices (kept alive by antlr→cel-go), unchanged; delta is apidiff/typeparams/LLM-eval tooling k8s doesn't vendor.
golang.org/x/mod v0.37.0 → v0.38.0 Two commits (comment fixes + dep bump) touching modfile/sumdb/zip — zero overlap with the vendored module/semver/lazyregexp packages.
golang.org/x/tools v0.47.0 → v0.48.0 gopls/analyzer-dominated delta; the few changed vendored files serve build-time (import-boss, gengo) and CI/test (typecheck, ginkgo) tooling only — no shipped binary links x/tools.
github.com/Masterminds/semver/v3 v3.4.0 → v3.5.0 Parsing-edge-case delta; only consumer is Ginkgo's test label filter (trusted input, not shipped). (differences.md URL malformed — /v3 is a module path, not a repo path.)
github.com/cpuguy83/go-md2man/v2 v2.0.6 → v2.0.7 roff table-rendering fix consumed only by build-time cmd/genman on first-party input.
github.com/go-errors/errors v1.4.2 → v1.5.1 Additive Join/Unwrap; sole consumer is kubectl-side kustomize via unchanged functions.
github.com/google/pprof 545e8a4d → b9395ee1 Vendored profile/ package unchanged across the whole range; the lone code fix (92041b74, un-vendored internal/driver) was already in June's range, and the new delta is CI-only.
github.com/onsi/gomega v1.40.0 → v1.42.1 Extended delta is a version-constant bump + docs/AI-plugin markdown + dep floors k8s already exceeds; matcher library remains test-only (452 import sites, all test code).

Action Plan (ordered)

# 1) MEDIUM — published GHSAs against current pins; land in the next dep PR
./hack/pin-dependency.sh github.com/go-openapi/swag v0.27.1
for m in cmdutils conv fileutils jsonname jsonutils loading mangling netutils stringutils typeutils yamlutils; do
  ./hack/pin-dependency.sh github.com/go-openapi/swag/$m v0.27.1
done
./hack/pin-dependency.sh github.com/go-openapi/jsonpointer v1.0.0    # MVS-forced by swag v0.27.1
./hack/pin-dependency.sh github.com/go-openapi/jsonreference v1.0.0  # set consistency

# 2) MEDIUM — upstream security release (HTTP/2 frame-flood mitigation; no v1.81.x backport)
./hack/pin-dependency.sh google.golang.org/grpc v1.82.1

# 3) LOW batch — fold into the same or next routine PR
./hack/pin-dependency.sh github.com/fxamacker/cbor/v2 v2.9.2            # apiserver CBOR codec hygiene
./hack/pin-dependency.sh github.com/opencontainers/selinux v1.15.1      # InitLabels fix (SELinux nodes)
./hack/pin-dependency.sh github.com/opencontainers/cgroups v0.0.7       # kubelet cgroup lib
./hack/pin-dependency.sh github.com/google/cadvisor/lib v0.60.5         # co-bump with cgroups
./hack/pin-dependency.sh github.com/cyphar/filepath-securejoin v0.7.0   # co-bump pair —
./hack/pin-dependency.sh cyphar.com/go-pathrs v0.2.5                    # securejoin v0.7.0 requires ≥ v0.2.5
./hack/pin-dependency.sh github.com/prometheus/common v0.70.0           # expfmt parser panic fix (test surface)

# 4) Hygiene — close the intra-family skew the June otel bump missed
./hack/pin-dependency.sh go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.69.0

./hack/update-vendor.sh
# then: hack/lint-dependencies.sh ; check hack/unwanted-dependencies.json
# post-bump sanity (httpsnoop lands transitively with otel updates): exercise kubectl exec/attach (Hijack path)

# Remainder (no security value — batch with their natural refreshes):
#   coredns/caddy (kubeadm/CoreDNS), ishidawataru/sctp (agnhost images),
#   chai2010/gettext-go (kubectl i18n), CSI spec (feature adopt),
#   containerd/containerd/api (containerd/cadvisor refresh), httpsnoop, cachecontrol,
#   gnostic-models, cel.dev/expr, genproto {api,rpc}, zap, prometheus/procfs,
#   x/{exp,mod,tools}, Masterminds/semver/v3, go-md2man/v2, go-errors, pprof, gomega

CVEs Already Patched (verify current vendor is sufficient)

OSV returns zero advisories affecting the current pin of every gapped package. The advisories below all exist but were fixed at or below the current pins. (The two swag GHSAs are deliberately not here — they affect the current pin and are the Priority 2 action item.)

CVE GHSA / Go vuln Package Fixed in Current k8s pin Status
CVE-2026-33186 (:path authz bypass, CVSS 9.1) GHSA-p77j-4mvh-x3m3 / GO-2026-4762 google.golang.org/grpc v1.79.3 v1.81.1 ✅ Patched — but the GRPC_GO_EXPERIMENTAL_DISABLE_STRICT_PATH_CHECKING kill switch still exists at the pin; removed in v1.82 (see Priority 2)
— (HTTP/2 Rapid Reset DoS) GHSA-m425-mq94-257g / GO-2023-2153 google.golang.org/grpc v1.56.3/v1.57.1/v1.58.3 v1.81.1 ✅ Patched
— (metadata tokens in logs) GHSA-xr7q-jx4m-x55m / GO-2024-2978 google.golang.org/grpc v1.64.1 v1.81.1 ✅ Patched
— (Windows rootfs escape) GHSA-6xv5-86q9-7xr8 / GO-2023-2048 github.com/cyphar/filepath-securejoin v0.2.4 v0.6.1 ✅ Patched (kubelet's use is Linux-side anyway)
CVE-2025-52881 (runc procfs write redirect) GHSA-cgrx-mc8f-2prm / GO-2025-4098 github.com/opencontainers/selinux v1.13.0 v1.13.1 ✅ Patched
CVE-2019-16884 (AppArmor/SELinux mount bypass) GHSA-fgv8-vj5c-2ppq / GO-2021-0085 github.com/opencontainers/selinux v1.3.1-0.20190929122143 v1.13.1 ✅ Patched
CVE-2023-47108 (metric-cardinality DoS) GHSA-8pgv-569h-w5rw / GO-2023-2331 go.opentelemetry.io/contrib/.../otelgrpc v0.46.0 v0.68.0 ✅ Patched (k8s uses only the client stats handler, never the vulnerable server interceptor)

Also at-pin (no advisory filed): grpc v1.81.1 itself shipped the xds/rbac SAN→Subject-DN bypass fix (PR #9111) — included in the pin, and grpc-xds is unused by k8s regardless.


Analysis by 5 parallel tier agents over the 32 logical units in Prow job 2079173402668568576, then independently re-verified end-to-end before publication: all 32 compare URLs, 27 fix-commit SHAs, 14 PR numbers, 7 global GHSA + 2 repo-level advisories, 7 Go vuln IDs, and 4 CVEs (NVD) resolved and cross-checked; the 44-row/32-unit accounting and every pin machine-confirmed against vendor/modules.txt; the load-bearing greps behind both MEDIUM findings re-derived against the k/k checkout at 9f6a7610f66. Vuln sources: OSV, pkg.go.dev/vuln, GitHub Security Advisories (global + repo-level), NVD.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment