KubeBolt 1.23.1 — cross-organization metric read, and four fixes behind it
1.23.1 is a security patch over 1.23.0. Drop-in — no schema change, no
migration, no agent bump (the node agent stays at 1.3.1).
Upgrade if you run KubeBolt with more than one organization. The rest of this
release is worth having; the first item is worth acting on.
Security
Cross-organization metric read. Any authenticated user — a viewer included —
could read another organization's series by naming the tenant in their own
PromQL. injectLabelMatcher left a {...} selector alone when it already
mentioned the label the server was about to inject, so a client-supplied
tenant_id or cluster_id survived into the query and the server's own scope
was never applied.
Those labels are now stripped from client input before the server injects its
own, so the server is the sole source of scope. Validated read-only against a
production cluster.
Both metric paths are covered — instant and range — along with the
subquery/nested-selector shapes that a hand-written PromQL can reach.
Fixes
-
Insights outlived their cause. A rule fired, and the insight then aged out
on a timer rather than when the underlying condition cleared. A recovered
workload could stay flagged for up to an hour. Every rule is now a predicate
over current state: a historical artefact may arm an alert but never keeps one
alive. Persisted insights are hydrated at boot, so a restart no longer strands
active ones. An invariant test covers all 24 rules and fails if a new rule is
added that violates the property. -
A nameless fallback AI provider broke Kobi turns. When the fallback was
configured without a provider name, a recoverable error on the primary turned
into a bareunknown provider:and the whole turn failed — the fallback made
things worse than having none. Reproduced locally in both directions. -
Settings errors said only that they failed. A rejected settings save
answers with{error, field, message}, whereerroris the category and
messageis the reason. The client readerrorfirst, so every settings form
showed a flat "validation failed" and discarded the only part that said what to
fix — including the Slack webhook validator, whosemessagecarries the real
parse error. -
The cluster map showed phantom external endpoints. The
(external)region
filled with nodes nothing connected to. Pods were filtered by kind and
namespace, but the loop building external nodes walked every flow in the
cluster, so a namespace-scoped view still got a node for every destination
anyone had talked to; their edges were then dropped, leaving the nodes
orphaned. They were not destinations without connections — every one is built
from a flow — they were destinations whose connection came from a namespace
the viewer had already excluded. On one dev cluster a vulnerability scanner
pulling its database from CDNs accounted for 96 of the distinct external
addresses while the two visible namespaces contributed one between them.
Upgrading
helm upgrade kubebolt oci://ghcr.io/clm-cloud-solutions/kubebolt/helm/kubebolt --version 1.23.1No values change, no agent action required.
Install
Helm (recommended for Kubernetes)
helm install kubebolt oci://ghcr.io/clm-cloud-solutions/kubebolt/helm/kubebolt
kubectl port-forward svc/kubebolt 3000:80Single Binary (download below)
# macOS Apple Silicon
curl -LO https://github.com/clm-cloud-solutions/kubebolt/releases/download/v1.23.1/kubebolt-darwin-arm64
chmod +x kubebolt-darwin-arm64 && mv kubebolt-darwin-arm64 /usr/local/bin/kubebolt
# Linux amd64
curl -LO https://github.com/clm-cloud-solutions/kubebolt/releases/download/v1.23.1/kubebolt-linux-amd64
chmod +x kubebolt-linux-amd64 && sudo mv kubebolt-linux-amd64 /usr/local/bin/kubebolt
kubebolt --kubeconfig ~/.kube/configAll platform binaries are attached below. Verify with sha256sum -c CHECKSUMS.txt.
Docker (single container)
docker run -p 3000:3000 -v ~/.kube:/root/.kube:ro \
ghcr.io/clm-cloud-solutions/kubebolt:1.23.1Homebrew (macOS, Linux)
brew install clm-cloud-solutions/tap/kubeboltkubectl krew plugin
kubectl krew index add clm https://github.com/clm-cloud-solutions/krew-index.git
kubectl krew install clm/kubebolt
kubectl kubeboltDocker Compose
git clone https://github.com/clm-cloud-solutions/kubebolt.git
cd kubebolt/deploy && docker compose up -dContainer Images
- Single container (binary + frontend):
ghcr.io/clm-cloud-solutions/kubebolt:1.23.1 - API only:
ghcr.io/clm-cloud-solutions/kubebolt/api:1.23.1 - Web only:
ghcr.io/clm-cloud-solutions/kubebolt/web:1.23.1
Changelog
Fixes
- fix(map): only show external endpoints reachable from a visible pod ()
- fix(web): show why a settings save was rejected, not just that it was ()
- fix(copilot): stop a nameless fallback provider from breaking Kobi turns ()
- fix(security): strip client-supplied tenant_id/cluster_id from PromQL ()
- fix(web): make the useWebSocket test typecheck ()
- fix(insights): clear on observed recovery, not on a clock ()
Documentation
- docs(insights): revise the flap-damping analysis; add ==> Go build + vet
==> Go test -race
? github.com/kubebolt/kubebolt/apps/api/cmd/mcp [no test files]
? github.com/kubebolt/kubebolt/apps/api/cmd/server [no test files]
ok github.com/kubebolt/kubebolt/apps/api/internal/agent 1.190s
ok github.com/kubebolt/kubebolt/apps/api/internal/agent/channel 2.134s
ok github.com/kubebolt/kubebolt/apps/api/internal/api 2.665s
ok github.com/kubebolt/kubebolt/apps/api/internal/audit 1.010s
ok github.com/kubebolt/kubebolt/apps/api/internal/auth 103.515s
ok github.com/kubebolt/kubebolt/apps/api/internal/cluster 1.226s
ok github.com/kubebolt/kubebolt/apps/api/internal/config 1.021s
ok github.com/kubebolt/kubebolt/apps/api/internal/copilot 1.213s
ok github.com/kubebolt/kubebolt/apps/api/internal/helm 1.053s
ok github.com/kubebolt/kubebolt/apps/api/internal/insights 1.044s
ok github.com/kubebolt/kubebolt/apps/api/internal/integrations 1.159s
? github.com/kubebolt/kubebolt/apps/api/internal/logging [no test files]
ok github.com/kubebolt/kubebolt/apps/api/internal/mcp 1.079s
? github.com/kubebolt/kubebolt/apps/api/internal/metrics [no test files]
? github.com/kubebolt/kubebolt/apps/api/internal/models [no test files]
ok github.com/kubebolt/kubebolt/apps/api/internal/notifications 1.016s
ok github.com/kubebolt/kubebolt/apps/api/internal/settings 1.116s
ok github.com/kubebolt/kubebolt/apps/api/internal/updatecheck 1.011s
ok github.com/kubebolt/kubebolt/apps/api/internal/usage 1.011s
ok github.com/kubebolt/kubebolt/apps/api/internal/websocket 1.260s
==> Web test (full suite, as CI runs it) ()
Other
- Merge pull request #174 from clm-cloud-solutions/develop ()
- chore(release): 1.23.1 — cross-organization metric read, and four fixes behind it ()
- Merge pull request #173 from clm-cloud-solutions/fix/cluster-map-external-scope ()
- Merge pull request #172 from clm-cloud-solutions/fix/settings-error-detail ()
- test(web): pin that an API error surfaces the reason, not the category ()
- Merge pull request #171 from clm-cloud-solutions/fix/kobi-fallback-provider ()
- Merge pull request #170 from clm-cloud-solutions/fix/cross-org-metrics-scope ()
- Merge pull request #169 from clm-cloud-solutions/fix/insights-lifecycle ()