v0.2.1
Rust shadow-utils 0.2.1 Release:
We are excited to announce the release of Rust shadow-utils 0.2.1 - the first release published on crates.io. Getting there meant renaming the published packages to uu_shadow and uu_shadow_core (both plain names were already taken) and pinning versions on every workspace dependency so the 15 crates (uu_passwd, uu_useradd, …, plus shadow-core) actually publish. Alongside packaging, this cycle closed a world-writable window in useradd's skel handling, removed another unsafe block and an unreachable!(), and made the CI matrix resilient to registry flakes.
Highlights:
-
First crates.io release
- The root package is now
uu_shadowand the shared libraryuu_shadow_core-shadow-rsandshadow-corewere already claimed by unrelated crates. The installed binary and symlink names are unchanged (#205) - Workspace dependencies on
shadow-coreand the 14 tool crates now carry explicit versions, whichcargo publishrequires (#206)
- The root package is now
-
Security
useraddcreated skeleton directories withmkdir()and only chmod'd them afterwards, leaving a brief window where a directory copied from/etc/skelcould be world-writable. The mode is now set atomically at creation time (#157, #158)cargo auditcan finally run in CI:Cargo.lockis now committed, so the daily advisory workflow has a lockfile to scan (#167, #168)
-
Less
unsafe, less dead code- One more
unsafeblock removed (#165) and anunreachable!()dropped fromvalidate.rs(#156), continuing the workspace-wideunsafe_code = "deny"policy - Unused
show_error/show_warningmacros deleted fromshadow-core(#182), and the clap-error boilerplate duplicated across all 14 tools folded into one helper (#181, #190)
- One more
-
Error-message fidelity
-
CI robustness
-
Dependencies
-
Contributions: This release was made possible by 3 new contributors joining our community
Call to Action:
Install it - cargo install uu_shadow
Report issues and contribute - github.com/uutils/shadow
Sponsor us on GitHub to accelerate development: github.com/sponsors/uutils
What's Changed
useradd
- useradd, skel: set mkdir mode atomically to close world-writable window (#157) by @pierre-warnier in #158
tools
- cli: identify shadow-rs as part of uutils (#161) by @pierre-warnier in #162
- tools: source the "Permission denied" message from the OS (#159) by @pierre-warnier in #171
shadow-core
- validate.rs: remove unreachable!() by @oech3 in #156
- remove 1 unsafe by @oech3 in #165
- shadow-core: remove unused show_error and show_warning macros by @shakilathasneem9 in #182
- shadow-core, tools: de-duplicate the clap-error boilerplate (#181) by @pierre-warnier in #190
Packaging
- cargo: rename package to uu_shadow. shadow-rs is already used by @sylvestre in #205
- fix: add version to shadow-core workspace dependencies for cargo publish by @sylvestre in #206
CI & Build
- ci: add
.pre-commit-config.yamlby @cakebaker in #164 - ci: commit Cargo.lock so cargo audit can run (#167) by @pierre-warnier in #168
- chore: gitignore AI review artifacts under docs/ by @pierre-warnier in #169
- ci: make the Docker test matrix resilient to registry flakes (#172) by @pierre-warnier in #173
- ci: polish the image-build retry loop by @pierre-warnier in #174
- docker: install cargo-deny as a pinned prebuilt binary by @pierre-warnier in #175
Documentation
Dependency Updates
- chore(deps): update debian docker tag to trixie-20260518 by @renovate[bot] in #163
- chore(deps): update debian docker tag to trixie-20260610 by @renovate[bot] in #176
- chore(deps): update rust crate zeroize to v1.9.0 by @renovate[bot] in #177
- chore(deps): update actions/checkout action to v7 by @renovate[bot] in #183
- chore(deps): update debian docker tag to trixie-20260623 by @renovate[bot] in #184
- Bump
anyhowfrom1.0.102to1.0.103by @cakebaker in #186 - chore(deps): update rust crate clap_complete to v4.6.6 by @renovate[bot] in #187
- chore(deps): update rust crate clap_complete to v4.6.7 by @renovate[bot] in #188
- deps: bump uucore from 0.8 to 0.9 (#179) by @pierre-warnier in #189
- chore(deps): update debian docker tag to trixie-20260713 by @renovate[bot] in #191
- chore(deps): update rust crate clap to v4.6.2 by @renovate[bot] in #192
- Bump
thiserror& adaptdeny.tomlby @cakebaker in #194 - chore(deps): update rust crate clap to v4.6.3 by @renovate[bot] in #195
- chore(deps): update rust crate libc to v0.2.187 by @renovate[bot] in #196
- chore(deps): update rust crate libc to v0.2.188 by @renovate[bot] in #197
- chore(deps): update rust crate libc to v0.2.189 by @renovate[bot] in #199
- chore(deps): update rust crate landlock to v0.4.6 by @renovate[bot] in #200
- deps: update clap to 4.6.4 (with syn 3.0.3) by @pierre-warnier in #201
- chore(deps): update rust crate clap_complete to v4.6.8 by @renovate[bot] in #202
- chore(deps): update rust crate landlock to v0.4.7 by @renovate[bot] in #203
- chore(deps): update rust crate clap to v4.6.5 by @renovate[bot] in #204
New Contributors
- @cakebaker made their first contribution in #164
- @shakilathasneem9 made their first contribution in #182
- @sylvestre made their first contribution in #206
Full Changelog: v0.2.0...v0.2.1
v0.2.0 — uutils adoption
First release under the uutils organization.
Highlights
- Repo transferred from
shadow-utils-rs/shadow-rstouutils/shadow-rs - uucore 0.8 — aligned with latest uutils ecosystem
nix→rustix— full migration, raw syscalls without libc overhead- Standalone per-tool install —
make installnow installs 14 individual binaries with least-privilege setuid layout matching GNU shadow-utils (#138) - Non-panicking I/O — all
println!/eprintln!replaced with graceful writes (#141) - Unwind tables suppressed — no binary layout leakage from setuid-root tools (#143)
- NSS-backed user lookup —
getpwuid_rfor LDAP/SSSD/systemd-homed compatibility (#147) - 35+ security findings addressed across 6 review rounds (Copilot + Gemini)
Full changelog
See CHANGELOG.md for the complete list.
v0.1.0 — First Release
shadow-rs v0.1.0
Memory-safe Rust reimplementation of all 14 Linux shadow-utils tools. Drop-in replacement for GNU shadow-utils.
Tools
passwd useradd userdel usermod groupadd groupdel groupmod pwck grpck chage chpasswd chfn chsh newgrp
Highlights
- Single multicall binary — 894 KB stripped, 4x faster than GNU
- 562 tests — unit, integration (all 14 tools), property-based, 4 fuzz targets
- Zero unsafe code outside FFI —
unsafe_code = "deny"enforced at workspace level - Security hardened — atomic file writes, password zeroing (zeroize), core dump suppression, env sanitization, audit logging, SELinux support
- 3-distro CI — Debian (glibc), Alpine (musl), Fedora (SELinux)
- Packaging — Makefile with setuid, Debian
.deb, Fedora.rpm - MIT license — GPL clean-room development, no GPL source referenced
- Reviewed — GitHub Copilot (automated) + Google Gemini CLI (manual security audit)
Install
# From source cargo build --release sudo make install # Docker test docker compose run --rm debian cargo test --workspace
What's next
- v0.2.0: Shell completions (
clap_complete), Landlock filesystem restriction - Future: uutils ecosystem integration (Path A)
See CHANGELOG.md for full details.