From 7d6142c605e78eebb2f7c49b6490569879ac1cca Mon Sep 17 00:00:00 2001 From: Nikolai Emil Damm Date: Sat, 18 Jul 2026 22:40:30 +0200 Subject: [PATCH] fix(headlamp): disable unverified plugin downloads --- .../apps/headlamp/cilium-network-policy.yaml | 25 ++--------- k8s/bases/apps/headlamp/helm-release.yaml | 41 ++++--------------- 2 files changed, 10 insertions(+), 56 deletions(-) diff --git a/k8s/bases/apps/headlamp/cilium-network-policy.yaml b/k8s/bases/apps/headlamp/cilium-network-policy.yaml index 609c719ea..3a5387a88 100644 --- a/k8s/bases/apps/headlamp/cilium-network-policy.yaml +++ b/k8s/bases/apps/headlamp/cilium-network-policy.yaml @@ -17,30 +17,11 @@ spec: # Kube API for dashboard - toEntities: - kube-apiserver - # Dex OIDC (via Cloudflare proxy) + plugin downloads: pluginsManager - # resolves plugin metadata on artifacthub.io and fetches the archives - # from GitHub releases (helm-release.yaml). Pinned by FQDN instead of - # world:443 so a compromised pod cannot exfiltrate to arbitrary - # external services. - # github.com 302-redirects a release-asset download - # (github.com///releases/download/...) to this release-asset - # CDN; without it every plugin archive fetch times out, the - # headlamp-plugin sidecar crashloops and the dashboard ships with no - # plugins. Same gap the kubescape policy already had to close. - # registry.npmjs.org: the headlamp-plugin sidecar bootstraps each plugin - # with `npx @headlamp-k8s/pluginctl ...`, which downloads pluginctl (and its - # deps) from the npm registry. Missing it -> npm ETIMEDOUT -> the sidecar - # crashloops on every (re)start; regression from the world:443 -> FQDN - # lockdown (#2019). + # Dex OIDC (via Cloudflare proxy). Dynamic plugin downloads are disabled + # in helm-release.yaml, so Headlamp no longer needs Artifact Hub, GitHub + # release assets, or npm egress at runtime. - toFQDNs: - matchName: "dex.${domain}" - - matchName: "artifacthub.io" - - matchName: "github.com" - - matchName: "api.github.com" - - matchName: "objects.githubusercontent.com" - - matchName: "raw.githubusercontent.com" - - matchName: "release-assets.githubusercontent.com" - - matchName: "registry.npmjs.org" toPorts: - ports: - port: "443" diff --git a/k8s/bases/apps/headlamp/helm-release.yaml b/k8s/bases/apps/headlamp/helm-release.yaml index 0a3fc0519..b2b9f1238 100644 --- a/k8s/bases/apps/headlamp/helm-release.yaml +++ b/k8s/bases/apps/headlamp/helm-release.yaml @@ -134,45 +134,18 @@ spec: clusterRoleBinding: create: false config: - watchPlugins: true + # Disable dynamic plugin loading until Headlamp supports committing + # plugin artifact integrity (digest/checksum) in GitOps state. The + # pluginsManager resolves Artifact Hub metadata at runtime by name/version + # only, which can install unverified same-origin JavaScript into the + # dashboard if an upstream package or delivery path is compromised. + watchPlugins: false oidc: clientID: public-client issuerURL: https://dex.${domain} scopes: "profile,email,groups" pluginsManager: - enabled: true - configContent: | - plugins: - - name: headlamp_flux - source: https://artifacthub.io/packages/headlamp/headlamp-plugins/headlamp_flux - version: 0.6.0 - - name: headlamp_cert-manager - source: https://artifacthub.io/packages/headlamp/headlamp-plugins/headlamp_cert-manager - version: 0.1.0 - - name: headlamp_keda - source: https://artifacthub.io/packages/headlamp/headlamp-plugins/headlamp_keda - version: 0.1.1-beta - - name: headlamp_opencost - source: https://artifacthub.io/packages/headlamp/headlamp-plugins/headlamp_opencost - version: 0.1.3 - - name: headlamp_kubescape - source: https://artifacthub.io/packages/headlamp/kubescape-headlamp-plugin/headlamp_kubescape - version: 0.11.2 - # Crossplane dashboard. Surfaces the Flux-managed Crossview app - # (apps/crossview) inside Headlamp via its "Open Crossview" action. - # Crossview has NO public route or homepage tile — this plugin is the - # ONLY entry point; its resolver falls through to a Headlamp-managed - # port-forward of crossview-service (crossview >= 4.5.0 handles OIDC - # on that split-horizon localhost origin via its empty-issuer - # skip-discovery fix — see apps/crossview/helm-release.yaml). - # Do NOT use the plugin's Install/Update/Uninstall buttons — those run - # a cluster-admin Helm Job; Crossview is managed declaratively by Flux. - - name: crossview-headlamp - source: https://artifacthub.io/packages/headlamp/crossview-headlamp/crossview-headlamp - version: 0.1.4 - installOptions: - parallel: true - maxConcurrent: 3 + enabled: false persistentVolumeClaim: enabled: false podSecurityContext: