{"id":51416966,"url":"https://github.com/uutils/shadow","last_synced_at":"2026-07-04T20:01:31.397Z","repository":{"id":346336625,"uuid":"1189419978","full_name":"uutils/shadow","owner":"uutils","description":"Memory-safe Rust reimplementation of Linux shadow-utils (useradd, passwd, groupadd, etc.)","archived":false,"fork":false,"pushed_at":"2026-07-01T05:04:00.000Z","size":676,"stargazers_count":7,"open_issues_count":8,"forks_count":4,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-07-01T07:06:39.859Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/uutils.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-23T09:56:40.000Z","updated_at":"2026-07-01T05:03:42.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/uutils/shadow","commit_stats":null,"previous_names":["shadow-utils-rs/shadow-rs","uutils/shadow-rs","uutils/shadow"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/uutils/shadow","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uutils%2Fshadow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uutils%2Fshadow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uutils%2Fshadow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uutils%2Fshadow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/uutils","download_url":"https://codeload.github.com/uutils/shadow/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/uutils%2Fshadow/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35133834,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-04T02:00:05.987Z","response_time":113,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-04T20:01:30.625Z","updated_at":"2026-07-04T20:01:31.338Z","avatar_url":"https://github.com/uutils.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!-- spell-checker:ignore reimplementation setuid nscd subuid subgid gshadow --\u003e\n\u003cdiv align=\"center\"\u003e\n\n# shadow\n\n[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/uutils/shadow/blob/main/LICENSE)\n[![CI](https://github.com/uutils/shadow/actions/workflows/ci.yml/badge.svg)](https://github.com/uutils/shadow/actions/workflows/ci.yml)\n[![MSRV](https://img.shields.io/badge/MSRV-1.94.0-blue)](https://github.com/uutils/shadow)\n\n\u003c/div\u003e\n\n---\n\nA memory-safe reimplementation of the Linux\n[shadow-utils](https://github.com/shadow-maint/shadow) in\n[Rust](http://www.rust-lang.org). shadow-utils (`useradd`, `passwd`,\n`groupadd`, etc.) is the suite of setuid-root tools that manages user accounts,\npasswords, and groups on every Linux system.\n\n## Why\n\nshadow-utils runs as **root or setuid-root on every Linux system**. It parses\nuser-supplied input, writes to `/etc/passwd`, `/etc/shadow`, `/etc/group`, and\nhas had recent CVEs (CVE-2023-4641: password leak in memory, CVE-2024-56433:\nsubuid collision enabling account takeover). Until this project appear, there was **no\nRust reimplementation** — not in uutils, not in Prossimo/Trifecta, not on\ncrates.io.\n\n[sudo-rs](https://github.com/trifectatechfoundation/sudo-rs) proved the model:\nan independent Rust rewrite of a privilege-boundary tool can go from zero to\ndefault-in-Ubuntu in under 3 years. This project follows that playbook.\n\n## Goals\n\n- **Drop-in replacement**: same flags, same exit codes, same output format as\n  GNU shadow-utils. Differences are treated as bugs.\n- **uutils compatible**: built on [`uucore`](https://crates.io/crates/uucore)\n  with the standard `uumain()` / `uu_app()` API contract. Designed to merge\n  into the uutils ecosystem.\n- **Memory safe**: eliminate entire classes of vulnerabilities (buffer overflows,\n  use-after-free, uninitialized memory) that affect the C original. Passwords\n  zeroed in memory via `zeroize`.\n- **Well-tested**: unit tests, property-based tests (`proptest`), integration\n  tests, fuzz targets for all parsers. Tested on Debian, Alpine (musl), and\n  Fedora (SELinux).\n- **Hardened**: Landlock filesystem sandboxing, signal blocking during\n  critical sections, core dump suppression, environment sanitization,\n  privilege drop during PAM.\n- **Auditable**: small dependency tree, `cargo-deny` license and advisory\n  checks, no GPL dependencies.\n\n## Status\n\n| Tool | Status |\n|------|--------|\n| `passwd` | **All 16 flags implemented.** Drop-in for GNU passwd. PAM password change, Landlock sandboxing, `--root`, `--quiet`, `--stdin`. Output bit-for-bit identical with GNU. |\n| `pwck` | **All checks implemented.** Drop-in for GNU pwck. Bit-for-bit identical output. |\n| `useradd` | **Implemented.** UID/GID allocation, home dir + skel, shadow entry, group creation. |\n| `userdel` | **Implemented.** Remove from all system files, optional home/mail cleanup. |\n| `usermod` | **Implemented.** Modify all properties, group membership, lock/unlock, set pre-hashed password. |\n| `chpasswd` | **Implemented.** Batch password change from stdin. |\n| `chage` | **Implemented.** Password aging management, `-l` list mode. |\n| `groupadd` | **Implemented.** Auto GID allocation, system groups, force mode. |\n| `groupdel` | **Implemented.** Primary group usage check. |\n| `groupmod` | **Implemented.** GID change, rename, password. |\n| `grpck` | **Implemented.** Group/gshadow integrity verification. |\n| `chfn` | **Implemented.** GECOS sub-field modification. |\n| `chsh` | **Implemented.** Shell change with /etc/shells validation. |\n| `newgrp` | **Implemented.** Effective group change with crypt verification. |\n\n## Building\n\n### Requirements\n\n- Rust (stable toolchain)\n- Linux (PAM headers, SELinux headers optional)\n- Docker + Docker Compose (for testing)\n\n### Build\n\n```shell\ngit clone https://github.com/uutils/shadow\ncd shadow\ndocker compose build debian\ndocker compose run --rm debian cargo build --release\n```\n\n### Install\n\nDefault install: 14 standalone per-tool binaries with least-privilege setuid\nlayout matching GNU shadow-utils. Only `passwd`, `chfn`, `chsh`, `newgrp` are\ninstalled setuid-root; the other 10 are plain `0755`.\n\n```shell\nsudo make install PREFIX=/usr/local\n```\n\nAlternative: single multicall binary with symlinks. Smaller footprint (~14×\ndisk savings) but larger setuid attack surface — the binary is installed\nsetuid-root, so all 14 applets run with `euid=root` when invoked via symlink.\nIntended for container/embedded use cases.\n\n```shell\nsudo make install-multicall PREFIX=/usr/local\n```\n\n### Test\n\nAll builds and tests run inside Docker containers to isolate from the host\nsystem. Three distros are tested to catch libc and PAM differences:\n\n```shell\ndocker compose run --rm debian cargo test --workspace    # Debian Trixie (glibc)\ndocker compose run --rm alpine cargo test --workspace    # Alpine (musl libc)\ndocker compose run --rm fedora cargo test --workspace    # Fedora (SELinux enforcing)\n```\n\n### Lint\n\n```shell\ndocker compose run --rm debian cargo clippy --workspace --all-targets -- -D warnings\ndocker compose run --rm debian cargo fmt --all --check\n```\n\n## Architecture\n\nCargo workspace monorepo built on [`uucore`](https://crates.io/crates/uucore):\n\n```\nsrc/bin/shadow-rs.rs     multicall binary (dispatches by argv[0])\n        |\nsrc/uu/{tool}/           individual tool crates (passwd, useradd, ...)\n        |\n   ┌────┴────┐\nuucore    shadow-core    shared infrastructure + domain library\n```\n\nTools use `uucore` for the standard uutils API (`UResult`, `#[uucore::main]`,\n`show_error!`) and `shadow-core` for domain-specific functionality.\n\n**shadow-core** provides:\n- File parsers for `/etc/passwd`, `/etc/shadow`, `/etc/group`, `/etc/gshadow`,\n  `/etc/login.defs`, `/etc/subuid`, `/etc/subgid`\n- Atomic file writes (lock, write tmp, fsync, rename, unlock, invalidate nscd)\n- PAM integration (feature-gated)\n- Username/groupname validation\n- UID/GID allocation\n- SELinux context handling (feature-gated)\n\nEach **tool crate** exports `uumain()` and `uu_app()`, following\n[uutils](https://github.com/uutils/coreutils) conventions exactly so a future\nmerge is frictionless.\n\n## Docker Test Matrix\n\n| Target | Base | libc | PAM | SELinux |\n|--------|------|------|-----|---------|\n| `debian` | `rust:latest` (Trixie) | glibc | Linux-PAM | headers |\n| `alpine` | `rust:alpine` | musl | Linux-PAM | none |\n| `fedora` | `fedora:latest` | glibc | Linux-PAM | enforcing |\n\n## Credits\n\nSecurity patterns from [OpenBSD](https://cvsweb.openbsd.org/src/usr.bin/passwd/)\n(ISC license). PAM integration patterns from\n[sudo-rs](https://github.com/trifectatechfoundation/sudo-rs) (Apache-2.0/MIT).\nuutils infrastructure via [`uucore`](https://crates.io/crates/uucore) (MIT).\n\nCode written by [Claude Code](https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/overview) (Anthropic),\nreviewed by [GitHub Copilot](https://github.com/features/copilot) and\n[Google Gemini CLI](https://github.com/google-gemini/gemini-cli).\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.\n\n**Important**: uutils/shadow is developed under a strict GPL clean-room policy. Do\n**not** read, reference, or feed into an LLM any code from\n[shadow-maint/shadow](https://github.com/shadow-maint/shadow) (GPL-2.0+).\nReference only: POSIX specs, man pages, BSD-licensed implementations (FreeBSD,\nOpenBSD, musl), and sudo-rs.\n\n## License\n\nuutils/shadow is licensed under the [MIT License](LICENSE).\n\nGNU shadow-utils is licensed under the GPL 2.0 or later.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuutils%2Fshadow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fuutils%2Fshadow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fuutils%2Fshadow/lists"}