GitHub

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_shadow and the shared library uu_shadow_core - shadow-rs and shadow-core were already claimed by unrelated crates. The installed binary and symlink names are unchanged (#205)
    • Workspace dependencies on shadow-core and the 14 tool crates now carry explicit versions, which cargo publish requires (#206)
  • Security

    • useradd created skeleton directories with mkdir() and only chmod'd them afterwards, leaving a brief window where a directory copied from /etc/skel could be world-writable. The mode is now set atomically at creation time (#157, #158)
    • cargo audit can finally run in CI: Cargo.lock is now committed, so the daily advisory workflow has a lockfile to scan (#167, #168)
  • Less unsafe, less dead code

    • One more unsafe block removed (#165) and an unreachable!() dropped from validate.rs (#156), continuing the workspace-wide unsafe_code = "deny" policy
    • Unused show_error/show_warning macros deleted from shadow-core (#182), and the clap-error boilerplate duplicated across all 14 tools folded into one helper (#181, #190)
  • Error-message fidelity

    • The "Permission denied" text is now sourced from the OS rather than hardcoded, so it matches GNU shadow-utils under non-English locales (#159, #171)
    • --version output identifies shadow-rs as part of the uutils project (#161, #162)
  • CI robustness

    • The Docker test matrix retries image builds instead of failing the whole run on a transient registry error (#172, #173, #174)
    • cargo-deny is installed as a pinned prebuilt binary, cutting image build time and removing a from-source compile (#175)
    • .pre-commit-config.yaml added (#164)
  • Dependencies

    • uucore upgraded from 0.8 to 0.9 (#179, #189), plus clap 4.6.5, clap_complete 4.6.8, landlock 0.4.7, libc 0.2.189, zeroize 1.9.0, anyhow 1.0.103 and a thiserror bump
  • 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

tools

shadow-core

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

Documentation

  • README.md: strip -rs from project name by @oech3 in #170

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 anyhow from 1.0.102 to 1.0.103 by @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 & adapt deny.toml by @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

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-rs to uutils/shadow-rs
  • uucore 0.8 — aligned with latest uutils ecosystem
  • nixrustix — full migration, raw syscalls without libc overhead
  • Standalone per-tool installmake install now 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 lookupgetpwuid_r for 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.

Read the original on github.com ↗