Volker Schwaberow

Tightening the Bolts on npwg

3 min read
Tightening the Bolts on npwg

On the surface, writing a password generator feels straightforward. You take an operating system entropy source, map indices across a character set, and print the result.

Over time, as a tool grows to support diceware passphrases, custom character templates, interactive console prompts, and clipboard helpers, small edge cases accumulate. Code that worked in early prototypes can leave subtle gaps in memory handling or process boundaries.

For version 0.5.2 of npwg, I took a step back from adding new features and focused entirely on auditing the internals.

What needed fixing

Going through the codebase with fresh eyes surfaced a few areas where practical security and reliability could be improved:

  1. Passing secrets through process environments
    On Linux, the background daemon responsible for keeping the clipboard alive after the CLI exits received the generated password via an environment variable. On multi-user systems, environment variables can be inspected through /proc/$PID/environ. In 0.5.2, secrets are passed exclusively through standard input (stdin). The daemon now holds the secret in memory for 45 seconds, wipes the clipboard, and exits cleanly.

  2. Blind trust on network downloads
    The Diceware module downloads the EFF large wordlist on demand. Previously, the file was accepted upon download without verification. The new loader checks the downloaded content against a pinned SHA-256 hash before writing anything to disk.

  3. Lingering buffers in memory
    Temporary strings used during password mutation, clipboard handling, and interactive menus remained in memory until standard garbage collection or OS reclaim. All sensitive buffers are now wrapped with the zeroize crate, zeroing out memory as soon as values go out of scope.

  4. Multi-byte character slicing
    Certain mutation and strength-scoring routines indexed raw UTF-8 bytes instead of Unicode character boundaries. When users mutated passwords containing non-ASCII characters, this could trigger panics or produce skewed entropy scores. The generator now indexes characters consistently.

Cutting the dependency fat

A security utility should stay lean. Over several releases, the dependency tree had accumulated crates that were either experimental or superseded by standard library improvements.

In this release, I removed five crates entirely: chacha20, dashmap, regex, futures, and rand_distr. I also trimmed unused feature flags from tokio. This reduced compile times, cut down the binary footprint, and narrowed the supply-chain surface.

Continuous integration now runs cargo fmt, cargo clippy, and unit test suites on every pull request across Linux, Windows, and macOS.

Trying the update

You can update or install npwg directly through Cargo:

cargo install npwg --locked

Prebuilt binaries for Linux, Windows, and macOS are also available on the GitHub Releases page.