CVE-2026-35366
Description
The printenv utility in uutils coreutils 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 vulnerability allows malicious environment variables (e.g., adversarial LD_PRELOAD values) to evade inspection by administrators or security auditing tools, potentially allowing library injection or other environment-based attacks to go undetected.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
coreutilscrates.io | < 0.6.0 | 0.6.0 |
Affected products
2Patches
10bfbbc00c789Fix printenv non-UTF8 (#9728)
2 files changed · +46 −12
src/uu/printenv/src/printenv.rs+19 −12 modified@@ -3,10 +3,14 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. -use clap::{Arg, ArgAction, Command}; use std::env; -use uucore::translate; -use uucore::{error::UResult, format_usage}; +use std::io::Write; + +use clap::{Arg, ArgAction, Command}; + +use uucore::error::UResult; +use uucore::line_ending::LineEnding; +use uucore::{format_usage, os_str_as_bytes, translate}; static OPT_NULL: &str = "null"; @@ -21,15 +25,16 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { .map(|v| v.map(ToString::to_string).collect()) .unwrap_or_default(); - let separator = if matches.get_flag(OPT_NULL) { - "\x00" - } else { - "\n" - }; + let separator = LineEnding::from_zero_flag(matches.get_flag(OPT_NULL)); if variables.is_empty() { - for (env_var, value) in env::vars() { - print!("{env_var}={value}{separator}"); + for (env_var, value) in env::vars_os() { + let env_bytes = os_str_as_bytes(&env_var)?; + let val_bytes = os_str_as_bytes(&value)?; + std::io::stdout().lock().write_all(env_bytes)?; + print!("="); + std::io::stdout().lock().write_all(val_bytes)?; + print!("{separator}"); } return Ok(()); } @@ -41,8 +46,10 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { error_found = true; continue; } - if let Ok(var) = env::var(env_var) { - print!("{var}{separator}"); + if let Some(var) = env::var_os(env_var) { + let val_bytes = os_str_as_bytes(&var)?; + std::io::stdout().lock().write_all(val_bytes)?; + print!("{separator}"); } else { error_found = true; }
tests/by-util/test_printenv.rs+27 −0 modified@@ -90,3 +90,30 @@ fn test_null_separator() { .stdout_is("FOO\x00VALUE\x00"); } } + +#[test] +#[cfg(unix)] +#[cfg(not(any(target_os = "freebsd", target_os = "android", target_os = "openbsd")))] +fn test_non_utf8_value() { + use std::ffi::OsStr; + use std::os::unix::ffi::OsStrExt; + // Environment variable values can contain non-UTF-8 bytes on Unix. + // printenv should output them correctly, matching GNU behavior. + // Reproduces: LD_PRELOAD=$'/tmp/lib.so\xff' printenv LD_PRELOAD + let value_with_invalid_utf8 = OsStr::from_bytes(b"/tmp/lib.so\xff"); + + let result = new_ucmd!() + .env("LD_PRELOAD", value_with_invalid_utf8) + .arg("LD_PRELOAD") + .run(); + + // Use byte-based assertions to avoid UTF-8 conversion issues + // when the test framework tries to format error messages + assert!( + result.succeeded(), + "Command failed with exit code: {:?}, stderr: {:?}", + result.code(), + String::from_utf8_lossy(result.stderr()) + ); + result.stdout_is_bytes(b"/tmp/lib.so\xff\n"); +}
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6- github.com/uutils/coreutils/pull/9728nvdIssue TrackingPatchWEB
- github.com/uutils/coreutils/issues/9701nvdExploitIssue TrackingWEB
- github.com/advisories/GHSA-7259-cwhx-3xx3ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-35366ghsaADVISORY
- github.com/uutils/coreutils/commit/0bfbbc00c7895c0fb6ea94987b4aab99e3d7ee52ghsaWEB
- github.com/uutils/coreutils/releases/tag/0.6.0nvdRelease NotesWEB
News mentions
0No linked articles in our index yet.