Description
When Robusta creates a default finding for Kubernetes change events, it uses the aggregation key GenericChange but does not populate the finding subject.
Because sink routing uses finding.subject.namespace, these notifications may end up with namespace == "None" in the scope/grouping layer and can be sent to the wrong sink.
This is especially visible when users configure Slack sinks with routing rules like:
- one sink for namespace: production
- another sink that explicitly includes namespace: "None"
In that setup, a Kubernetes resource that actually belongs to production may still be routed to the "None" sink if the finding was created through the default GenericChange path.
Actual Behavior
A Kubernetes change notification is sent with:
- aggregation_key = GenericChange
- namespace = None
- missing or undefined grouped labels such as app=(undefined)
As a result, sink scope matching may route the notification incorrectly.
Expected Behavior
Default findings created for Kubernetes change events should preserve the Kubernetes subject metadata, including:
- subject.name
- subject.namespace
- subject.labels
- subject.annotations
- source = KUBERNETES_API_SERVER
This ensures sink routing and Slack grouping use the actual resource namespace instead of "None".
Root Cause
K8sBaseChangeEvent.create_default_finding() creates a Finding with only:
- title
- aggregation_key = "GenericChange"
but without:
- subject=self.get_subject()
- source=self.get_source()
Later, routing relies on finding.attribute_map["namespace"], which is derived from finding.subject.namespace. Since the subject is missing, namespace becomes "None".
Proposed Fix
Update the default finding creation for Kubernetes change events to include the event subject and source.
Suggested change:
return Finding(
title=title,
aggregation_key="GenericChange",
subject=self.get_subject(),
source=self.get_source(),
)
Impact
This bug can cause:
- incorrect sink routing
- incorrect Slack grouping by namespace
- confusing summaries showing namespace: None
- alerts from production workloads appearing in fallback or infra channels
Reproduction Idea
Configure two Slack sinks:
- one with scope.include: namespace: production
- one with scope.include: namespace: "None"
Trigger a Kubernetes change event that goes through the default GenericChange path.
Observe that the notification may be routed to the "None" sink even though the resource actually belongs to production.
Description
When Robusta creates a default finding for Kubernetes change events, it uses the aggregation key GenericChange but does not populate the finding subject.
Because sink routing uses finding.subject.namespace, these notifications may end up with namespace == "None" in the scope/grouping layer and can be sent to the wrong sink.
This is especially visible when users configure Slack sinks with routing rules like:
In that setup, a Kubernetes resource that actually belongs to production may still be routed to the "None" sink if the finding was created through the default GenericChange path.
Actual Behavior
A Kubernetes change notification is sent with:
As a result, sink scope matching may route the notification incorrectly.
Expected Behavior
Default findings created for Kubernetes change events should preserve the Kubernetes subject metadata, including:
This ensures sink routing and Slack grouping use the actual resource namespace instead of "None".
Root Cause
K8sBaseChangeEvent.create_default_finding() creates a Finding with only:
but without:
Later, routing relies on finding.attribute_map["namespace"], which is derived from finding.subject.namespace. Since the subject is missing, namespace becomes "None".
Proposed Fix
Update the default finding creation for Kubernetes change events to include the event subject and source.
Suggested change:
Impact
This bug can cause:
Reproduction Idea
Configure two Slack sinks:
Trigger a Kubernetes change event that goes through the default GenericChange path.
Observe that the notification may be routed to the "None" sink even though the resource actually belongs to production.