Jul 29, 2026·7 min read·2 visits
Authenticated users with Flow or ClusterFlow creation rights can inject newlines into Logging Operator Custom Resources, enabling downstream Fluentd configuration manipulation and arbitrary command execution.
A critical security flaw (CVE-2026-54680) in the Kubernetes Logging Operator allows authenticated attackers with namespace-level access to craft malicious Custom Resources that inject arbitrary configuration directives into the downstream Fluentd logging aggregator, resulting in unauthenticated remote code execution (RCE) in the context of the aggregator pod.
The Kubernetes Logging Operator manages log collection pipelines by dynamically orchestrating Fluentd and Fluentbit instances. The central component of this operator is responsible for compiling high-level declarative Custom Resources (CRDs), such as Flow and ClusterFlow, into raw, functional configurations loaded by downstream collectors. Because of the nature of logging pipelines, the operator acts as a translation layer, processing configuration parameters from user-defined YAML declarations and organizing them into structured configuration files.
The critical attack surface is situated in how the operator processes user-controlled parameter values within the configuration renderer. Specifically, the component tasked with creating the fluent.conf file allows unvalidated strings to flow from Kubernetes API objects to the final plaintext configuration structure. If these parameters are not properly structured, they expose the parsing engine of the downstream Fluentd log aggregator.
This exposure manifests as a structural injection vulnerability, tracked as CWE-74 and CWE-77. Attackers with permission to modify or create Flow objects can manipulate the structure of the generated configuration file. Because the downstream Fluentd component possesses highly privileged plugin capabilities—such as executing external processes to transport or manipulate log messages—gaining control over its configuration is equivalent to achieving remote code execution inside the collector pod.
The core defect exists within the Fluentd configuration renderer FluentRender defined in the file pkg/sdk/logging/model/render/fluent.go. This rendering engine is responsible for writing structured key-value pairs representing custom filters, record transformers, and output destinations to the destination configuration stream. The engine relies on the indentedf helper function to format nested blocks, splitting incoming multi-line parameters by newline boundaries to maintain clean indentation.
Because the renderer handles input strings directly, it assumes that any newline character (\n or \r) represents an intended formatting decision rather than a malicious escape sequence. If an operator-defined CRD includes a parameter populated with arbitrary newline characters, the indentedf function outputs these raw boundaries directly into the final fluent.conf stream. This behavior breaks the configuration out of the expected nested block context.
An attacker can construct a payload that effectively terminates the active configuration block, closes the parent directives like <record> or <filter>, and injects top-level blocks. This direct block escape allows the registration of arbitrary Fluentd input, filter, or output plugins. By utilizing Fluentd's built-in @type exec plugin, an attacker can designate command-line tools to be executed upon the arrival of log streams, completing the path to system command execution.
The vulnerability lies in the lack of character validation and escaping during the translation from the Go structures representing Custom Resources to the raw configuration file.
Below is a logical flow representation of how the untrusted CRD input bypasses validation and alters the configuration structure.
Prior to the patch, indentedf processed strings using standard, unescaped formatting mechanisms:
// VULNERABLE RENDERER MECHANISM (fluent.go)
func (f *FluentRender) indentedf(indent int, format string, values ...interface{}) {
indentString := strings.Repeat(" ", indent)
in := fmt.Sprintf(format, values...)
// Raw string splitting without verifying whether 'line' breaks context boundaries
for _, line := range strings.Split(in, "\n") {
if line != "" {
fmt.Fprint(f.Out, indentString+line+"\n")
}
}
}To remediate this, the maintainers implemented two mechanisms in commit cf437d7f1e056c78740bf5716ac8bdebcf002425. The first is structural token validation to prevent newlines in directive structures. The second is an escaping and quoting wrapper for raw values:
// PATCHED SANITIZATION ENGINE
var fluentEscaper = strings.NewReplacer(
`\`, `\\`,
`"`, `\"`,
"\n", `\n`,
"\r", `\r`,
"\t", `\t`,
`#`, `\#`, // Escaping '#' neutralizes Ruby string interpolation
)
func escapeFluentValue(value string) string {
if !strings.ContainsAny(value, "\n\r") {
return value // Safe; no escape required
}
// Wrap with quotes and escape special characters
return `"` + fluentEscaper.Replace(value) + `"`
}The addition of the # character to the escaping list is a critical security measure. Fluentd evaluates double-quoted strings and supports embedded Ruby interpolation syntaxes like #{system('id')}. By escaping the # symbol into \#, the patch prevents attackers from bypassing the newline constraints to execute code via internal language evaluations.
To exploit this vulnerability, an attacker requires access permissions sufficient to create, modify, or patch Flow or ClusterFlow resources within a Kubernetes namespace managed by the Logging Operator. Because these resource actions are typical for developers managing their service logging configurations, this requirement matches a low-privilege threshold (PR:L).
The attacker initiates the exploit by defining a custom Flow and targeting the record_transformer filter plugin. The payload uses carriage returns and newlines to break out of the configuration scope. Below is an example representation of the malicious Custom Resource containing the injection payload:
apiVersion: logging.banzaicloud.io/v1beta1
kind: Flow
metadata:
name: malicious-flow
namespace: default
spec:
filters:
- record_transformer:
records:
- inject_key: "safe_value\n</record>\n</filter>\n<match **>\n @type exec\n command id > /tmp/rce_output\n</match>"
globalOutputRefs:
- default-outputWhen the operator picks up this resource, it dynamically constructs the fluent.conf file. The output engine interprets the literal newlines as structural block endings, closing the <filter> declaration prematurly and creating an independent <match> block using the command execution plugin @type exec. The downstream Fluentd container parses the config file successfully, identifies the new configuration, and executes the designated command as soon as any log enters the system.
Successful exploitation of CVE-2026-54680 results in full command execution in the context of the running Fluentd aggregator pod. By default, the aggregator container executes with permissions and system mount scopes defined in the Kubernetes Deployment spec. In many default configurations, this container runs with substantial cluster access or contains credentials enabling communication with internal cluster resources.
An attacker operating within the Fluentd container can read and manipulate all log messages entering the pipeline, presenting a complete compromise of confidential business data and system logs. Sensitive fields—such as authentication tokens, passwords, and API keys leaked in log messages—can be extracted by the attacker. In addition, the attacker can use the container as a pivot point to perform network reconnaissance or execute attacks against the Kubernetes API.
The CVSS v3.1 score is evaluated at 9.9 (Critical), reflecting the low barrier to entry for users who already possess basic namespace permissions. The changed scope (Scope: Changed) highlights that the attack breaks out of the custom resource declaration context and executes commands inside the real operating system space of the host container. This can lead to service disruptions or manipulation of downstream log auditing solutions.
The primary remediation path requires upgrading the Logging Operator deployment to version 6.6.0 or later. This release incorporates the validation and escaping safeguards to neutralize any embedded newline characters and prevent configuration syntax hijacking.
For environments where an immediate operator update cannot be scheduled, administrators can implement defensive admission policies. Utilizing engines such as OPA Gatekeeper or Kyverno, teams can validate Custom Resources during the admission phase. The following Kyverno cluster policy blocks incoming resources containing potential injection syntax:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: block-fluentd-injection
spec:
validationFailureAction: Enforce
background: true
rules:
- name: block-newlines-in-records
match:
any:
- resources:
kinds:
- logging.banzaicloud.io/v1beta1/Flow
- logging.banzaicloud.io/v1beta1/ClusterFlow
validate:
message: "Carriage returns or newline characters are not permitted inside Flow records configurations to prevent command injection."
pattern:
spec:
filters:
- =(record_transformer):
records:
- inject_key: "!*[\n\r]*"Additionally, organizations should audit existing Flow, ClusterFlow, Output, and ClusterOutput Custom Resources for unexpected line feeds or structural escape patterns. Ensuring that Fluentd aggregator containers run as non-root users, utilizing read-only root filesystems, and removing access to the local service account token if unused will limit the post-exploitation capabilities of an attacker.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
Logging Operator Kube-Logging | < 6.6.0 | 6.6.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-74, CWE-77 |
| Attack Vector | Network |
| CVSS Score | 9.9 (Critical) |
| Exploit Status | PoC Available |
| Scope | Changed |
| Privileges Required | Low |
| Impact | Remote Code Execution (RCE) |
A container isolation bypass vulnerability exists in proot-distro prior to version 5.1.6. The utility accepted hardlink entries pointing outside the container directory being restored, allowing cross-container file read and write capabilities.
A protection mechanism failure in the netfoil DNS proxy prior to version 0.4.0 causes blocked domains to resolve to null IP addresses (0.0.0.0 or ::) with a NOERROR status instead of NXDOMAIN. On Linux systems, connections to these addresses are routed to the loopback interface (localhost), allowing local processes to intercept sensitive HTTP traffic, including authorization headers and session cookies, intended for the blocked domains.
A directory traversal vulnerability exists in the `activerecord-tenanted` Ruby gem's local storage path resolution logic. Prior to version 0.7.0, the `path_for` method failed to sanitize input keys, allowing remote attackers to traverse directories and access arbitrary files on the host filesystem.
An uncontrolled resource consumption vulnerability in the OpenTelemetry Javaagent RMI context propagation mechanism allows remote unauthenticated attackers to cause a Denial of Service (DoS) via heap memory exhaustion.
A sensitive data exposure vulnerability (CWE-532) exists in OpenTelemetry Java Instrumentation prior to version 2.28.0. The JDBC auto-instrumentation component's SQL statement sanitizer contains lexer flaws that prevent the correct redaction of administrative passwords under specific conditions, such as when double-quotes represent identifiers or during multi-statement executions separated by semicolons.
CVE-2026-54705 is a critical DOM-based Cross-Site Scripting (XSS) vulnerability affecting the MathLive library prior to version 0.110.0. The flaw stems from a lack of proper character escaping in the rendering path for LaTeX text-mode commands such as \text{} and \mbox{}, enabling unauthenticated attackers to execute arbitrary JavaScript in the victim's browser.