The module lifecycle stage: Generally available version

The module has requirements for installation

v1.3.1

Release date: 2026-11-02

The release fixes the vulnerabilities of the batch hooks binary in the module bundle.

Highlights

Changes in this release:

  • The module images and the module bundle contain no known vulnerabilities with an available fix.

Security updates

Security updates in this release:

  • The batch hooks binary of the module bundle uses golang.org/x/net v0.62.0, golang.org/x/crypto v0.58.0, github.com/klauspost/compress v1.19.2 and github.com/google/go-containerregistry v0.22.1. The update fixes CVE-2026-56855, CVE-2026-63209, CVE-2026-78659, CVE-2026-78660, CVE-2026-78661, CVE-2026-78662, CVE-2026-78663, CVE-2026-78669, CVE-2026-97032 and CVE-2026-97045, and removes github.com/docker/distribution affected by CVE-2026-85747.

v1.3.0

Release date: 2026-10-29

The release moves the module to the General Availability stage, adds a role model for its resources and an event on containers that exit with an error, and moves the gateway to Vector 0.58.0. Several changes need an action before the update, described in the Upgrade notes section.

Highlights

Changes in this release:

  • The module is at the General Availability stage in every edition.
  • Permissions on the module resources are granted through the roles of the security subsystem and the namespace roles, not only to a cluster SuperAdmin.
  • The K8S_CONTAINER_TERMINATED event reports a container that exits with a non-zero code while its Pod keeps running.
  • The gateway runs Vector 0.58.0, the version of the log-shipper agents.

New features

This release adds:

  • The built-in kube-audit shipper reports K8S_CONTAINER_TERMINATED (Low) when a container exits with a non-zero exit code while its Pod is not deleted: a process crash, an OOM kill, or a failed start, init containers and native sidecars included. The event carries the container name, image, reason, exit code, termination message, and restart count. The event needs a DKP basic audit policy that logs the Pod status updates of kubelet with the request body. The rule appears in DKP 1.77; without it, the event is not generated. A container stopped after a failed liveness probe is not reported. When a failed container of a Pod with restartPolicy: Never or OnFailure stays terminated while another container keeps running, the event repeats on every status update of the Pod, such as a readiness change.
  • A transform source path of a shipper can pick an array element by a condition: containerStatuses[?state.terminated].name reads the first element in which state.terminated is set, and containerStatuses[?state.terminated.exitCode!=0].name also compares the value with == or !=. Before, an array element could be read only by its index, which picked an arbitrary element when the array order did not follow the event.
  • The module ships its capabilities in the role model of DKP 1.78: d8:system-capability:security-events-manager:{view,edit,manage_shippers} and d8:namespace-capability:security-events-manager:{view,edit}. On a cluster below 1.78 it ships the previous d8:manage:permission:module:security-events-manager:* and d8:use:capability:module:security-events-manager:* objects instead, so one version of the module serves clusters on either side of the change.
  • The manager of the security subsystem writes ClusterSecurityEventConfig, SecurityEventDefinition, ClusterSecurityEventAlertRule, ClusterSecurityEventLoggingTransformationRules, ClusterSecurityEventEnrichmentPlugin and the security-events-manager ModuleConfig, and reads every cluster-scoped resource of the module. PodSecurityEventShipper and SecurityEventLoggingTransformationRules are granted in the namespace roles, because both are namespaced. SecurityEvent is granted nowhere: the kind is a reference schema for the event document and the API holds no instance of it.
  • The same permissions are available in the deprecated ClusterAuthorizationRule model, through the d8:user-authz:security-events-manager:* roles at the User, Editor, ClusterEditor and ClusterAdmin levels.

Improvements

This release improves:

  • The stage field of module.yaml is General Availability in every edition. Before, only the CSE edition shipped the module at this stage, and the other editions showed it as Experimental.
  • The gateway configuration compiles about eight times faster, which shortens vector validate in the controller and the reloader and the start of the gateway. On a test cluster with the built-in shippers, validation took about 31 seconds and now takes about 4. The generated VRL no longer checks the parent objects before each mapped field, and the gateway builds Vector with a VRL compiler that shares type information instead of copying it (vectordotdev/vrl#1895).
  • A security event no longer contains an empty object, such as "object": {}, when a shipper maps a field whose source value is missing. The parent object appears only together with a mapped value.
  • D8SecurityEventsManagerGatewayEventRegistryDrops (S4) also counts the events that the new enforce_required_fields transform drops. The gateway checks the required fields of a SecurityEventDefinition in that transform, after enforce_event_registry, and each transform logs at most one dropped line a minute. With Vector 0.58, the line about an event without a definition and the line about an event without a required field would otherwise suppress each other. The alert fires per transform: component_id names the check that drops events. Find the codes with d8 k -n d8-security-events-manager logs deploy/gateway -c vector --since=1h | grep -E "enforce_(event_registry|required_fields): dropped".
  • D8SecurityEventsManagerGatewayBufferHighUsage (S5) reads the buffer usage from vector_buffer_size_bytes and vector_buffer_max_size_bytes. Vector 0.58 no longer exports vector_buffer_byte_size, and the alert would not fire on it.

Fixes

This release fixes:

  • Right after a restart, the aggregator no longer evaluates only part of the ClusterSecurityEventAlertRule objects in its first pass, and the gateway enrichment no longer misses static-user names with k8s-nodeuser-info. Both components reported ready once their Kubernetes cache was filled, before their own lists and indexes had caught up with it.
  • The K8S_CLUSTER_ADMIN_BOUND event is raised only for a ClusterRoleBinding whose roleRef names the ClusterRole cluster-admin, and it carries the name of the binding in object.name. Before, the event was raised for almost every ClusterRoleBinding created by a cluster administrator, whatever role it bound: the rule matched cluster-admin in the authorization annotation of the audit event, which names the binding that allowed the request.
  • A PodSecurityEventShipper or ClusterSecurityEventShipper with a produces[] item that sets neither transform nor enrich no longer stops the gateway from applying its configuration. Such an item produced an empty block in the generated VRL, vector validate rejected the whole configuration, and the gateway kept running the previous one: no later change of any shipper, definition or destination took effect, and security_events_manager_gateway_config_validation_error stayed at 1. Any user allowed to create a PodSecurityEventShipper in a namespace could cause this. The controller now leaves such an item out of the mapping transform.
  • The gateway applies a Plugin enrichment rule only to the events of the shipper and the event code that declare it. Previously, each rule applied to the events of every shipper. For example, the rule of the operator-trivy shipper that fills actor.id from the pod ServiceAccount replaced the user in every dex-authenticator event with system:serviceaccount:<NAMESPACE>:default.
  • The events of the built-in shippers, such as kube-audit, keep reaching the gateway after the module is disabled and enabled again. Previously, the module issued a new mTLS certificate authority on enable, and the log-shipper agents kept connecting to the gateway with the old one until they were restarted by hand. The controller now restarts the agents a minute after the certificate authority changes.

Security updates

Security updates in this release:

  • The module images contain only the binaries of the module and the libraries they load. The base image no longer brings the BusyBox shell and utilities, rsync, locate and updatedb, and enrichment-cache no longer ships cat.
  • Module images are rebuilt with updated Go dependencies to remediate CVE-2026-78659, CVE-2026-78660, CVE-2026-78661, CVE-2026-78663, CVE-2026-78669, CVE-2026-97032 and CVE-2026-97045 in golang.org/x/net and CVE-2026-56851 in golang.org/x/text.
  • A regular expression or grok pattern of a shipper or of SecurityEventLoggingTransformationRules can no longer run as VRL in the gateway or stop it from applying its configuration. The gateway renders these patterns into remap programs shared by every source of the cluster. A pattern with a backslash before a quote closed the VRL regex literal, so the rest of it ran as VRL over all security events and could drop or rewrite the events of other namespaces; a pattern that did not compile failed vector validate, and the gateway stopped applying any change. A quote and an escaped backslash are now rendered as \x27 and \x5c, which mean the same to the regex engine and cannot close the literal. The admission webhook rejects a regular expression that does not compile or uses a construct Vector’s regex engine refuses (\Q...\E, a { that does not start a repetition), a grok reference not of the form %{NAME}, %{NAME:field} or %{NAME:field:type} or naming a pattern that is neither built in nor custom, a grok pattern with an unclosed group or character class and a malformed custom pattern key, in parser of PodSecurityEventShipper and ClusterSecurityEventShipper, in the Regex and NotRegex values of produces[].extract, and in SecurityEventLoggingTransformationRules and ClusterSecurityEventLoggingTransformationRules. Before it publishes the gateway configuration, the controller compiles every rendered pattern with the Vector the gateway ships. A pattern that fails the webhook check or this compilation is left out of the gateway configuration and the rest is published. The shipper gets the PatternsPublished condition with the status False, the reason PatternsLeftOut and the patterns in the message; the status is Unknown while Vector has not compiled every pattern of the shipper yet (PatternsNotVerified) or when the controller did not publish the configuration (GatewayConfigNotPublished). The shipper is also reported by D8SecurityEventsManagerProblematicClusterObject with the problem pattern_does_not_compile or unrenderable_extract. Writing SecurityEventLoggingTransformationRules is granted to the namespace manager by this release, which made the issue reachable from a namespace.
  • The capabilities of the module carry no rbac.deckhouse.io/namespace label, so none of them grants access inside d8-security-events-manager. That namespace holds the mTLS client certificate the log-shipper agent authenticates with, the Loki API token and the generated Vector configuration with the resolved credentials of every destination.
  • Writing a ClusterSecurityEventShipper or a ClusterSecurityEventDestination, and reading the sensitive fields of a destination, stay with the cluster administrator. Both are granted by a capability of their own, d8:system-capability:security-events-manager:manage_shippers, which the manager of the security subsystem does not hold. A shipper with input.type: File names node file paths that the log-shipper agent reads with its own privileges and forwards to the destination the same object names, and a destination names the Secret of d8-security-events-manager that is read as its credential, among those labeled as destination credentials.
  • An HTTP destination that declares an authentication credential but has no value for it no longer reaches the gateway configuration. Such a destination used to be rendered as an http sink with no Authorization header: a half-filled auth block is left out of the Vector configuration, so the security events were shipped to the endpoint unauthenticated. spec.http.auth is now checked the same way as the credentials of the loki, elasticsearch, splunkHEC and kafka destinations. While a field the strategy requires — spec.http.auth.token for Bearer, spec.http.auth.username and spec.http.auth.password for Basic — stays empty, the destination is left out of the gateway configuration and receives no events, the rest of the configuration is published, the DestinationsPublished condition of ClusterSecurityEventConfig is False with the reason DestinationCredentialMissing, and the D8SecurityEventsManagerDestinationCredentialMissing alert fires. A destination with spec.http.auth.strategy: None, or with no spec.http.auth at all, is published as before.
  • The roles of the module components carry only the calls the components make. The alert evaluator reads the bundled cluster-loki destination and the cluster-loki-token Secret by name instead of every destination and every Secret of d8-security-events-manager. The controller writes the main object of SecurityEventDefinition only and has no update or patch on the other resources of the module, and its leader-election rights are narrowed to its own Lease. In d8-log-shipper it updates only the d8-se-tls-log-shipper Secret.
  • The registration of ClusterSecurityEventEnrichmentPlugin with multitenancy-manager covers spec[].producesDefaults.enrich[].plugin of a PodSecurityEventShipper as well as spec[].produces[].enrich[].plugin. The controller reads the plugin name from both fields, so a ClusterResourceGrantPolicy that restricted the plugins of a project could be bypassed through producesDefaults.
  • A ClusterResourceGrantPolicy that withholds a SecurityEventDefinition from a project now takes effect. A PodSecurityEventShipper names a definition by its event code in spec[].produces[].eventCode, while multitenancy-manager compares a referenced value with object names, so a policy on SecurityEventDefinition never matched and a project could produce any event code. The registration of SecurityEventDefinition is now enforcement: External: the admission webhook of the module maps the event code to its definition and rejects a shipper whose definition is missing from the AvailableClusterResource securityeventdefinitions of its namespace. In a project namespace without that catalog, which DKP 1.77 deletes when the project may use no definition, every known event code is rejected. An event code a shipper already carries is not rechecked when the shipper is updated, and writes by deckhouse-controller, user-authz, kube-system controllers and system:masters are not checked, as in multitenancy-manager itself. The check covers only event codes that have a SecurityEventDefinition when the shipper is written: a code without one is accepted with a warning, and if an administrator later creates a definition for it that the project may not use, the existing shipper produces events with that code. Namespaces outside projects and clusters without multitenancy-manager are not affected.

Breaking changes

Changes that affect backward compatibility:

  • The admission webhook rejects a ClusterSecurityEventDestination whose spec.elasticsearch.index, spec.kafka.topic, spec.file.path, an endpoint or a value of spec.http.headers contains {{. Vector reads such a value as a template filled from each event, and since 0.57 it rejects a template with no literal prefix, such as {{ event.code }}. A destination created earlier with such a value stops the controller from publishing the gateway configuration: the gateway keeps the previous configuration, and D8SecurityEventsManagerControllerConfigNotPublished fires. Replace the template with a literal value.
  • Vector 0.58 no longer exports vector_buffer_byte_size and vector_buffer_events. Update your own dashboards and alerts on the gateway buffers to vector_buffer_size_bytes and vector_buffer_size_events.
  • A ClusterSecurityEventDestination may name in tokenSecretRef and passwordSecretRef only a Secret of d8-security-events-manager labeled security-events-manager.deckhouse.io/credential-secret: "true". Without this check, whoever may write a destination could name the Loki API token or another destination’s credential and have the gateway deliver it to an endpoint of their choosing. A reference to a Secret without the label, or to one that is missing, leaves that destination out of the gateway configuration, so it receives no events until the reference is fixed. Before, a missing Secret stopped publishing of the whole gateway configuration; now only the destination that names it is left out. The rest of the configuration is published, the DestinationsPublished condition of ClusterSecurityEventConfig is False with the reason DestinationCredentialMissing, and the D8SecurityEventsManagerDestinationCredentialMissing alert fires. Only the reference the authentication strategy reads is checked: tokenSecretRef for Bearer, passwordSecretRef for Basic, neither for None; the Kafka SASL password and the Splunk HEC token are always checked. The Secret shipped with the module carries the label already.
  • On Deckhouse 1.78 and newer, writing ClusterSecurityEventShipper and ClusterSecurityEventDestination and reading clustersecurityeventdestinations/sensitive are granted by d8:system-capability:security-events-manager:manage_shippers, which aggregates into d8:subsystem:security:superadmin and the system superadmin role only. Below 1.78 the same permissions are aggregated into d8:manage:all:manager. After the cluster is updated to 1.78, d8:manage:all:manager, which then aliases d8:system:manager, and d8:system:manager itself no longer grant them.
  • An HTTP destination with spec.http.auth.strategy: Bearer or Basic whose required credential is empty stops receiving events after the update. Before, it was published without an Authorization header and received the events unauthenticated; now it is left out of the gateway configuration, as described in security.

Upgrade notes

Before upgrading, note the following:

  • The module containers no longer have a shell, so d8 k exec ... -- sh fails with executable file not found. To inspect a running pod, attach an ephemeral debug container: d8 k -n d8-security-events-manager debug -it <POD_NAME> --image=<DEBUG_IMAGE> --target=<CONTAINER_NAME>.
  • Before the update, list the destinations that use a template: d8 k get clustersecurityeventdestinations -o json | jq -r '.items[] | select(.spec | tostring | contains("{{")) | .metadata.name'. Replace the template in each destination the command prints with a literal value.
  • Before updating, label every Secret your destinations reference. List them together with the label: d8 k get clustersecurityeventdestinations -o json | jq -r '[.items[].spec | .. | objects | (.tokenSecretRef?, .passwordSecretRef?) | .name? // empty] | unique | .[]' | xargs -r d8 k -n d8-security-events-manager get secret -L security-events-manager.deckhouse.io/credential-secret. Add security-events-manager.deckhouse.io/credential-secret=true to each Secret whose label column is empty.
  • Before updating Deckhouse to 1.78, bind d8:subsystem:security:superadmin (or a role that aggregates it) to whoever writes shippers and destinations through d8:manage:all:manager today.
  • Before updating, check the HTTP destinations: one that sets spec.http.auth.strategy to Bearer or Basic needs a non-empty token, or username and password, inline or through tokenSecretRef and passwordSecretRef. If the receiver needs no authentication, set spec.http.auth.strategy: None.

Known issues

Known limitations of this release:

  • The availability of a SecurityEventDefinition to a project is checked only when a PodSecurityEventShipper is created or changed. An event code with no definition at that moment is accepted with a warning, and a code the shipper already carries is not rechecked on update. If a definition for such a code is created later and the project may not use it, the shipper keeps producing events with that code until it is changed.

Docs

Documentation changes:

  • The diagnostics of the reloader and enrichment-cache in the advanced usage guide query their endpoints through kubectl port-forward instead of wget inside the container.

Dependencies

Dependency updates:

  • vector: 0.44.0 → 0.58.0

  • lua: 5.4.7 → 5.4.8

v1.2.2

Release date: 2026-10-13

The release restores the collection and delivery of security events broken since version 1.2.0, adds SecurityEvent fields to CEF messages, and adds an alert on shippers and definitions that are not Ready.

Highlights

Changes in this release:

  • A CEF destination can send any SecurityEvent field, for example the vulnerability counters of an image, as a CEF extension.
  • Clusters with the log-shipper built into Deckhouse or with the external log-shipper 1.1.0 collect security events from every source again.
  • Process and file events of runtime-audit-engine reach their destinations.
  • The gateway and the controller keep working through module updates and short API server outages.

New features

This release adds:

  • The encoding.cef.extensions parameter of ClusterSecurityEventDestination adds SecurityEvent fields to the extension part of CEF messages. Each item names the CEF key, the dot-separated path of the field, such as metadata.extra.critical, and, for the custom keys cs1–cs6, cn1–cn3 and the like, the label written as the <KEY>Label pair. The cluster-wide list is set in the securityEventConfig.cef.extensions module parameter, which fills spec.cef.extensions of the generated default ClusterSecurityEventConfig; a destination list replaces it as a whole. Without the parameter, a destination sends the base set of extensions only.
  • The D8SecurityEventsManagerResourceNotReady alert (S4) fires when a ClusterSecurityEventShipper, a PodSecurityEventShipper or a SecurityEventDefinition has not been Ready for 10 minutes. Until such a resource is Ready, the events of its sources may not be collected or delivered. For a shipper waiting for its ClusterLogDestination, the status of the resource was the only place that reported it. The security_events_manager_controller_resource_ready metric exports the Ready condition of each of these resources. The D8SecurityEventsManagerResourceReadinessUnknown alert (S4) fires when the controller cannot read resources of one of these kinds for 15 minutes, because the first alert cannot fire for them then.

Improvements

This release improves:

  • CEF messages carry the event identifier in externalId and the object of the event in cs1 (object.name), cs2 (object.type) and cs3 (object.namespace). Before, the image of a vulnerability event or the name of a changed resource reached a SIEM only with the JSON codec.
  • The security_events_manager_controller_log_shipper_drop_event_supported metric is 1 when log-shipper filters the lines of a source on the node and 0 when the whole source reaches the gateway, and the Ready condition of such a SecurityEventDefinition says so in its message.

Fixes

This release fixes:

  • Since version 1.2.0 every SecurityEventDefinition stayed in ReconcileFailed with the message that spec.transformations[0].action of ClusterLogDestination does not support DropEvent. This happened with the log-shipper built into Deckhouse and with the external log-shipper 1.1.0: neither has the transformation, and both satisfy the log-shipper >= 1.0.6 requirement. Shippers waited in WaitingForDestination, and no source the module had not collected before the update was collected. The controller now writes the destination without DropEvent when log-shipper lacks it, and rewrites every destination within five minutes after an update of log-shipper adds or removes it. Without the transformation the lines of a source reach the gateway unfiltered, and the gateway drops the ones no rule selects.
  • The gateway dropped security events with the message enforce_event_registry: dropped <CODE> from <SOURCE>: required field <FIELD> is missing when the event lacked a field its SecurityEventDefinition marks as optional. When the controller first processed a definition, every field in spec.fields became required: true. This affected any definition: those of the runtime-audit-engine module, of the module itself, and the ones created by hand. Most runtime-audit-engine events about processes and files carry no actor.id, so they did not reach the destinations. The controller now leaves spec.fields of a definition as it is.
  • The gateway is ready only when Vector accepts events on its source port. Before, a gateway pod became ready while it still validated its first configuration and ran the default one without the source.
  • New gateway pods start when no destination has a custom CA. Before, they stayed in ContainerCreating after the controller deleted the gateway-destination-cas Secret.
  • The controller is ready only when its admission webhook serves, waits 5 seconds before it stops, and hands the leader lease over on a graceful stop. Creating or updating objects of the module no longer fails during an update of the module. With one controller replica, the default, a restart or an eviction of the controller pod still rejects these writes until the new pod is ready.
  • A controller started while the API server is unavailable waits for it for up to 10 minutes instead of being restarted by its liveness probe into CrashLoopBackOff.
  • The controller keeps its leader lease through API server delays of up to 40 seconds. Before, a delay of more than 10 seconds stopped the controller and its admission webhook, and writes of objects of the module failed until it restarted. After an abnormal exit of the controller, such as an OOM kill or a lost node, the new controller pod reconciles objects of the module after the old lease expires, that is up to 60 seconds later instead of 15; its admission webhook serves without this wait.

Breaking changes

Changes that affect backward compatibility:

  • CEF messages no longer contain the act extension, which repeated the suser value, and no longer contain extensions with an empty value, such as outcome= for an event without an outcome. The component, the node and the cluster moved from src, dvc and dvchost to dproc, dvchost and deviceExternalId: in the CEF dictionary src and dvc hold IPv4 addresses, and strict parsers dropped the names written there. Before updating, switch the SIEM parsing rules that read the actor from act to suser, and the rules that read these three fields to the new keys. The keys cs1–cs3 are now taken by the object of the event: when a rule already expects other data in them, set encoding.cef.extensions with these keys to keep that data.

Upgrade notes

Before upgrading, note the following:

  • The update does not repair definitions already changed by the controller. Check spec.fields of your definitions: a definition is affected when all its fields are required: true while its manifest marks some of them required: false. Apply the original manifest of a definition you created again, for example with kubectl apply. The definitions of the module itself are restored by the update. The definitions of another module, such as runtime-audit-engine, are restored the next time Deckhouse applies the release of that module, for example after a change of its ModuleConfig settings.

v1.2.1

Release date: 2026-10-01

The release fixes the time at which the D8SecurityEventAlertFiring alert of ClusterSecurityEventAlertRule rules resolves.

Highlights

Changes in this release:

  • A short-lived security event keeps the alert of a ClusterSecurityEventAlertRule rule in the list of cluster alerts long enough to be noticed.

Fixes

This release fixes:

  • The D8SecurityEventAlertFiring alert again resolves five minutes after a ClusterSecurityEventAlertRule rule last fired. Starting from version 1.1.4, the alert resolved as soon as the event left the time window of the rule query: for a rule with a one-minute window, in about two minutes. A group that matches again within these five minutes keeps firing without waiting for for again.

v1.2.0

Release date: 2026-09-28

The release reduces the log collection load on nodes, drops security events that fail the event registry check, and restricts the module schemas and permissions. The module requires Deckhouse 1.76 and log-shipper 1.0.6 or later.

Highlights

Changes in this release:

  • Each log source is read once per node regardless of the number of event codes.
  • Events that fail the event registry check are dropped, and the enrichment plugins fill their target fields.
  • The module custom resources and configuration are bounded by the schema, the component permissions are narrowed, and destination fields that can contain secrets are hidden from users without access to them.
  • A cluster-wide shipper collects pod logs from the namespaces it specifies, and a namespace selector can include and exclude namespaces at the same time.
  • A destination that sends events in the CEF format can specify the format version in the header prefix.

New features

This release adds:

  • The D8SecurityEventsManagerAgentDeliveryStalled alert fires when a log-shipper agent has undelivered security events and has not delivered any of them to the gateway for 10 minutes. Previously, such a delay triggered no alert, and the gateway pods remained Ready. The alert specifies the node and the sink.
  • The input.kubernetesPods.namespaceSelector parameter accepts matchNames and excludeNames together: the exclusion is applied after the inclusion. Previously, only one of the lists could be specified.
  • The encoding.cef.version parameter of ClusterSecurityEventDestination sets the CEF format version: V0 writes the CEF:0 prefix and is used by default, V1 writes CEF:1. The header fields and extensions do not change. The parameter is available for the Kafka, Vector, File, Console, and Socket destinations.
  • The spec.cef.version parameter of ClusterSecurityEventConfig sets the CEF format version for the whole cluster. The encoding.cef.version parameter of a destination overrides it.
  • In DKP 1.78 and later, with the multitenancy-manager module enabled, SecurityEventDefinition and ClusterSecurityEventEnrichmentPlugin are registered as grantable cluster resources. By default, both resources are available to all projects. To restrict access to them, use ClusterResourceGrantPolicy.

Improvements

This release improves:

  • Collection configs and destinations are created per shipper item instead of per event code. Previously, a log source with 50 event codes was read 50 times on every node and required a separate disk buffer for each code, up to about 20 GiB per node. Events are still filtered on the node.
  • All destinations use one TLS Secret in the d8-log-shipper namespace instead of a copy per event code.
  • The gateway determines the event code by the same extract rules as the agent. A log line that matches several event codes produces an event for each of them.
  • If a shipper item contains a rule that cannot be converted into a node filter, the logs of the item are sent to the gateway unfiltered and are processed there. This prevents events from being dropped on the node.
  • Collection configs and destinations created by earlier versions of the module are removed after the new ones are ready.

Fixes

This release fixes:

  • Connections of log-shipper agents to the gateway no longer fail with the SSL alert number 80 error. The error occurred on about every second reconnection and delayed the delivery of events.
  • The k8s-pod-info, k8s-container-info, and k8s-nodeuser-info enrichment plugins fill the target field again. Starting from version 1.0.2, the plugins left the field empty, and the gateway log contained the cjson unavailable error: actor.id, object.name, and object.namespace of events from external modules and static user names were not set. If the JSON library fails to load, the gateway log now contains the reason.
  • Setting one encoding.cef parameter in ClusterSecurityEventDestination no longer sets the other parameters to built-in values. Previously, deviceVendor, deviceProduct, and deviceVersion received default values and overrode spec.cef of ClusterSecurityEventConfig.
  • If several SecurityEventDefinition objects declare the same event code and source, the gateway uses the definition with the alphabetically first name. Previously, the severity, category, and description of such events could change between reconciliations. The other definitions are reported by the gateway_config_problematic_cluster_objects metric with the duplicate_code_source problem.
  • The gateway configuration no longer changes between reconciliations when the cluster has several ClusterSecurityEventConfig objects. Previously, the order of route conditions and the source of the CEF header defaults depended on the order of objects in the API cache, which caused unnecessary gateway reloads and could change the vendor, product, and version in the CEF header.
  • The order of parsing rules in the gateway no longer changes between reconciliations. Previously, when two rules covered the same pods or two shippers declared the same source and event code, the applied parser or transform could change.
  • The cluster-loki destination is created only when the kube-rbac-proxy CA is available. Previously, the destination could be created without a CA, and all events sent to Loki were lost.
  • parser rules are applied to a shipper that selects pods by input.kubernetesPods.labelSelector.matchExpressions. Previously, the logs of such a shipper were collected but not parsed, and the fields set in transform remained empty.
  • A shipper with a pod selector that contains only NotIn and DoesNotExist requirements covers pods without labels, as Kubernetes and log-shipper do. Previously, the logs of such pods were collected but not parsed.
  • A ClusterSecurityEventShipper with input.type: KubernetesPods and namespaces specified in input.kubernetesPods.namespace or input.kubernetesPods.namespaceSelector.matchNames collects events from these namespaces. Previously, such a shipper remained in the ReconcileFailed state and collected no events.
  • The controller no longer logs the failed to remove finalizer during SED cleanup and failed to update success status errors when two reconciliations process the same SecurityEventDefinition at the same time. These errors did not affect the result of the reconciliation.
  • The gateway.logShipperBuffer.maxEvents parameter is applied. Previously, it was ignored, and a buffer of the Memory type used the log-shipper default.
  • TLS Secrets created in d8-log-shipper by earlier versions of the module are removed when no destination references them. When a SecurityEventDefinition is deleted, its destination is removed before the Secrets it references. Previously, a reference to a deleted Secret could break the log-shipper configuration for all modules in the cluster.
  • Changing or removing a shipper item or deleting a shipper removes the related ClusterLogDestination. Previously, such objects remained in the cluster, were processed by every log-shipper agent, and prevented the shared TLS Secret from being removed.
  • A shipper with a source that has no SecurityEventDefinition no longer blocks the removal of its other objects. Previously, items removed from such a shipper kept their collection configs and continued to collect logs.
  • The gateway drops events that fail the event registry check. Previously, with the default Low severity threshold, events without a matching SecurityEventDefinition or without a required field reached the storage without a severity, category, and description, and severity-based filters and dashboards did not show them. The D8SecurityEventsManagerGatewayEventRegistryDrops alert fires on such drops.

Security updates

Security updates in this release:

  • Destination fields that can contain secrets are marked with x-kubernetes-sensitive-data: true: the authentication token and password of the http, loki, and elasticsearch destinations, the Kafka SASL password, the Splunk HEC token, and the spec.http.headers values. In Deckhouse 1.76 and later, these fields are removed from get, list, and watch responses for users without access to the clustersecurityeventdestinations/sensitive subresource and are masked in the audit log. In Deckhouse 1.77 and later, they are also masked in create, update, and patch responses. The values are stored in etcd unencrypted unless controlPlaneManager.encryptionEnabled is enabled, so use the tokenSecretRef and passwordSecretRef fields instead.
  • The bundled cluster-loki destination verifies the certificate and the host name of Loki. Previously, in Deckhouse versions earlier than 1.76, the verification was disabled, which allowed Loki to be impersonated from the cluster network.
  • All user-settable fields of the module custom resources and configuration have explicit limits: maxLength for strings, maxItems for arrays, maxProperties for maps, and minimum and maximum for numbers.
  • SecurityEventDefinition.spec.code and produces[].eventCode of both shipper types must match the ^[A-Z0-9_]+$ format. Previously, objects with other codes were accepted and ignored. Such objects are now rejected on creation and on a spec change.
  • The controller ClusterRole no longer grants cluster-wide access to secrets and events. Access to Secrets is limited to the module namespace and d8-log-shipper, and write access in the module namespace is limited to gateway-vector-config and gateway-destination-cas. The controller no longer changes Secrets owned by users.
  • The gateway reloader and the enrichment-cache sidecar serve metrics only on loopback addresses: 127.0.0.1:9256 and 127.0.0.1:9261. Ports 9255 and 9260, which are reachable from the cluster network, serve only health probes. Prometheus collects the metrics through kube-rbac-proxy.
  • The controller Service no longer publishes port 8081 of the health probes.
  • RBAC objects are renamed to include the component name: d8:security-events-manager:controller:rbac-proxy, d8:security-events-manager:aggregator:rbac-proxy, d8:security-events-manager:gateway:rbac-proxy, d8:security-events-manager:gateway:pod-reader, and d8:security-events-manager:controller:log-shipper-secrets for the Role and RoleBinding in d8-log-shipper.

Breaking changes

Changes that affect backward compatibility:

  • The module requires log-shipper 1.0.6 or later.
  • The minimum supported Deckhouse version is 1.76. The module is not installed on earlier versions.
  • A namespace name in input.kubernetesPods.namespaceSelector and input.kubernetesPods.namespace must be a valid DNS-1123 label. Previously, invalid names were accepted and broke log collection for the entire shipper.
  • input.kubernetesPods.labelSelector.matchLabels cannot be empty. Previously, an empty matchLabels was accepted, and logs were collected from all namespaces without producing events.
  • A requirement in input.kubernetesPods.labelSelector.matchExpressions must have a non-empty key, must have values for the In and NotIn operators, and must not have values for the Exists and DoesNotExist operators. Previously, such requirements were accepted, and the shipper remained in the ReconcileFailed state.
  • The module configuration is bounded by the schema: replicas has minimum and maximum values, and CPU and memory values must use the plain or suffixed Kubernetes quantity format. The exponential format, for example 128e6, is rejected. A ModuleConfig that does not match the schema blocks the module update.
  • SecurityEventDefinition.spec.metadata accepts only docs.desc.{en,ru} and tests.{executionTarget,testability,trigger.commands,trigger.cleanupCommands}. Other keys are removed on the next write of the object.

Upgrade notes

Before upgrading, note the following:

  • Update Deckhouse to 1.76 or later before updating the module.
  • Update log-shipper to 1.0.6 or later before updating the module. With an earlier log-shipper version, the module keeps the previous collection scheme.
  • Before updating, check the ModuleConfig, your SecurityEventDefinition objects with other keys in spec.metadata, and custom resources with long regular expressions, Grok patterns, field paths, or HTTP header values against the new schemas. The bundled destination and event definitions match the new schemas.
  • Before updating, check shippers for namespace names and matchExpressions requirements that the new schema rejects. Existing objects with such values are not deleted, but any change to them is rejected until the values are corrected.
  • Find SecurityEventDefinition objects and shippers with event codes that do not match ^[A-Z0-9_]+$. They are ignored, and any change to their spec is rejected.
  • To read inline destination credentials, grant get, list, or watch access to the clustersecurityeventdestinations/sensitive subresource. The module controller and the d8:security-events-manager:admin-kubeconfig role already have this access.
  • Add the security-events-manager.deckhouse.io/credential-secret label to manually created Secrets with credentials of alert rule destinations. The controller no longer adds this label. The Secret bundled with the module already has it.
  • To make destinations created before the update follow spec.cef of ClusterSecurityEventConfig, remove deviceVendor, deviceProduct, and deviceVersion from their encoding.cef. The values written by earlier versions remain in the objects.
  • After the update, expect a one-time duplication of events from the collected log files: each file is read again from the beginning of its current rotation.
  • After the update, events that fail the event registry check do not reach the storage. If the D8SecurityEventsManagerGatewayEventRegistryDrops alert fires, find the dropped event code by the enforce_event_registry: dropped line in the log of the vector container of the gateway, and make sure that the source fills the fields that the SecurityEventDefinition lists as required.

Docs

Documentation changes:

  • The examples page contains a ClusterSecurityEventShipper that collects pod logs from specified namespaces, including matchNames and excludeNames used together.
  • The SecurityEventLoggingTransformationRules example is placed in the d8-runtime-audit-engine namespace, where the shipper that references it runs. The page also states that spec.selector of these rules is not used to select pods.
  • The k8s-pod-info examples use @root.pod and @root.namespace for the pod name and namespace. The previous examples used fields that events do not contain.
  • The Falco examples select pods by the app: runtime-audit-engine label in the d8-runtime-audit-engine namespace. The previous examples used a label that module pods do not have.
  • The path syntax of transform[].value and enrich[].args[].value is described, including brackets and quotes for keys that contain a dot. The Falco examples are corrected accordingly.

v1.1.5

Release date: 2026-09-07

Security updates for the alert-evaluator, controller, and go-hooks images: dependency upgrades remediate known vulnerabilities, and OpenVEX attestations mark unused golang.org/x/crypto packages as not affected.

Highlights

Changes in this release:

  • The alert-evaluator, controller, and go-hooks images include updated golang.org/x libraries that remediate High and Critical vulnerabilities found in recent image scans.
  • OpenVEX attestations for the controller and module bundle mark vulnerabilities in golang.org/x/crypto/ssh and golang.org/x/crypto/openpgp as not affected, because those packages are not used.

Security updates

Security updates in this release:

  • In the alert-evaluator image, golang.org/x/net is updated to v0.56.0, golang.org/x/text to v0.39.0, and golang.org/x/sys to v0.46.0. The update remediates related CVEs, including CVE-2025-47911, CVE-2025-58190, CVE-2026-25680, CVE-2026-25681, CVE-2026-27136, CVE-2026-33814, CVE-2026-39821, CVE-2026-39824, CVE-2026-42502, CVE-2026-42506, CVE-2026-46600, and CVE-2026-56852.
  • In the controller and go-hooks images, golang.org/x/crypto is updated to v0.55.0. The update remediates Critical CVE-2026-56854.
  • OpenVEX statements for the controller and module bundle mark CVE-2026-56855, CVE-2026-78662, and GO-2026-5932 as not_affected with the vulnerable_code_not_in_execute_path justification. The controller uses golang.org/x/crypto for bcrypt, scrypt, and pbkdf2 through sprig; go-hooks uses it for ocsp and pkcs12 through cfssl. Neither component imports golang.org/x/crypto/ssh or golang.org/x/crypto/openpgp.

v1.1.4

Release date: 2026-09-03

Alert rules are now LogQL, evaluated directly against Loki: ClusterSecurityEventAlertRule is reshaped after PrometheusRule (groups of rules with alert/expr/for/labels/annotations), and the alerting pipeline no longer runs through Vector.

Highlights

Changes in this release:

  • ClusterSecurityEventAlertRule is now shaped like PrometheusRule: spec.groups[].rules[], each rule with alert, for, severityLevel, labels and annotations, and either a hand-written LogQL expr or a structured match/aggregation block (event codes, sources, categories, actors, grouping, threshold) that compiles into the equivalent LogQL. This is a breaking change to the resource spec — rewrite existing rules before upgrading.
  • Every rule declares its form in the required mode field (Expr or Match), matching the block it sets. The platform web interface uses mode to show only the fields for the selected form.
  • A new alert-evaluator component, running inside the existing aggregator Deployment, evaluates each rule’s LogQL query against the cluster’s Loki on a schedule and reports firing rules through the same security_events_alert_last_firing_timestamp_seconds metric as before. The D8SecurityEventAlertFiring alert is unchanged.
  • gateway no longer forwards a copy of matching events to aggregator over the network: alert-evaluator reads directly from Loki. aggregator’s TLS material and Vector process are no longer needed.
  • Alert rules require the cluster-loki ClusterSecurityEventDestination to be enabled — without it, LogQL has no data to query.

Improvements

This release improves:

  • A rule can now look arbitrarily far back and group by any label LogQL supports, not only the eight fixed fields the previous aggregation.groupBy enum offered. Use a hand-written expr for that.
  • Each ClusterSecurityEventAlertRule reports its own status.conditions (Ready/Degraded, with a reason such as LogQLQueryError, LokiDestinationMissing or CardinalityLimitExceeded).

Breaking changes

Changes that affect backward compatibility:

  • Every rule in ClusterSecurityEventAlertRule.spec.groups[].rules[] must declare mode: Expr or mode: Match, matching the block it sets (expr or match). A rule without mode, or with a mode that disagrees with its block, is rejected.
  • The old spec.match/spec.aggregation/spec.alert fields (one rule per object) are removed. Rewrite each rule under spec.groups[].rules[], using either a hand-written LogQL expr or the same match/aggregation fields as before (eventCodes, sources, categories, severityMin, actorType, actors, excludeActors, excludeSystemActors, groupBy, threshold, window), now nested per rule. See the module documentation for examples.
  • The API server now enforces field constraints on ClusterSecurityEventShipper, PodSecurityEventShipper, ClusterSecurityEventLogTransformation, SecurityEventLogTransformation, SecurityEventDefinition, ClusterSecurityEventEnrichmentPlugin and ClusterSecurityEventDestination that were previously silent. An empty label selector (labelSelector: {} / selector: {}) is now rejected instead of matching everything, ClusterSecurityEventDestination’s spec.*.buffer.maxEvents must be at least 100, and several free-text fields no longer accept an empty string.
  • Alert rule evaluation requires the cluster-loki ClusterSecurityEventDestination (enable it via securityEventConfig.destinations). Without it, every ClusterSecurityEventAlertRule is reported Degraded and no rule is evaluated; event collection and delivery to other destinations are unaffected.

Upgrade notes

Before upgrading, note the following:

  • When rewriting a rule, add mode: Expr to a rule with a hand-written expr, or mode: Match to a rule built from match/aggregation.
  • Before upgrading, save every existing ClusterSecurityEventAlertRule (d8 k get clustersecurityeventalertrule -o yaml). After upgrading, rewrite each rule under the new spec.groups[].rules[] shape — the old top-level spec fields are rejected by the updated CRD schema.
  • Before upgrading, check whether existing resources violate the newly enforced constraints: run d8 k get clustersecurityeventshipper,podsecurityeventshipper,clustersecurityeventlogtransformation,securityeventlogtransformation,clustersecurityeventdestination -o yaml and look for an empty labelSelector/selector or buffer.maxEvents below 100. An existing object that violates a constraint keeps working, but the next write to it is rejected.
  • Confirm cluster-loki is enabled (securityEventsManager.securityEventConfig.destinations includes cluster-loki) before relying on alert rules; otherwise every rule stays Degraded.

Known issues

Known limitations of this release:

  • Evaluation state (pending/firing) lives in the evaluator process’s memory: restarting it resets the for countdown for every rule.
  • Grouping by a LogQL label with unbounded cardinality is capped at 500 distinct label sets per rule; the rest are dropped and the rule is reported CardinalityLimitExceeded, but it keeps firing for the groups it already tracks.

Docs

Documentation changes:

  • The alerting section of the examples page is rewritten for the PrometheusRule-shaped resource, covering both the expr and match/aggregation forms, including the line filter that reproduces the old excludeSystemActors behavior.

v1.1.3

Release date: 2026-08-27

Security fixes for module images: OpenVEX attestations mark golang.org/x/crypto GO-2026-5932 as not affected for the controller and module bundle hooks.

Highlights

Changes in this release:

  • Module images publish OpenVEX attestations so CVE scans suppress GO-2026-5932 where openpgp is not on the execute path.

Security updates

Security updates in this release:

  • Added OpenVEX statements for GO-2026-5932 (golang.org/x/crypto/openpgp) on the controller and module bundle (go-hooks), status not_affected / vulnerable_code_not_in_execute_path.
  • Wired cosign OpenVEX attestation into the module build so CI CVE scans read the statements from the OCI registry.

v1.1.2

Release date: 2026-08-27

Alerting on security events: the new ClusterSecurityEventAlertRule resource counts matching events per key over a time window and raises an ordinary Prometheus alert once the threshold is reached. Adds an Http destination type for webhooks and HTTP collectors, and a new event for containerd integrity violations.

Highlights

Changes in this release:

  • New ClusterSecurityEventAlertRule resource: describe which events to watch, how to count them, and what the alert should say.
  • A firing rule raises the Prometheus alert D8SecurityEventAlertFiring, so it becomes a ClusterAlert object, shows up in the console next to every other alert, keeps its history and travels through the cluster’s existing alert delivery. There is nothing to configure for delivery.
  • New Http destination type sends security events to any HTTP endpoint — a webhook or an HTTP collector — with authentication, TLS, custom headers and a choice of body framing.
  • New security event D8_CONTAINERD_INTEGRITY_VIOLATION reports a containerd integrity check failure — most often an image refused at pull because its signature did not verify.

New features

This release adds:

  • ClusterSecurityEventAlertRule (cluster-scoped, short name csear). spec.match selects events by event code, minimum severity, category, source component, actor and actor type; spec.aggregation groups them by groupBy and fires as soon as a group reaches threshold within window; spec.alert carries the summary, description, extra labels and the DKP severityLevel. A rule without aggregation alerts on every matched event.
  • match.excludeSystemActors (enabled by default) keeps platform identities out of a rule, using the same list as the “Exclude system” filter of the console. Routine cluster work dominates the event stream — on an idle cluster the DKP ServiceAccount alone produced 2617 of 2812 secret reads in an hour — so without it the first rule anyone writes is an alert about the platform. match.excludeActors and match.actors take globs against actor.id for anything the built-in list does not cover.
  • The alert resolves on its own about five minutes after the rule last fired. There is no field to set: the aggregator publishes security_events_alert_last_firing_timestamp_seconds, the moment a rule last fired, and D8SecurityEventAlertFiring tests the age of it. The metric is exported on the aggregator’s /alert-metrics/metrics endpoint and can be used in dashboards.
  • New destination type Http: spec.http.endpoint with optional auth, tls and headers, and framing — JSONArray (default) for receivers that expect one document per request, NewlineDelimited for collectors that read NDJSON. The number of delivery attempts for one batch is bounded, so a receiver that keeps rejecting a request it will never accept cannot hold up everything queued behind it: once the attempts run out the batch is dropped into the sink’s error metrics, which the module already alerts on.
  • New security event D8_CONTAINERD_INTEGRITY_VIOLATION (category Runtime, severity High, source containerd-integrity). It fires when containerd refuses an image whose signature does not verify, and when a file checksum on the node does not match the expected one. object.name carries the image reference, object.namespace the namespace it was being pulled into, and metadata.extra the message, the file path and the expected and actual hashes where the event provides them. Collected only on nodes running cri ContainerdV2 in the CSE edition; probe traffic from d8-upmeter is filtered out.
  • kube-audit events now carry actor.sourceIP, the originating client address taken from the head of the request chain, next to the full actor.sourceIPs chain. Alert rules can group by it (ActorSourceIP), which is how a rule about unauthorized requests identifies the client when there is no identity to group on.
  • The module runs a new single-replica alert-aggregator component that holds the counters, with its own alert D8SecurityEventsManagerAggregatorNotAvailable. While it is down, event collection and delivery continue — events wait in the gateway buffer — but counting windows restart, so a partially reached threshold begins from zero.

Improvements

This release improves:

  • Transform source paths can address array elements, for example sourceIPs[0]. Previously every path segment was treated as a map key, so any array field in a log was unmappable.
  • Module documentation, CRDs and OpenAPI schemas are now included in the bundle and release images.

Upgrade notes

Before upgrading, note the following:

  • No configuration change is required. The alerting components are created on upgrade and stay idle until the first ClusterSecurityEventAlertRule exists. The alert-aggregator runs a single replica with a Recreate rollout by design — counters live in one process — so its updates and node drains produce a short gap in counting.

Known issues

Known limitations of this release:

  • A rule can only match what the cluster’s audit policy records. The default DKP policy logs list of secrets but not a get of one secret by name, and drops most requests from system:authenticated, so a rule on K8S_SECRET_ACCESSED will not see d8 k get secret <name>. Check the audit policy before concluding that a rule does not work.
  • Counters live in the aggregator’s memory. Restarting it starts every window from zero.
  • Grouping by a value with unbounded cardinality is capped: past 500 distinct values for a label the tag is dropped and the alert still fires, one dimension poorer.
  • On clusters with update.blockOnAlerts enabled in the deckhouse module, an alert at or below the configured level (4 by default) blocks DKP releases from being applied while it is firing. The severityLevel default of 6 stays out of the way; lower it deliberately.

Docs

Documentation changes:

  • The examples page gained an alerting section with a rule per detection story: repeated exec into pods by one actor, a burst of RBAC edits grouped per actor and namespace, unauthorized requests grouped by client address, and a containerd integrity violation as the case where a single occurrence is enough. It also gained an HTTP destination example.

v1.0.5

Release date: 2026-08-24

Security fixes for module images: updated Go dependencies in batch hooks and related components to remediate known CVEs.

Highlights

Changes in this release:

  • Module images include dependency updates that address known CVEs in Go components.

Security updates

Security updates in this release:

  • Bumped golang.org/x/net and golang.org/x/text in hooks/batch and related Go images for CVE remediation.
  • CVE-oriented security fixes included in the component images.

v1.0.4

Release date: 2026-08-18

Fixes an upgrade deadlock: the controller could not publish gateway configs and the gateway Deployment could not roll out.

Highlights

Changes in this release:

  • The controller can publish the gateway Vector config again — its own validation step could never complete on real clusters.
  • The gateway Deployment now rolls out on clusters with as many system nodes as replicas, instead of stalling on a Pending pod.
  • A destination whose credential cannot be resolved no longer takes the whole gateway config down with it.
  • Gateway reloader metrics are renamed to stop colliding with log-shipper’s.

Improvements

This release improves:

  • New controller.vectorValidateTimeout parameter (default 60s) for the vector validate run the controller performs before publishing a gateway config.
  • New alerts: D8SecurityEventsManagerControllerConfigNotPublished, D8SecurityEventsManagerDestinationCredentialMissing and D8SecurityEventsManagerControllerValidateUnavailable. Previously the controller could stop publishing configs indefinitely without any alert firing.

Fixes

This release fixes:

  • The controller no longer freezes the published gateway config. Its vector validate step ran with a 10s timeout in a 64Mi container and was either killed by the deadline or OOM-killed, and the failure was treated as a verdict that the config was invalid, so the Secret stayed at its last revision permanently. Validation now runs with --no-environment (~2s instead of ~5s on a 256 KB config, no topology build and no network healthchecks), the container floor is 192Mi, the timeout default is 60s, and a check that cannot be executed no longer blocks publishing — the gateway reloader validates the config regardless.
  • The gateway Deployment now uses maxSurge: 0 / maxUnavailable: 1. With the default surge, updating a 2-replica gateway asked for a third pod, and the required host anti-affinity meant that pod stayed Pending forever on a cluster with two system nodes: the module reported itself Deployed while still running the previous image.
  • A ClusterSecurityEventDestination that declares a credential the controller cannot resolve now blocks publishing and reports the exact destination and field, instead of emitting an auth block without its token. Vector rejects such a block outright, which made the whole gateway config fail to load and stopped delivery to every destination, not just the affected one. Covers Loki, Elasticsearch, Splunk HEC and Kafka SASL.
  • auth.strategy: None, the CRD default, no longer reaches the generated config as {"strategy": "none"}, which Vector does not accept.
  • The controller Deployment now has a system node selector; it previously had none and could be scheduled onto worker nodes.
  • The CI Vector validation test now validates the defaults.json the gateway image actually ships instead of a hand-written stand-in.

Breaking changes

Changes that affect backward compatibility:

  • Gateway reloader metrics are renamed with a security_events_manager_gateway_ prefix: vector_config_validation_error, vector_config_apply_failures_total, vector_config_periodic_retry_attempts_total, vector_config_reloads_success_total, vector_config_last_reload_success_timestamp_seconds, reloader_validate_duration_seconds, reloader_validate_timeout_seconds, reloader_apply_duration_seconds, reloader_vector_restarts_total, reloader_fsnotify_events_total. The old names collided with log-shipper’s vector-reloader, whose alerting rules do not filter by namespace, so this module’s config problems fired D8LogShipperConfigInvalid. Module rules, dashboards and docs are updated; custom recording rules, alerts and panels built on the old names need updating.
  • The CONTROLLER_VECTOR_VALIDATE_SKIP_ABOVE_BYTES environment variable is removed. Its 256 KiB threshold sat just above the real config size, so it was liable to skip validation by accident rather than by intent; the new fail-open behaviour covers the case it was meant to.
  • The default minimalSeverity changed from Medium to Low in v1.0.3 without a release note. Clusters upgrading from v1.0.0 or earlier ship substantially more events than before, which interacts with the disk buffer defaults also introduced in v1.0.3. Set it explicitly if the previous volume is wanted.

Upgrade notes

Before upgrading, note the following:

  • The controller container memory floor rises from 64Mi to 192Mi (VPA ceiling from 256Mi to 512Mi). This is what vector validate needs to run at all; below it the container is OOM-killed mid-validation.

v1.0.3

Release date: 2026-08-17

Gateway buffer configuration, enrichment plugins, SecretRefs for destinations, CEF/Socket sinks, and security hardening for the Vector gateway and controller RBAC.

Highlights

Changes in this release:

  • Configurable Disk buffers for gateway and log-shipper layers, with per-destination overrides.
  • Enrichment plugins (k8s-pod-info, k8s-container-info, k8s-nodeuser-info) via ClusterSecurityEventEnrichmentPlugin.
  • Credentials for destinations can use SecretRefs instead of plaintext in the CR.
  • CEF encoding and Socket destinations for SIEM integration.
  • Gateway API bound to loopback; tighter Secret RBAC and SSRF checks on enrichment endpoints.

New features

This release adds:

  • Configurable buffer settings: gateway.buffer and gateway.logShipperBuffer in module values; per-destination override via spec.buffer in ClusterSecurityEventDestination; default Disk + Block; maxSize requires a Kubernetes quantity with a unit suffix (for example 512Mi).
  • Event K8S_ADMISSION_POLICY_DENIED for admission-policy-engine denials in the Kubernetes audit log.
  • CRD ClusterSecurityEventEnrichmentPlugin for built-in Internal enrichment plugins served by the enrichment-cache sidecar (External plugins are in the schema but not wired yet).
  • Enrichment plugins k8s-pod-info, k8s-container-info, and k8s-nodeuser-info.
  • tokenSecretRef and passwordSecretRef on ClusterSecurityEventDestination for Loki, Elasticsearch, Kafka SASL, and Splunk HEC; built-in cluster-loki stores its token in a Secret.
  • CEF encoding for Kafka, Vector, File, and Console destinations (encoding.codec: CEF), optional syslog wrapping, and default CEF metadata via spec.cef / module values.
  • Socket destination type (TCP/UDP/Unix) for CEF-over-syslog to SIEM systems.

Fixes

This release fixes:

  • Fixed the D8SecurityEventsManagerControllerReconcileErrorsHigh alert.
  • gateway.reloaderValidateTimeout configures the Vector validate timeout (default 120s) so large gateway configs do not fail with a silent timeout.
  • TLS Secrets in d8-log-shipper are cleaned up when the related SecurityEventDefinition is deleted.
  • Credential Secret resolution failures are logged at warning with field path context.
  • Credential Secret watcher uses label security-events-manager.deckhouse.io/credential-secret: true instead of watching all Secrets.
  • Reloader SaveTo() writes the Vector config with mode 0600.
  • resolveDestinationSecretRefs() returns a deep copy so credentials stay fresh after Secret rotation.
  • Lua extractJSON returns nil and logs when cjson is unavailable (no fragile regex fallback).
  • Corrected the enrichment-cache port comment (9260 → 9261).
  • E2E triggers for K8S_CLUSTERROLEBINDING_DELETED and K8S_CONFIGMAP_MODIFIED create the test namespace and guard CRB delete against 404 races.
  • Controller-created Secrets and log-shipper CRs include the heritage: deckhouse label.

Security updates

Security updates in this release:

  • Fixed CVEs in module images.
  • Vector gateway API listens on 127.0.0.1:8686 only; port 8686 removed from the Service.
  • mTLS client private key is stored in a Secret in d8-log-shipper, not embedded in ClusterLogDestination.
  • Controller Secret RBAC limited to d8-security-events-manager and d8-log-shipper.
  • CEL blocks SSRF on ClusterSecurityEventEnrichmentPlugin spec.endpoint.url.
  • gateway-vector-config Secret annotated with security.deckhouse.io/contains-credentials: true.

Breaking changes

Changes that affect backward compatibility:

  • Shipper enrich shape: plugin is a free-form string; args is an ordered {key,value} array; plugin names use hyphens (k8s-pod-info). Old CRs with the previous shape fail to parse; Plugin enrichment was not functional before.
  • spec.splunkHEC.token is optional when tokenSecretRef is set.
  • CEL enforces mutual exclusivity of inline token/password and their *SecretRef counterparts on ClusterSecurityEventDestination.

v1.0.0

Release date: 2026-06-26

Initial release of the security-events-manager module.

Highlights

Changes in this release:

  • First public release of the module.