Subject
inquire is a Rust library for building interactive terminal prompts. It provides seven prompt types — Text (with autocompletion), Editor (gated on the editor feature, opens $EDITOR/$VISUAL on a temp file), DateSelect (gated on the date feature, calendar navigation backed by chrono), Select, MultiSelect, Confirm, CustomType, and Password — together with a pluggable rendering layer that targets crossterm (default), termion, or console as the terminal backend. The crate is configurable via per-prompt builders and a global RenderConfig carried in a Mutex.
Methodology
The published crate contents were compared against the upstream Git repository at the commit recorded in .cargo_vcs_info.json (3d5b65422a24...) using diff -rq. All Rust files under src/ were read in full (≈15.3K LOC across 70 files, including the unit tests under #[cfg(test)] mods). grep (BSD) was used to enumerate the call sites that justify the capability claims: std::net, std::fs, std::process, std::env, thread::, unsafe, forbid(unsafe_code), and the various impl-* indicators. find was used to enumerate non-textual artefacts in contents/. No build scripts, proc macros, or binary blobs were present, so no dynamic-execution review was needed. inquire's upstream CI configuration (under vcs-root/.github/workflows/) was inspected to confirm that lint, format, and tests run on stable, MSRV (1.82.0), and three OSes. The code was not built or executed locally; findings were derived by reading.
Results
The comparison between the published crate contents and the upstream Git repository shows that the code files match byte-for-byte; Cargo.toml differs only in cargo's standard normalization, and Cargo.toml.orig/.cargo_vcs_info.json/Cargo.lock are the cargo-generated artefacts. The CRATE_README.md differs from the upstream README.md because the README in the published crate is a stripped-down variant — the include list in the manifest (/src, /../LICENSE) excludes other repo files, and the README points to assets that only exist in the repository.
The crate ships no binary artefacts (justifying has-binaries), no build.rs (justifying has-build-exec), no install hooks, and no proc macros (justifying has-install-exec). The published Cargo.toml declares build = false explicitly, and [lib] carries no proc-macro = true. The audited surface contains no unsafe blocks at all (justifying uses-unsafe — grep for the unsafe token across src/ returns zero matches; the upstream README's "unsafe forbidden" badge is enforced by the absence of any such code rather than by #![forbid(unsafe_code)], which is not set).
Network, JIT, interpreter, and cryptographic functionality are entirely absent from the source tree — grep for std::net, wasmtime, rusty_v8, mlua, rusqlite, ring, openssl, sha2, aes, ed25519, RustCrypto returned no matches in the audited code (justifying uses-crypto, uses-jit, uses-interpreter, uses-network, impl-crypto, impl-jit, impl-interpreter, impl-protocol, impl-algorithm, impl-datastructure). The crate uses chrono for date math when the date feature is on, but does not itself implement an algorithm or datastructure worth the implementation claims, and does not implement any concurrency primitives (justifying impl-concurrency).
The crate has a sizeable in-tree test suite (145 #[test] or #[rstest] annotations across 18 files, including prompts/{confirm,select,multiselect,password,text,dateselect}/test.rs, the input handler tests, and parser/utils/ansi unit tests), but no integration tests under tests/, no fuzz harnesses under fuzz/, and no property-based tests (justifying has-unit-tests, has-integration-tests, has-fuzz-tests, has-property-tests).
Five low-severity findings were recorded:
- FINDING-1:
src/enum_support.rs is a dead module that is never wired into lib.rs and contains a phantom import of FromListOption from list_option, a type that does not exist there. Likely abandoned scaffolding for a strum/derive integration that was moved out to the separate inquire-derive crate.
- FINDING-2:
DateSelect's day/week navigation calls NaiveDate::add(Duration) directly, which panics on overflow, while the parallel month/year navigation uses checked arithmetic. Reaching the panic would require navigating to within days of NaiveDate::MAX/MIN (~year ±262143), so it is not realistically triggerable.
- FINDING-3: The
Password prompt's confirmation compares the two inputs with String's short-circuiting ==, not a constant-time compare, and stores the password as a plain String with no zeroize on drop. Not a meaningful exposure in the prompt's threat model (local terminal, no remote observer of timing), recorded for visibility.
- FINDING-4:
date_utils::get_month panics on out-of-range months. Currently only reachable through NaiveDate::month(), which always returns 1..=12, so unreachable in practice; flagged as the only panic! in the audited surface.
- FINDING-5: The
Editor prompt spawns the configured editor command via process::Command::new(...).args(...).arg(tmp_file_path).spawn(). The argv form precludes shell injection; the command source (with_editor_command or $EDITOR/$VISUAL) is the documented and trusted-by-design contract — justifies exec-safe.
The ANSI escape-sequence matcher in src/ansi.rs is the only parser implementation in the crate (justifying impl-parser). It is a small hand-written state machine over &str, fully panic-free and allocation-free, with unit tests covering normal and pathological inputs (justifying parser-impl-safe, parser-impl-tested). The comment cites vt100.net/emu/dec_ansi_parser as the basis; it implements a deliberately simplified subset of the DEC ANSI parser sufficient for inquire's rendering needs. The implementation is correct for that documented subset, justifying parser-impl-correct.
The crate uses concurrency only through a Mutex<RenderConfig> global accessed via set_global_render_config/get_configuration (justifying uses-concurrency); the lock is held for trivial scoped writes, so poisoning is not reachable under normal use. The thread-safety contract of the public prompt builders themselves is not explicitly documented per-type, supporting concurrency-documented being asserted false because no per-type Send/Sync narrative exists in the docs.
The code makes no malicious calls — no data exfiltration, no obfuscated payloads, no targeted cfg branches, no telemetry — supporting is-benign.
Conclusion
inquire 0.9.4 is a focused, well-organised terminal prompt library with a clean separation between the prompt state machines, the input/key abstraction, and three pluggable terminal backends. The audit surfaced five low-severity findings: one dead module (FINDING-1), one panic-on-overflow on a code path the user cannot realistically reach (FINDING-2), one minor cryptographic-hygiene gap in the Password prompt that does not actually matter for the prompt's threat model (FINDING-3), one unreachable panic! in date_utils (FINDING-4), and a documentation-only note about the editor subprocess invocation (FINDING-5). The published crate matches its upstream Git tree byte-for-byte, ships no binaries or build hooks, contains no unsafe code, and has a 145-test in-tree suite plus a multi-OS CI matrix.