Releases: kubescape/storage
Release v0.0.284
Summary
Fixes the Rancher cattle-agent tight retry loop reported in #318, which the mitigation in #321 could not resolve (confirmed by the reporter). Two independent server defects were found and fixed:
1. The WatchList=false feature-gate override was a silent no-op
ComponentGlobalsRegistry.Set() — the only bridge propagating the parsed feature-gates flag into utilfeature.DefaultMutableFeatureGate — ran before flags.Set("feature-gates", ...) populated the flag value, and was never re-invoked. The WatchList gate therefore silently stayed at its default (enabled), so the server accepted watch?sendInitialEvents=true requests (HTTP 200) it could never complete: the file-based storage has no Cacher and never emits the terminal initial-events-end BOOKMARK. This matches the reporter's awaiting required bookmark event for initial events stream log lines.
The calls are now reordered so the override is effective at request time. The apiserver then rejects sendInitialEvents watches pre-stream (HTTP 422), and WatchList-enabled clients (client-go ≥ v0.35 ships WatchListClient Beta default-on; Rancher uses v0.35.1) fall back gracefully to legacy list+watch.
Note:
ServerSideApplyis GA/non-gated in Kubernetes 1.35; #321'sServerSideApply=falsetoken was always inert and is removed to prevent a boot-timeunrecognized feature gateerror now that flag ordering is fixed. There is no SSA behavior change in this PR. A negative test guards against reintroducing stale gate tokens.
2. Pre-closed watch channels caused "very short watch" tight loops
watch.NewEmptyWatch() returns a pre-closed channel. A reflector reading it observes 0 events in <1s → VeryShortWatchError → immediate re-watch → tight loop, in both legacy and WatchList modes — which is why disabling WatchList alone could never fully fix #318. Two sites were affected:
- namespaced watch keys in
StorageImpl.Watch immutableStorage.Watch(ConfigurationScanSummary, VulnerabilitySummary, GeneratedNetworkPolicy)
Both now return idleWatch: a zero-goroutine watch.Interface that stays open and event-free until client disconnect or Stop() (closure driven by context.AfterFunc + sync.Once). Reflectors hold a quiet open connection instead of tight-looping. The real watchDispatcher path for cluster-scoped resources is untouched.
Scope
This does not implement WatchList/sendInitialEvents semantics (#320) for the resources served by the real watch dispatcher — they still never emit initial-events-end bookmarks. Correctness relies on the now-effective WatchList=false producing the pre-stream 422 so clients never enter that path.
Testing
- Regression test proving the gate is effective after
PersistentPreRunE(fails on pre-fix code) + boot-safety + unrecognized-token guard +skipcontract - 422 pre-stream assertion at the exact handler decision point (
ValidateListOptions) - Idle-watch tests: stays open with zero events, closes on ctx-cancel /
Stop()/ double-Stop()/ Stop-before-cancel; N=200 concurrent watches add ~0 goroutines (goleak-verified) - Full suite green (
make test— target added in this PR),go vetclean,-race -count=3clean - Pending before merge: kind-cluster smoke with a client-go v0.35 reflector / Rancher to confirm fallback behavior end-to-end (a test image will be posted on #318)
🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes
-
New Features
- Improved watch behavior with idle watch support to prevent tight retry loops.
- Enhanced feature-gate configuration handling.
-
Bug Fixes
- Watches now properly manage lifecycle and context cancellation.
-
Tests
- Added feature-gate validation and configuration tests.
- Added idle watch behavior and performance tests.
-
Chores
- Updated build configuration with test runner.
- Added testing dependency.
Release v0.0.283
Why
While debugging a customer's IPv6-only cluster (follow-up to #333), the storage pod was NotReady with MissingEndpoints and only 4 log lines — no clue why. Root cause turned out to be a Kubernetes 1.26 cluster (storage requires >= 1.28): the delegated-authentication informer never completes its cache sync against the older control plane, so /readyz is stuck at [-]informer-sync.
The reason it took so long to find: main.go unconditionally muted klog (the Kubernetes apiserver's own logger — serving, aggregation, informer-sync, post-start hooks) to Fatal, dropping the reflector error that would have named the cause immediately.
Changes
main.go— gate the klog level onKS_LOGGER_LEVEL. Atdebug, surface apiserver logs; otherwise keep the quietFataldefault (no behavior change unless opted in). The chart already plumbsKS_LOGGER_LEVELfromlogger.level.README.md— document the >= 1.28 requirement (with the exactinformer-sync/MissingEndpointsfailure signature), the IPv6serverBindAddressbehavior, and theKS_LOGGER_LEVEL=debugknob.
Testing
go build ./...andgo vet .pass.- Default behavior unchanged (klog stays
Fatal);KS_LOGGER_LEVEL=debugnow lets apiserver diagnostics through.
Related
- #333 (merged) — IPv6-only bind address + cert SAN.
- A companion PR on
kubescape/helm-chartsadds akubeVersion: ">=1.28.0-0"guard so 1.26 installs fail fast instead of silently wedging.
🤖 Generated with Claude Code
Summary by CodeRabbit
-
Documentation
- Added Requirements section specifying minimum Kubernetes version (1.28+)
- Added configuration guidance for IPv6-only and dual-stack cluster setups
- Documented informer cache sync behavior considerations for older Kubernetes versions
-
New Features
- Added debug-level logging support via KS_LOGGER_LEVEL=debug environment variable for improved troubleshooting
Release v0.0.282
Problem
The storage apiserver does not come up on IPv6-only clusters. Confirmed from a live pod: it listens on 0.0.0.0:8443 (the apiserver default), which cannot accept IPv6 connections.
Root cause: SecureServing.BindAddress is never set. The binary is config-driven, not flag-driven — main.go runs stdlib flag.Parse() with only -kubeconfig registered, so passing --bind-address to the process is rejected (flag provided but not defined: -bind-address). Configuration is the only available lever.
Change
- Add a
serverBindAddressconfig field (pkg/config/config.go) and wire it intoSecureServing.BindAddressinpkg/cmd/server/start.go, mirroring howserverBindPortis already handled. - Default
"::"so IPv6-only clusters serve with no Helm changes. Withbindv6only=0(the Linux default)"::"also accepts IPv4/dual-stack traffic, so existing clusters keep working. - Escape hatch: set
serverBindAddress: "0.0.0.0"to force IPv4-only binding. - Add
::1to the self-signed cert loopback SANs (start.go) for IPv6 loopback TLS on the self-signed path.
Testing
go build ./...passes.go test ./pkg/config/...passes (updatedTestLoadConfigexpectation for the new default).- Pending: maintainer/customer confirmation that the pod serves on a real IPv6-only cluster after deploy.
Notes
- The
serverBindAddressvalue flows through the existing config mount (/etc/config/config.json); the Helm chart can expose it but no chart change is required for the default to take effect. - Follow-ups (not in this PR): IPv6-correct NetworkPolicy CIDR (
/128) and IPv6-safe HTTPEndpoint URL parsing — data-correctness fixes tracked separately.
🤖 Generated with Claude Code
Summary by CodeRabbit
- New Features
- Added configurable server bind address setting with IPv6 default
- Enhanced self-signed certificate generation to support both IPv4 and IPv6 loopback addresses for improved compatibility
Release v0.0.281
…nnotation
Overview
ValidateStatusAnnotation is an allowlist that rejects any kubescape.io/status
value not in the known set. This adds the new unsupported-schema value so
objects carrying it pass validation instead of being rejected with "invalid value".
Context: kubevuln will write a stub VulnerabilityManifestSummary annotated
kubescape.io/status: unsupported-schema for images whose registry serves a
manifest schema the scanner can't read. While VulnerabilityManifestSummary
itself isn't currently routed through this validator, adding the value here keeps
the shared status vocabulary consistent and future-proofs any object type that
is validated by it.
Changes
pkg/utils/validations.go: addhelpers.UnsupportedSchemato the
ValidateStatusAnnotationswitch.pkg/utils/validations_test.go: add a "valid status - unsupported schema" case.
Related issues/PRs
Depends on kubescape/k8s-interface#155 (defines helpers.UnsupportedSchema).
Bump k8s-interface to the release that includes it, then drop the temporary
local replace before merge.
Part of: kubescape/kubevuln#369
Checklist
- Commits signed off (DCO)
- Builds and tests pass locally (against the k8s-interface change)
Release v0.0.280
Server-side aggregation of user-managed (ug-prefix) ApplicationProfile and
NetworkNeighborhood into the consolidated ContainerProfile during
consolidateKeyTimeSeries. Lets node-agent treat the CP as a single source
of truth and drop its per-tick ug- fetch.
- Merge math ported from node-agent's projection.go, operating on the
internal softwarecomposition types (no interface or storage method - Idempotent across ticks via kubescape.io/last-merged-ug-{ap,nn}-rv
annotation markers; merge skipped when ug- ResourceVersion is unchanged. - Re-consolidation trigger: option (c) (#315 discussion), relies on the existing 30s
ConsolidateTimeSeries cadence; no AP/NN watcher added (per @matthyx
guidance, memory cost of caching ug- objects rules out a watch path). - Deterministic ordering for DNSNames and MatchExpressions to keep
SyncChecksum stable across re-merges of unchanged content. - LabelSelector / PodSelector / NamespaceSelector MatchLabels: user value
wins on collision (utils.MergeMaps preserves base, so a local
overrideMerge is used here instead).
Refs #315, kubescape/node-agent#788
Known limitations (to discuss in PR review):
- Stale-on-edit/delete: merge is additive against the persisted CP, so
removing entries from a ug- CRD does not retract them from already-
merged consolidated CPs. The proper fix is a CRD shape change
(separate user-managed sub-spec, replaced wholesale) - Idle workloads: updateProfile early-returns when no new time-series
arrives, so ug- edits to Completed workloads do not propagate until
the next tick that has new data. Accepted trade-off for option (c).
worth a note: Changes were initially drafted using help from copilot, and manually reviewed and edited
Summary by CodeRabbit
-
New Features
- Produces per-container "merged" profiles by combining observed data with user-managed application and network overlays; registers merged-first REST reads and a separate merged storage variant.
-
Bug Fixes
- Avoids unnecessary observed writes when no new time-series data; skips processing when required identifiers are missing; retracts stale merged profiles when overlays are removed; refreshes merged state each tick without forcing observed saves.
-
Tests
- Added extensive unit and e2e tests covering merge correctness, idempotency, RV behavior, merged-first semantics, retraction, cleanup, and edge cases.
Release v0.0.278
exec-path: symlink-faithful argv[0] resolution
⚠️ Merge order
This PR depends on #323 and must be merged AFTER it.
PR #323 defines WildcardIdentifier (and the broader CollapseConfig / NewPathAnalyzerWithConfigs surface) in types.go and analyzer.go. Without it, compare_exec_args.go (this PR) fails to compile because WildcardIdentifier is undefined.
Correct merge order:
#323— path-wildcards: anchored trailing-*+ per-endpoint port + R0040 args#322(this PR) — allowing wildcards in exec args
Summary by CodeRabbit
-
New Features
- Enhanced command-line argument pattern matching: anchored wildcard and single-value dynamic tokens, plus a new "args required" option that changes empty-vs-anchored behavior and is exposed in the API schema.
-
Tests
- Expanded coverage for literal, dynamic, wildcard, mixed patterns, realistic argv forms, argv[0] semantics, ReDoS resistance, back-compat checks, and protobuf roundtrip/field-tag tests.
-
Chores
- API conversion mappings updated to carry the new flag.
Release v0.0.277
Release v0.0.276
Summary
Bumps vulnerable indirect dependencies identified in security advisory scan:
| Advisory | Package | From | To | Severity |
|---|---|---|---|---|
| GHSA-gj49-89wh-h4gj | github.com/cilium/cilium |
v1.17.14 | v1.17.15 | High |
| GO-2026-5025…5030 | golang.org/x/net |
v0.53.0 | v0.55.0 | Unknown |
| GO-2026-5024 | golang.org/x/sys |
v0.43.0 | v0.45.0* | Unknown |
| GO-2026-5005…5023, 5033 | golang.org/x/crypto |
v0.50.0 | v0.52.0 | Unknown |
* Advisory required v0.44.0; bumped to v0.45.0 because x/net@v0.55.0 and x/crypto@v0.52.0 both transitively require it.
Not yet addressed
- GHSA-x744-4wpc-v9h2 —
github.com/docker/dockerfix requires v29.3.1, which is not yet published to the Go module proxy. Will be addressed in a follow-up once available.
Test plan
-
make buildpasses - CI passes
🤖 Generated with Claude Code
Release v0.0.275
analyze_endpoints: per-endpoint port handling (Internal/External merge key now includes the port so endpoints exposing the same path on different ports stay distinct)analyze_opens: anchored trailing-*only matches when the wildcard is at the end of the pattern (no recursive-*accidents)analyzer:DefaultCollapseConfigsaccessor andFindConfigForPathvalue-return (used by node-agent's CEL helpers)
CompareDynamic perf note: the current implementation allocates two []string slices per call. matthyx's earlier review of PR #316 line 358 called this out and indicated he'd own a zero-alloc rewrite; remains untouched
Summary by CodeRabbit
-
Bug Fixes
- Wildcard-port merging now only folds matching endpoints and respects internal flags; header marshal failures no longer print to stdout; SBOM-listed paths are preserved during consolidation.
-
Performance
- Faster and lower-allocation path analysis via pooled buffers and optimized/memoized pattern matching.
-
New Features
- Per-prefix collapse/configuration and deterministic consolidation of open-paths/endpoints; exposed helpers for collapse inspection.
-
Tests
- Large suite of new regression, consolidation, memoization, benchmark and profiling tests.
Release v0.0.274
Summary by CodeRabbit
-
Bug Fixes
- Improved cleanup operations to properly handle pod-based workloads as cleanable resource types. Pods are now correctly processed during cleanup cycles, ensuring orphaned pod profiles are appropriately removed.
-
Tests
- Added tests validating pod cleanup behavior in standalone scenarios, confirming proper profile removal and retention across different workload configurations.