A template + collected wisdom for auditing any single posixutils-rs utility against POSIX.1-2024 (IEEE Std 1003.1-2024). Distilled from the first full audit (more, see display/audit.md).
Goal of an audit: produce <crate>/audit.md — a checkbox-driven punch list a maintainer can work through PR by PR.
- Sliced spec:
~/tmp/posix.2024/sliced/— see its top-levelREADME.md,INDEX.md,ALIASES.md. Use the slice, never the 4107-page PDF. - Primary spec file:
~/tmp/posix.2024/sliced/xcu-shell-and-utilities/3-utilities/<util>.md. If the utility name is weird (shell builtin./:, posixutils-rspcc→c17, etc.), consultALIASES.mdfirst. - Implementation: typically
<category>/<util>.rs(e.g.display/more.rs,file/cat.rs). Multi-file utilities live in their own crate (sh/,awk/,pax/,cc/,make/,m4/,editors/). - Tests:
<category>/tests/<util>/mod.rs. Skim for coverage signal, not bug-hunting. - Cross-referenced spec sections to consult when the main spec links them:
xbd-base-definitions/12-utility-conventions/— argv parsing rules (POSIXgetoptsemantics,--,-operand,+prefix exceptions)xbd-base-definitions/9-regular-expressions/9.3-Basic-Regular-Expressions.mdand9.4-Extended-Regular-Expressions.md— every search-capable utilityxbd-base-definitions/8-environment-variables/—LANG/LC_*precedence,COLUMNS/LINESsemanticsxrat-rationale/— the matching appendix when "why" matters (e.g., Austin Group Defects mentioned in CHANGE HISTORY)
- Locate spec + implementation + tests (paths above). Verify alignment via
ALIASES.mdif name is non-obvious. - Read the full per-utility spec.md. Do not skim. The spec sections set the audit outline.
- Read the implementation in full. Files >2000 lines: chunk-read, or delegate to a
feature-dev:code-explorersubagent with an explicit template (see §5). - Skim tests for what's covered. Track gaps as "write a test" items.
- Verify Critical/Major claims by reading cited line ranges directly, and by grepping for "absent" things (signals, file descriptors, env vars). Do this BEFORE writing the audit doc — never publish unverified claims.
- Write
<crate>/audit.mdusing the template in §6. Every actionable finding is a checkbox. - Propose PR groupings at the bottom — 3 to 6 small, themed PRs are easier to land than one mega-PR.
Walk the spec section by section in order. For each section, decide: CONFORMS / PARTIAL / MISSING / DIVERGES / N/A.
| Spec section | What to verify | Common pitfalls |
|---|---|---|
| SYNOPSIS | Option letters match; option grouping (-abc) works; -- end-of-options handled; + prefix if spec mentions XBD 12.2 exception |
Clap quirks around +, position-of-- operand, unknown-option behavior |
| OPTIONS | Each declared option is present AND its full semantics match | Flag parsed but never consulted in the render/exec path; only first sentence of the spec implemented |
| OPERANDS | - operand routes to stdin; missing-operand → stdin; multiple operands handled in order |
- ambiguity when mixed with file paths; single-line stdin reads |
| STDIN | Only consumed when spec says so | Spurious early stdin slurp; truncation to first line |
| INPUT FILES | File types accepted; for interactive utilities, where commands are read from | Reading commands from stdin instead of stderr / /dev/tty |
| ENVIRONMENT VARIABLES | Every variable listed in the spec is read; precedence rules honored | Reading once at init and never re-checking on resize/refresh; missing LC_* chain |
| ASYNCHRONOUS EVENTS | Every signal mentioned has a handler; default-others rule respected | Missing SIGCONT/SIGWINCH; signal handling via polling instead of signal-hook |
| STDOUT / STDERR | Content target, diagnostic target, prompt target | Prompt written to stdout instead of stderr; missing required prompt fields (filename, EOF, next-file) |
| OUTPUT FILES | Usually "None" — quick check | — |
| EXTENDED DESCRIPTION | Utility-specific rendering / behavior rules | Multi-column character handling, control-char display, fold/wrap rules |
| Interactive commands | One row per command; count-prefix; semantics | ''-style "last position" trackers not updated; commands that move >1 screenful not flagged as "large movement" |
| EXIT STATUS | 0 success / >0 error mapping | Always exits 0; doesn't propagate per-file errors |
| CONSEQUENCES OF ERRORS | Per-command error policy (continue vs abort) | :n/:p-class errors abort instead of advancing |
| Cross-cutting | i18n (gettext), regex flavor (BRE vs ERE), locale-driven behavior, security-sensitive syscalls (setuid/setgid) | Hardcoded English diagnostics; ERE leaks where BRE required; ignored setgid() return values |
Per-finding status (use exactly these labels):
- CONFORMS — matches spec; pre-check the box
- [x]. - PARTIAL — present but incomplete; semantics not fully implemented. Unchecked.
- MISSING — not implemented at all. Unchecked.
- DIVERGES — implemented but contradicts the spec. Unchecked.
- N/A — optional/XSI/CT feature legitimately not provided; track but unchecked.
Per-finding priority (assign to every unchecked item):
- Critical — user-visible data loss, hang, crash, or "doesn't do what
mansays" on the golden path (util | more,util file). Block on these for any release pitch. - Major — spec-mandated behavior absent on a common path; or wrong exit code; or wrong I/O channel; or missing signal handling for interactive utilities.
- Minor — strict-conformance gaps that don't bite real users today (string-vs-path comparison, locale env var coverage, undocumented flags, hardcoded English).
When in doubt, prefer the higher severity — easier to demote than to discover the bug in the field later.
These are recurring antipatterns surfaced by the more audit. Worth a 30-second grep on every utility.
-
grep -n 'stdin\(\)' <util>.rs— interactive utilities should NOT read commands from stdin. Spec says stderr (with/dev/ttyfallback). -
grep -n 'self.tty\|stdout()' <util>.rsnear prompt-writing code — prompts go to stderr per spec. - Look for
.lines().next()orread_line()where the code expects to ingest a whole file/stream — truncation bug.
-
grep -nE 'SIGCONT|SIGWINCH|signal_hook|libc::signal' <util>.rs— interactive utilities (more, vi, ed, ex, mailx) MUST handle SIGCONT and SIGWINCH per spec. Zero matches = MISSING. - Window-size changes detected via polling
terminal_size()in an input loop are DIVERGES from "asynchronous event" semantics.
-
grep -nE 'env::var\("(LANG|LC_ALL|LC_CTYPE|LC_COLLATE|LC_MESSAGES|NLSPATH|COLUMNS|LINES)"' <util>.rs— verify every var the spec lists is read. - After a resize or refresh, the env vars
COLUMNS/LINESshould be re-honored. Common bug: read once at init, then ignored. - MORE/
LESS/EDITOR-style pre-option env vars: must be processed BEFORE the command line, with CLI args overriding.
- Spec says "may treat
+as an option delimiter": clap doesn't do this natively — track as MISSING unless explicitly wired. - Hidden test flags (
--test,--debug) in the public clap surface: should be#[arg(hide = true)]or behind a feature gate. -
-operand: confirm it routes to stdin AT THAT POSITION in the file list, not just "stdin if-present". - Bundled short options (
-ceisuvs-c -e -i -s -u): clap handles by default; double-check for utilities written without clap.
-
EDITOR == "vi"/EDITOR == "ex"antipattern — won't match/usr/bin/vi,vim,view. UsePath::new(&editor).file_name(). - Same pattern for
SHELL,PAGER,TERM-prefix checks.
- For
vi/exinvocations, POSIX mandates-c linenumber. Many implementations historically use the older+Nform — DIVERGES from spec even though most editors accept both. -
setuid(getuid())/setgid(getgid())return values being ignored (let _ = ...) is a security smell worth flagging.
- Search/match utilities default flavor:
grep -nE 'RegexFlags::|Regex::new' <util>.rs. POSIXgrep(no-E),sed(without-E),more/ed/ex/vi/expruse BRE.awkandgrep -E/egrepuse ERE. Easy to wire the wrong flavor. - Tag-style lookups: if the spec says "tag" (literal name), don't use
grep(regex). Use literal match orgrep -F.
-
grep -n 'gettext\|gettextrs' <util>.rs— clap help strings often are gettext'd, but runtime diagnostic strings (errors, prompts) often aren't. POSIX requiresLC_MESSAGESto affect diagnostic text. -
setlocale(LC_ALL, "")should be present nearmain(). Missing →LC_*env vars do nothing.
- Lines longer than the terminal: fold vs truncate vs wrap — check spec wording.
- Multi-column (wide) Unicode characters at the wrap boundary: POSIX leaves this unspecified, but truncating mid-codepoint is a crash risk.
- Backspace/underscore/overstrike → underline/bold translation: check the FULL POSIX sequence (
char + n*BS + n*'_'), not just the n=1 case. -
\rat end of line: should be silently discarded before\n, not displayed as a control character. - Non-printable characters: spec usually says "use the same format as
ex print" —^Xfor control,\NNNoctal for high bytes.
-
exit(0)everywhere → never propagates errors. Should set ahad_errorflag and exit non-zero at the end. - Per-command error policy (CONSEQUENCES OF ERRORS) is often missed:
:n/:p-style errors should advance/retreat AND set non-zero exit, not abort.
For utilities >1500 lines, delegate to feature-dev:code-explorer. It's read-only and good at cross-referencing two large files.
Prompt template (paste, fill in <util>, <path>):
Perform a systematic POSIX.1-2024 conformance audit of
<util>.Spec (read in full):
/home/jgarzik/tmp/posix.2024/sliced/xcu-shell-and-utilities/3-utilities/<util>.mdImplementation (read in full):/home/jgarzik/repo/posixutils-rs/<path>/<util>.rsTests (skim for coverage signal):/home/jgarzik/repo/posixutils-rs/<path>/tests/<util>/mod.rsSupporting spec sections to consult as referenced:
xbd-base-definitions/12-utility-conventions/— argv rulesxbd-base-definitions/9-regular-expressions/— BRE/ERE if applicablexbd-base-definitions/8-environment-variables/— LC_*/COLUMNS/LINESOutput sections (in order): SYNOPSIS, OPTIONS (table), OPERANDS, STDIN, INPUT FILES, ENVIRONMENT VARIABLES (table), ASYNCHRONOUS EVENTS, STDOUT/STDERR, OUTPUT FILES, EXTENDED DESCRIPTION, Interactive commands (table — only if utility has them), EXIT STATUS, CONSEQUENCES OF ERRORS, Cross-cutting (i18n, regex flavor, signal handling).
Per finding: cite implementation line numbers; mark CONFORMS / PARTIAL / MISSING / DIVERGES / N/A; do NOT flag things the spec leaves "implementation-defined" or "unspecified" unless they cause a crash/hang.
End with: Summary table — top 5–10 issues ranked Critical / Major / Minor with one-line fix sketches.
~2000–3000 words. Tables liberally. No code blocks >5 lines. Read-only — do NOT modify files.
After it returns: always spot-check at least the Critical findings. Read the cited lines. Grep for "absent" claims. Agent summaries describe what the agent intended to find, not necessarily what's true. (The more audit had two such checks that both confirmed real bugs — but treat verification as mandatory, not optional.)
# POSIX.1-2024 Conformance Audit — `<util>`
**Implementation:** `<path>/<util>.rs` (N lines) + `<path>/tests/<util>/mod.rs` (N lines)
**Spec:** POSIX.1-2024 (IEEE Std 1003.1-2024), Vol. 3 §3, pp. X–Y
**Reference slice:** `~/tmp/posix.2024/sliced/xcu-shell-and-utilities/3-utilities/<util>.md`
**Date:** YYYY-MM-DD
## TL;DR
[2-4 sentences: what works, what doesn't, headline risks.]
## Priority issues
### Critical
- [ ] **#1 — <one-line summary>.** `<file>:<line>`. Fix: <one-line sketch>.
### Major
- [ ] **#N — ...**
### Minor
- [ ] **#N — ...**
## Detailed conformance matrix
### Options
- [x] `-a` CONFORMS — ...
- [ ] **`-b` PARTIAL** — ...
### Operands / STDIN
- [x] ...
- [ ] ...
### Environment variables
- [x] `VAR` CONFORMS — ...
- [ ] **`VAR` MISSING** — ...
### Asynchronous events
- [ ] **SIGFOO MISSING** — ...
### STDOUT / STDERR
- [ ] **...**
### Interactive commands (if applicable)
- [ ] **`cmd` PARTIAL** — ...
### Extended description / rendering
- [ ] **...**
### Exit status / consequences of errors
- [x] ...
- [ ] **...**
## Test coverage signal
Not covered:
- [ ] <behavior>
- [ ] <behavior>
## Suggested PR groupings
- **PR A — "<theme>"**: #X, #Y, #Z
- **PR B — "<theme>"**: ...Rules for the doc:
- Every actionable item is
- [ ](unchecked). Future sessions will tick boxes as PRs land. - Things already CONFORMS are
- [x](pre-checked) so the doc shows what's done vs outstanding at a glance. - Every Critical / Major / Minor priority item gets a number (
#1,#2, …) that the PR groupings can reference. - Every finding cites a
<file>:<line>range. "CONFORMS" without a line is useless. - The doc is the contract. Don't rewrite it during fix PRs — only tick boxes and append "✓ fixed in PR #NNN" inline.
- Don't paraphrase the spec. Cite the section name and quote the operative
shallverbatim when something is on the line. (The slice gives you line numbers and section headers for free.) - Don't audit by running a subagent on the spec alone. It hallucinates code structure. Always pair spec + implementation.
- Don't trust "the agent said the file doesn't contain X." Verify with
grep. - Don't propose fixes for things the spec calls "unspecified" or "implementation-defined" — unless the current behavior crashes, hangs, or is actively wrong (negative count, division-by-zero on empty file, etc.).
- Don't audit tests. Tests are signal, not source-of-truth. The implementation is what conforms (or doesn't).
- Don't bundle the fixes into the audit. Audit = punch list. Fixes = separate, focused PRs. The whole point of the checkbox format is to defer execution.
- Commit
<crate>/audit.md(alongside source). Reviewers can compare against the spec at any time. - When picking up the next session: read the file, choose 1–3 unchecked items that share a theme, write the fix + a test that proves the box now ticks, and tick the box in the same PR.
- If a finding turns out to be wrong on closer inspection: do NOT silently delete the box. Tick it with a one-line note (
- [x] ~~#7~~ — re-examined; actually conforms because of <reason>). This preserves history for the next auditor.
-
awk/audit.md—awk(full language audit, behaviorally verified; 1 Criticalclose()crash, 6 Major:-Fescapes, byte-vs-char, printf*,-f -, field uninitialized comparison, 1024-field cap). -
calc/audit.md—expr,bc(behaviorally verified).expr: 4 Critical (precedence ignored, regex-not-BRE:, div-by-zero panic, exit status).bc: 2 Critical (quit-in-for-in-function panic, diagnostics on stdout), Major (noBC_SCALE_MAX/BC_BASE_MAX/BC_DIM_MAX, no 70-col wrap). Note: behavioral verification refuted several agent-proposed findings (three Critical "division/sqrt rounds" claims and the-1^2precedence Major) —bctruncates correctly and matches GNU on-1^2. -
cron/audit.md—crontab,at,batch,crond(the cron family;crondaudited vs. Vixie cron + implicitcrontab/at/batchrequirements + secure-daemon practice). Headline risks:crondexecutes spool files with no ownership/permission/symlink checks;crontab -etruncates the existing entry;at/batchjobs are filed but never run; multi-operandattimespecs and thecrontabstdin form are unsupported. -
datetime/audit.md—cal,date,sleep,time(the date/time crate; four single-file utilities, static spec-vs-code against the sliced POSIX.1-2024 tree, every "absent"/"wrong-value" claim grep-verified).calis the cleanest (Julian→Gregorian Sep-1752 gap, operand forms, ranges, andTZ-driven current month all conform; onlyLC_TIMEmonth/weekday names are hardcoded English).timecarries both Criticals: the end-of-runtms_endismem::zeroed()and never refilled by a secondlibc::times()call, and the arithmetic reads the parent's owntms_utime/tms_stimesubtracted start−end instead of the child'stms_cutime/tms_cstimeend−start — so the reported User/System CPU time is a near-zero constant unrelated to the invoked utility (the utility's whole purpose).timealso discards the child's exit status (let _ = child.wait()) and always exits 0, violating "exit status oftimeshall be the exit status of utility". Major elsewhere:sleep 0is rejected (range(1..)) though POSIX'stimeoperand is a non-negative integer; anddate's 2-digit-year century inference is off by one (yy=69→ 2069, but POSIX mandates 69–99 → 1969–1999). Minors:date's empty-strftime-is-an-error andfrom_utf8_lossymangling, and hardcoded-English diagnostics indate/time(LC_MESSAGESinert). Totals: 2 Critical, 3 Major, 6 Minor. All actionable findings have since been remediated on thedatetime-auditbranch across five themed, independently-committed phases (each with regression tests;build/clippy --all-targets/fmt/ datetime tests clean): Phase 1timeCPU accounting + exit-status propagation (#T1/#T2/#T3/#T5); Phase 2sleep 0+ the crate's firstsleeptest module (#S1); Phase 3datecentury off-by-one (infer_century+ unit test), grow-until-fitsstrftime, raw-byte output (#D1/#D2/#D4); Phase 4 crate-wideplib::diag::init_locale+gettextdiagnostics fordate/time(#T4/#D3/#T6, with#S2dispositioned a deferred clap/tree-wide concern); Phase 5calLC_TIME-aware month/weekday names viaplib::locale::strftime(#C1). All four utilities promoted to README Stage 6 — Audited. Deferred:.mocatalog shipping (tree-wide, soLC_MESSAGESstays inert) and two minor test-coverage niceties. -
dev/audit.md—yacc,lex,ar,nm,strings,strip(development utilities; sharedplib::diag/io/archive/localeinfrastructure). -
display/audit.md—more(the first full pass; covers 15 priority items, 28 interactive commands, signal handling, i18n). -
editors/audit.md—ed,ex,vi(the editor family; Critical/Major findings behaviorally verified). Four cross-cutting themes: theregexcrate is ERE where the spec requires BRE (eddoes no translation at all;exaddress searches bypass the converter);vi/exinstall zero signal handlers (no SIGWINCH/SIGCONT/SIGHUP — resize corrupts the screen, hangup loses the buffer);ednever sets a non-zero exit status on command errors; andvi/exnever callsetlocale. Other headline risks:edreports an identical-result substitution as "no match",vi -r/-thard-error and exit, andex -sstill sources EXINIT/.exrc. -
fs/audit.md—dfonly (thefs/crate now ships a single POSIX utility plus the Linuxmntent.rsmount-table helper;cp/mv/rmmoved totree/,basename/dirname/pathchk/realpathtopathnames/). Static spec-vs-code audit against the sliced POSIX.1-2024 tree, grep-verified for every "absent" claim. The block-figure path (-k,-P, default 512-byte units, the-Pdata-line format, size/used/avail values, POSIX-locale header strings) is largely correct, butdfis materially incomplete:-tis unimplemented (XSI, in the SYNOPSIS); the default and-toutput never report free inodes / "file slots" despite a DESCRIPTIONshall; and the Capacity percentage uses the wrong denominator (f_bfreeinstead off_bavail), so it disagrees withdf -P/coreutils on any reserved-block filesystem and can never exceed 100% as the spec note requires. Two robustness defects compound this: a non-UTF-8 mount path panics the golden no-operand path (to_str().unwrap()on kernel-supplied names), and a failed or unmatchedfileoperand silently falls back to printing every filesystem (ensure_maskedmasks all when nothing matched). Locale init (setlocale/textdomain) is wired but runtime diagnostics are hardcoded English. 1 Critical, 4 Major, 7 Minor. All findings have since been remediated (5 phases on thefs-auditbranch): byte-faithfulOsString/PathBufnames + no all-filesystems fallback + newline guard (#1/#5/#8/#9); correctf_bavailcapacity % +u128-safe scaling + zero-denominator guard (#4/#10/#11); free-inode columns +-t/-P|-texclusion (#2/#3/#7);gettextdiagnostics + coreutils-aligned non-fatal enumeration errors (#6/#12) — each with regression tests (24 fs tests) and behaviorally cross-checked against GNU coreutilsdf.dfpromoted to README Stage 6 — Audited. -
file/audit.md—cat,cmp,dd,file,find,od,split,tee(thefile/crate; eight utilities, behaviorally verified against the mega-PDF, no sliced tree). Headline risks:teedoes not copy stdin→stdout and rejects file operands;find -nameis regex not fnmatch (bracket ranges like[a-z]match nothing) and-iname/-mountare missing;filemagic</>comparisons are inverted and symlinks are followed by default;od -cemits named chars instead of C escapes;split-operand is not stdin and the{NAME_MAX}check is absent;cmp -sleaks anEOFdiagnostic;ddconv ordering / SIGINT re-raise. Cross-cutting: hardcoded-English diagnostics. -
i18n/audit.md—gencat,gettext,ngettext,iconv,locale,localedef,msgfmt,xgettext(thei18n/crate; eight utilities, all behaviorally verified against the mega-PDF, no sliced tree). Real in-tree implementations (not host delegations), but every utility has gaps and several have Critical defects. Headline risks:gencatpanics (exit 101) when merging into a pre-existing catalog and processes no escape sequences/line-continuation (catalogs miscompiled);iconvprints a conversion/codeset error yet exits 0 (and derives its default codeset from a naiveLANGsplit that hard-fails underLANG=C);localereturns hardcodedd_fmt/t_fmt/yesexpr/noexprregardless of locale and is missing ~30LC_MONETARY/LC_TIMEkeywords;localedefwrites only a one-lineLC_IDENTIFICATIONmarker and never parses-f charmap/LC_CTYPE/LC_COLLATE(no usable locale);msgfmtignoresdomaindirectives so a multi-domain.pocollapses into one file named after the input;gettext/ngettextappend a spurious trailing<newline>outside-s, lack-E, andngettextcan't take the optional[textdomain]operand;xgettextwritesmessages.pot(spec:messages.po), registers-Xfor the spec's-x, and sorts output alphabetically instead of in extraction order. Cross-cutting: error paths exiting 0, hardcoded-English diagnostics (LC_MESSAGESinert), and unimplementedNLSPATH/LANGUAGE. All priority findings have since been remediated on thei18n-auditbranch (13 phases): seven utilities —gencat,gettext,iconv,locale,msgfmt,ngettext,xgettext— are now promoted to README "Stage 6 — Audited";localedefreceived bounded parser/exit-code/directive fixes but stays at Stage 3 because emitting a real libc-consumable compiled locale (LD-1) andLC_CTYPE-driven byte interpretation (cross-cutting theme 4) are explicitly deferred. -
m4/audit.md—m4(macro processor; behaviorally verified against the mega-PDF spec, no sliced tree available). 2 Critical panics (indexempty-needlewindows(0);eval/0,%0), 8 Major (evalignores radix/min-digit args + no octal/hex + shift-vs-relational precedence;$#==0 formacro();m4wrapnot rescanned;defncan't reproduce built-ins; recoverable errors abort the run; byte-not-character semantics). Core path (spec EXAMPLES,$@/$*/shift, divert/undivert, pushdef/popdef, m4exit-after-error) conforms. -
mailx/audit.md—mailx(the message send/receive utility; ~4.4 kloc across nine modules, 141 tests; static spec-vs-code audit with grep verification of every Critical/Major "absent" claim). Headline risks: the-Eoption — one of only two required on all systems — is unimplemented and errors out; the entire ASYNCHRONOUS EVENTS section is absent (noSIGINThandler anywhere, soSIGINTkills mailx and-i/ignoreis dead code keyed off anErrorKind::Interruptedthat never fires); and header-summary display panics on multibyte text (byte-offset&s[..n]slicing inmessage.rs/mailbox.rs). Major band: everysh -cinvocation omits the--argument mandated by Austin Group Defect 1528 (pipe/!/~!/~|/~r !); the-f fileoperand is mis-parsed into Send Mode unless glued to-f(breaking the RATIONALE's requiredmailx -fin mymail.box);-nwrongly skips the userMAILRC(spec attaches "unless −n" only to the system start-up file); nosetlocale/gettextand hardcoded-English diagnostics; loaded messages are never given thenewstate (alwaysunread, soNshows asUand:nmatches nothing); the~:command-level escape is a stub whosesetonly echoes;~wtruncates instead of appending; and reply-all ignoresReply-To. The command/escape/msglist surface is otherwise broad and mostly conforming. No fixes applied — audit only. -
make/audit.md—make(behaviorally verified against the mega-PDF spec, no sliced tree). 5 Critical (recipe lines containing=abort the parse withEmptyIdent;.POSIXrejected as unsupported; missingincludepanics;make -kreports failure+exit 2 on success; command-linemacro=valueoperands unsupported), plus Major gaps: no$(VAR:a=b)substitution, no backslash-newline continuation, single-suffix inference unused, no-j/token-pool/.WAIT/.NOTPARALLEL, no multiple-f, no shell-e,SHELLenv var misused,.SUFFIXESBTreeSet loses order,MAKEFLAGSignored. Behavioral verification refuted four agent-proposed findings ($(VAR)-verbatim-to-shell,$$passthrough, inverted?=,-includepanic). -
man/audit.md—man(themancrate plus the mdoc/roff engine the maintainer built implicitly to satisfy POSIXman; behaviorally verified against the mega-PDF, no sliced tree). Every priority finding has since been remediated on theman-auditbranch (Phases 1–5 plus a follow-on engine rewrite: a single terminal backend, a full roff front-end, pest replaced by a total hand-written recursive-descent parser, and tbl/eqn preprocessors). Original headline risks: a.Xr namepage panicked the process and deeply nested macros overflowed the stack; legacyman(7)/roff pages rendered as an empty page yet exited 0; no bold/italic/underline was emitted and\fB…\fRfont escapes leaked as literal text;PAGERwas spawned even when stdout is not a terminal; width was capped at 78; and-kdid literal-substring matching rather than the spec’sgrep -Ei(ERE). -
misc/audit.md—true,false,test/[(themisccrate; behaviorally verified against the mega-PDF, no sliced tree). The cleanest crate audited so far: no Critical or Major defects.true/falseare textbook-conforming;testimplements the full primary set, the 0/1/2/3/4/>4 argument-count precedence algorithm, the[ … ]form, and correct 0/1/>1 exit codes. Only real divergence:</>compare by byte/scalar order instead ofLC_COLLATEcollation. Informational: the POSIX-2024-removed-a/-o/(/)operators survive as a >4-arg extension (legal — that path is "unspecified") but the 3-arg-a/-oform errors; integer operands arei64-bounded and reject leading blanks. -
pathnames/audit.md—basename,dirname,pathchk,realpath(thepathnames/crate; all findings behaviorally verified against the release binaries).dirnameis the cleanest (lexicalPathBuf::pop()conforms). The other three are broken on common paths:basenamepanics (exit 101) on/,.., and any…/..operand and strips the suffix from the whole pathname before extracting the component (missing the step-6 "suffix identical to result" guard →basename /usr/bin/env envprintsbin);pathchk's default filesystem mode errorspathconf errorfor every existing file and every creatable relative name (find_fshandlereturns""), wires-p/-Pas mutually exclusive (spec mandates using them together), and usesis_ascii()instead of the portable-filename character set for-p;realpathdoes not resolve symbolic links in default or-Emode (purely lexicalnormalize()) — only-e(viafs::canonicalize) is correct, and the existing tests codify the divergent lexical behavior. Cross-cutting: hardcoded-English diagnostics (LC_MESSAGESinert) andto_string_lossy/Stringnon-UTF-8 mangling. All priority findings have since been remediated (Phases 1–5): basename rewritten to the POSIX 6-step byte algorithm; pathchk'sfind_fshandlerepaired and-p/-Pmade combinable; realpath now resolves symlinks in default &-Emodes; all four adoptplib::diag+ byte-faithful I/O. All four utilities promoted to README "Stage 6 — Audited". -
pax/audit.md—pax(the archiver; ~10.3k lines across three on-the-wire formats — ustar, cpio ODC, pax interchange — five modes, multivolume, and-ssubstitution; comprehensive all-surface audit, behaviorally cross-checked in both directions against GNUtar1.35 and GNUcpio2.15, since no referencepaxis installed). Verdict: the hard parts are right and the easy parts are wrong. All three formats interoperate bidirectionally with tar/cpio on the everyday path (regular/dir/symlink/hardlink/fifo, ustar prefix/name long-name split ≤255, special-char/Unicode names, EOF markers, input auto-detection); the pax self-counting extended-header length is correct (incl. the digit-carry boundary) and the-sBRE substitution engine (&,\1–\9,g,p, in-order/first-success, empty→skip) and fnmatch patterns (correctly do not cross/) conform. Headline defects are process semantics, not wire formats: exit status is never set non-zero for unmatched patterns / missing operands / per-file failures (Critical), and a per-file error aborts the run so extraction stops mid-archive and later members are silently lost (Critical, data loss). Major band: ustar/cpio numeric fields corrupt members ≥8 GB (dropped terminator / silent high-digit truncation); pax drops sub-second mtime (20 mtime=…vs GNU30 mtime=….123456789); default extraction ignores umask (mode 0777 vs tar's 0755); default blocksize is 10240 for every format (spec: 5120 for cpio/pax) and-bmisreads 1–511 as a GNU blocking factor (-b 20→10240 bytes);-srejects thes/Sflags; append silently coerces a mismatched-xformat; a directory pattern doesn't select its subtree (-dinert in read/list); and several-okeyword behaviors (:=standard-keyword overrides, delete/override/invalid in read/list, the POSIXlistopt=%(keyword)sform) are unimplemented. Non-POSIX extensions (kept, documented):-zgzip and-MGNU-style multivolume. No crashes/hangs. All findings have since been remediated on thepax-auditbranch (8 phases): both Critical findings (exit status; per-file abort/data-loss) and every Major/Minor item are fixed and covered by per-phase regression tests (120 integration tests), each behaviorally re-verified against GNUtar/cpio; only #26 (non-UTF-8 path bytes; cpio TRAILERc_mode) is dispositioned WON'T-FIX.paxis promoted to README Stage 6 — Audited. -
print/audit.md—lponly (theprint/crate ships a single POSIX utility;pr/printflive intext/). Static spec-vs-code audit against the sliced POSIX.1-2024 tree, every "absent" claim grep-verified. Thislpis a thin IPP (Internet Printing Protocol) client — destination is anipp://URI, data uploaded synchronously via theippcrate, no CUPS/spool//dev/lpintegration and no system-default printer — a deliberate minimal-deps architecture divergence (audited the wayuucp's SSH transport was: spec-intent gaps recorded Major, not Critical). No Critical defects. The POSIX surface is complete and the mechanics conform:-/no-operand→stdin, multiple files printed in order as integral wholes,-d>LPDEST>PRINTERprecedence, request-ID-to-stdout gated by-s, diagnostics-to-stderr, and — the cleanest i18n wiring audited so far —setlocale+textdomain+gettexton every diagnostic. Four Major findings:-m(mail) and-w(terminal write) are parsed-but-ignored no-ops (-cis also ignored but is a conforming no-op — IPP always slurps + uploads the whole file before exit, so the-cguarantee always holds); no system-default destination so barelp/lp filealways exits 1 (permitted via "no device available→non-zero" but violates the RATIONALE's "should always execute with no options or operands" intent); and the destination must be anipp://URI, so historicalLPDEST=name/PRINTER=namevalues are rejected. Minors: first-error aborts remaining operands (permitted — CONSEQUENCES=Default),copiesu32→i32overflow, noipps://, silent malformed--o,<dest>-0request-ID fallback, noNLSPATH.LC_TIME/TZare N/A (banner is the IPP server's job). All actionable findings have since been remediated (5 phases on theprint-auditbranch):resolve_uriaccepts bare printer names →ipp://localhost/printers/<name>(#4);-nbounded toi32::MAX, malformed-owarns, missingjob-idis an error (#6/#8/#9); per-file errors continue instead of aborting (#5); and-m/-wnow poll IPPjob-stateto completion (120 s bound) then mail via local sendmail / write/dev/tty(#1/#2) — each phase committed with regression tests (22 integration + 5 unit). Dispositioned WON'T-FIX: #3 (no system default — conforming per 103059–61), #7 (ipps:///TLS — minimal-deps), #10 (NLSPATH— tree-wide).lppromoted to README Stage 6 — Audited. -
process/audit.md—env,fuser,kill,nice,nohup,renice,timeout,xargs(theprocess/crate; eight utilities plus the sharedsignal.rstable; static spec-vs-code audit against the sliced POSIX.1-2024 tree, with every Critical/Major claim confirmed by reading the cited code + spec lines, and several agent-proposed findings refuted and recorded inline). Headline risks cluster in two families. The exec-launcher exit-status contract is split:nohup/timeout/xargsmap 126/127 correctly, butenvandnicepropagate the exec error throughmain's?and always exit 1 — andniceadditionally aborts instead of honoring the spec's central "a failednice()shall not prevent invoking the utility" guarantee (plus a wrongres < 0errno check and a clap range that rejects-n 40).reniceaccepts only a singleIDwhere POSIX mandatesID..., so per-ID error continuation is structurally impossible, and it wrongly rejects numeric ID0and excludes+20.nohupnever sets the mandated 0600 mode onnohup.out, readsdirs::home_dir()instead of$HOME, misses the "redirect stderr to the same open file description as stdout" case, andpanic!s (exit 101) on a file-open failure.timeouttruncates sub-second/fractional durations viaalarm(2)(sotimeout 0.5snever fires), unconditionally resets the child's SIGTTIN/SIGTTOU toSIG_DFLinstead of inheriting timeout's own disposition, and forwards only 5 signals rather than the full terminate-default set.xargslacks the POSIX.1-2024-roption and runs the utility zero times on empty input where the spec requires exactly once, plus ac8 as charcast that corrupts multibyte UTF-8 arguments.fuser's stdout PID format uses two spaces for ≤4-digit PIDs vs the spec's" %1d", and its/proc/mapsdevice decode uses obsolete 8-bit minor encoding.killis the cleanest — no Critical/Major; the agent's "kill -l 6prints IOT not ABRT" headline was refuted (ABRTis present and ordered first). Cross-cutting: locale is initialized everywhere but runtime diagnostics are hardcoded English (LC_MESSAGESinert), andenv/nice/nohup/renicehave zero tests. Totals: 10 Critical, 16 Major. Refuted findings (recorded, not actionable):env -u(not in POSIX.1-2024),fuserexit>0-on-no-match (GNU-only),xargssignal→125 / 255-diagnostic (folds to conformant exit 1),killABRT/IOT + 128+N boundary + negative-pid,reniceobsolescent positional form. All priority findings have since been remediated on theprocess-auditbranch across 8 themed phases (one per utility), each independently committed with regression tests and behaviorally re-verified: a sharedposixutils_process::exec::exec_error_exit126/127 mapper (env/nice);niceinvoke-anyway + errno check + full range;reniceID...+ per-ID continuation + ID 0 +-20..=20(andplib::priorityno longer prints its own diagnostics);nohup0600 +$HOME+ spec stderr-fd routing + no-panic;timeoutsetitimersub-second + SIGTTIN/SIGTTOU inheritance + full forwarding set + WCOREDUMP re-raise;xargs-r/run-once-on-empty + UTF-8 word-split + quoted-newline error +-Ein insert mode;fuser" %1d"format +makedev+ error propagation;killper-signal-l+-l-option edge; and a crate-wideplib::diagi18n migration (#C1). Validation: full workspace build +clippy --all-targets+fmt --checkclean; 132 process integration tests + 71 plib tests green. All eight utilities promoted to README Stage 6 — Audited. -
sys/audit.md—getconf,ipcrm,ipcs,ps,uname,who(the system-information crate; six utilities plus thepslinux.rs/psmacos.rsback-ends; static spec-vs-code against the sliced POSIX.1-2024 tree, every Critical/Major claim confirmed by reading the cited code + spec lines, and thelibc-0.2.180crate source for portability claims).unameis the cleanest (no Critical/Major) andipcrmnearly so (only argv-order + decimal-key Minors; macOS msg-queue omission is a documented platform limitation). The headline defects are correctness bugs on the golden path:ipcsparses the/proc/sysvipc/*mode field as decimal when the kernel writes it in octal (%4o), so the MODE/permission column is wrong on every Linux run (Critical) — compounded byQBYTESalways-, theS/R/CMODE status flags hard-coded-, and/procread errors silently swallowed (exit 0 on failure); andpsetimemixes time bases — it subtracts the processstart_time(clock-ticks-since-boot on Linux) from the current Unix epoch, so elapsed time is meaningless (Critical, the code admits it's "simplified"), while CPU time hardcodes 100 ticks/s instead ofsysconf(_SC_CLK_TCK), the macOS PID enumeration uses a fixed 1024-entry buffer that silently truncates the process list, and SYNOPSIS options-w/-n+ theCOLUMNSenv var are absent.getconfis current-spec-stale: its-vgate accepts only obsolescentPOSIX_V6_*/POSIX_V7_*and rejects the POSIX.1-2024POSIX_V8_*names (Issue 8 / Defect 1330), and the<limits.h>Maximum/Minimum constants aren't accepted as operands.whoomits the-d<exit>field and the-lliteralLOGINname. Cross-cutting: locale init is wired in all six (setlocale+textdomain+gettext) but no.mocatalogs ship, soLC_MESSAGESis inert;ipcs/whohonorTZincidentally vialocaltime_r,psignoresTZ/LC_TIMEentirely. Refuted (recorded, not actionable): getconf's_SC_PASS_MAX/_PC_FILESIZEBITS"macOS build break" — both are defined for Apple inlibc— ps's-oall-null-header "inverted logic" and-fCMDheader (#P12, correct per spec 112543), and who's extra-operand handling (#W3, clap already exits 2). Totals: 2 Critical, ~12 Major. All findings have since been remediated on thesys-auditbranch across 11 themed phases (one or two utilities each, independently committed with regression tests;build/clippy --all-targets/fmtclean, 151 sys + 71 plib tests green): ipcs MODE octal-parse + 11-char POSIX MODE + QBYTES + facility-not-in-system + error propagation; ps elapsed/CPU time-base normalization (epoch seconds +_SC_CLK_TCK+/proc/stat btime),stime/TZ,-w/COLUMNSwidth,-n,<defunct>, controlling-tty, and the macOS PID-buffer/argv//devfixes; who-d<exit>+-lLOGIN+ LC_TIME + idle clamp; getconfPOSIX_V8_*+<limits.h>LONG_BIT/WORD_BIT+ NPROCESSORS/option sysconf +POSIX2_SYMLINKS+ verbatim confstr; ipcrm argv-order + full key range; and uname's directlibc::uname()(dropping the unmaintained crate). macOS-only changes arecargo check/clippy --target x86_64-apple-darwinclean (runtime macOS verification pending CI). Dispositioned WON'T-FIX/deferred:_CS_POSIX_V8_*confstr + pure-header limit macros (not inlibc), macOS SysV message queues (#IR3), and crate-wide.mocatalogs (tree-wide i18n, as indev/). All six utilities promoted to README Stage 6 — Audited. -
screen/audit.md—stty,tabs,tput(the terminal-screen crate; three utilities plus stty-privateosdata.rstermios tables; static spec-vs-code against the sliced POSIX.1-2024 tree, with every Critical/Major claim behaviorally confirmed by running the release binaries — apty.fork()harness exercised the TTY-onlysttyset-mode paths).tputis the cleanest (exactclear/init/resetoperand set, full 0/2/3/4/>4 exit ladder, continue-past-unavailable) andtabsis solid (full XSI preset set,-0..-9,n[[sep[+]n]...]operand with+Nincrements + strict-ascending validation, gettext diagnostics). Butstty's set path — its primary job — is severely broken:stty <single mode operand>(stty sane/stty raw/stty cs8) panics (assert!(args.operands.len() > 1)atstty.rs:642, exit 101, PTY-confirmed), and every negation operand (-echo,-icanon, …) is rejected by clap as an unknown option because the positional lacksallow_hyphen_values— so mode-setting only works with 2+ positive operands. Majorsttygaps: single-character control-char assignment (stty erase x) is unsupported (only^c/^-/undef); the Issue-8rows/cols/sizewindow-size operands are entirely absent; and the speed table mis-keysB50as"54"(sostty 50fails,stty 54mis-programs).sttycorrectly uses standard input for get/set (the security RATIONALE) and its-a/-g/short displays conform; diagnostics are hardcoded English (vs gettext intabs/tput).sttyships zero executable tests (TTY excuse). Headline counts: 2 Critical + 4 Major (stty), 1 Major (tabs), 0 Critical/Major (tput). All findings have since been remediated on thescreen-auditbranch across 5 themed phases: stty's set path (single-operand panic +allow_hyphen_valuesnegation), single-char control-char assignment,rows/cols/sizewindow-size operands, the"50"speed-key fix + cfg-gated higher bauds, locale-faithful control-char rendering +gettext/stty:-prefixed diagnostics, and the-a/-g+operands guard; tabs' default-terminal fallback, terminal-width-derived cap + beyond-width rejection, leading-+rejection, and non-terminal-stdout guard; and tput'sif/rffile-contents emission +iprogexecution, reset→init fallback, and valid-before-invalid operand ordering. A newportable-pty-backed integration harness brings stty from zero tests to a full suite (8 unit + PTY regressions); full workspacebuild/clippy --all-targets/fmtclean, 46 screen tests green. All three utilities promoted to README Stage 6 — Audited. -
sccs/audit.md—admin,delta,get,prs,rmdel,sact,sccs(front-end),unget,val,what(the full POSIX SCCS family; ten utilities plus the sharedplib::sccsfilefile-format core, all behaviorally verified against GNU CSSC 1.4.1 in both interop directions). The shared core (checksum, SID, delta-table, body weave, p-file) was already byte-interoperable with CSSC; defects were mostly CLI-layer. Original headline risks:getemitted CSSC encoded/binary (e-flag) bodies un-decoded (uuencoded garbage) andwhataborted on the first non-UTF-8 file (every binary — its core use case);rmdelnever reweaved the body (orphan^AI/^AEblock left behind) and gated removal on a spoofable$LOGNAMEcompare; thesccsfront-end's-r(run-as-real-user) was a parsed-then-ignored no-op and it spawned siblings by bare name;prsemitted no trailing newline per delta (default output corrupted) and dumped RustDebugfor:FL:;admin -i/-t/-yate the following operand;deltawas missing-m/-g/the stdin-comment path and thev-flag MR check;valcould not produce its 0x80/0x40 exit bits. Cross-cutting:-/directory operands missing in get/delta/admin,$LOGNAMEinstead ofgetpwuid,TZ-blind timestamps, theNo id keywordswarning absent, no z-file locking, hardcoded-English diagnostics. All findings have since been remediated (14 phases): a shared-core foundation (real_login_name/TZ-awarenow(),remove_deltareweave,uudecode_sccs/uuencode_sccs,prs_fl_line,expand_operands, aZLockRAII lock + SIGINT cleanup) plus per-utility fixes, each behaviorally re-verified byte-for-byte against CSSC. All ten utilities promoted to README "Stage 6 — Audited"; the handful of remaining Minor items are documented WON'T-FIX/N-A (BSDsccs -p, permissivedelta -r,:KV:extension, p-file 0644, etc.). -
sh/audit.md—sh(the POSIX shell command language in full: §2 Shell Command Language incl. §2.15 special built-ins, theshutility page, and all 16 regular built-ins; the most exhaustive audit to date, behaviorally verified againstdashandbash --posix). The shell is broad and feature-complete, but behavioral testing found 7 Critical defects — five process-aborting panics and two silent-wrong-result bugs on common paths:casepattern matching is unanchored (case ab in a)matches → wrong branch);read -r x ypanics;$((1/0))/$((5%0))panic; a missing script-file operand panics instead of exiting 127; a[]]bracket pattern panics; andset -uis inert (unset vars expand to empty, status 0). ~30 Major gaps cluster in unimplemented POSIX.1-2024 additions ($'…',;&,set -o pipefail,{varname}<), arithmetic edge cases (no unary chaining/comma op; div-by-zero panics), error/exit semantics (returnignores$?,commandreturns 1 not 127, signal status off-by-one, special-builtin expansion errors don't abort),break/continueescaping function boundaries, symbolicumask, glob skipping symlinks, non-re-inputtable-p/list output quoting, and theENV/MAIL*startup machinery. i18n is initialized but diagnostics are hardcoded English. Behavioral verification refuted several agent-proposed findings (hash-store,kill -lSIGKILL,exec N>filepersistence,read x ywithout options, literal-.glob, release-build arithmetic overflow/shift/0xpanics). All findings have since been remediated across 11 themed phases: 54 of 59 numbered items fixed (every Critical and every Major), each behaviorally re-verified vsdash/bash --posixand covered by atests::audit_regressionsmodule — the panics,caseanchoring,set -u, the POSIX.1-2024 additions ($'…'/;&/set -o pipefail/{varname}<partly), arithmetic edge cases, exit/error semantics,break/continuescoping, symbolicumask, glob symlinks, re-inputtable-poutput,ENV/MAIL*startup, the vi-mode internals, and a gettext pass over the diagnostic surface. The 5 remaining items (#33 async signal/stdin, #48 bg/fg strictness, #51 read PS2, #54 dot-readable message, #57 IO_LOCATION) are documented WON'T-FIX/deferred with zero-or-minimal runtime impact; #56's interpolated-message gettext wrapping is a documented zero-effect residual.shis promoted to README Stage 6 — Audited (253 unit + 178 integration tests green, clippy clean, fmt clean). -
tree/audit.md—cp,mv,rmonly (a partialtree/audit), plus theftw/race-free traversal dependency — these data-destroying utilities are the canonical TOCTOU/symlink-swap targets, so the audit adds an explicit filesystem-race / security-hardening lens on top of POSIX conformance. Static spec-vs-code + grep proofs + behavioral spot-checks vs GNU coreutils (release binaries; baseline tree 143 passed / 9 root-ignored, ftw 8 passed). The recursive interior of all three is correctly built on ftw's dir-fd model (unlinkat/openat/mkdirat/symlinkatrelative to a pinned parent fd; ancestor path-swaps provably defeated), but three Critical issues cut across the family: (#F1) ftw's directory-descentopenatuses bareO_RDONLYwith noO_NOFOLLOW/O_DIRECTORYand no post-opendev/inore-verification, leaving the historically-exploited leaf symlink-swap window — under an adversarial rename it turnsrm -rinto an arbitrary-directory-deletion primitive (coreutilsftsguards exactly this); and (#C1/#M1) the sharedcopy_characteristicsre-applies the source'sS_ISUID/S_ISGIDviafchmodateven when thechownto duplicate ownership failed — the privilege leak POSIX 90720-90721 / 108104-108105 forbids (behaviorally:cp -p /usr/bin/passwd→ mode4755owned by the caller; GNU clears it). Major band:cp a b c/mv a b cwith a non-directory final operand silently process only the first source (mv removes it) and exit 0 instead of erroring (90605-90606);cpaborts the whole hierarchy on the first per-file error instead of continuing with same-level siblings (90829-90832); andrmis missing two POSIX.1-2024-mandated options —-d(remove empty dir, Austin Group Defect 802) and-v(verbose, Defects 1154/1365/1487), both rejected as unknown arguments. Minors: severalpanic!/unreachable!()/.unwrap()abort sites in ftw (getrlimit,DeferredDirreopen, unknownS_IFMT) and rm; symlink-cycle detection only on ftw's deferred slow path; the top-level single-filermpath and mv/cp target probes are path-based (not dir-fd-relative); hardcodedyaffirmative (noLC_MESSAGESyesexpr);prompt_userread_line().unwrap(). CONFORMS: prompts→stderr, default symlink semantics, mv same-fs atomicrename+ CONSEQUENCES-OF-ERRORS guarantee, mv same-file/hard-link/dir-mismatch steps, rm dot/dotdot//guards + no-symlink-follow + arbitrary-depth/fd-budget. All findings have since been remediated (8 phases on the audit branch): #F1 (ftw descent nowO_NOFOLLOW/O_DIRECTORY+(dev,ino)re-verification, with a deterministicftw/tests/race.rsregression), #C1/#M1 (sharedcopy_characteristicsmasks setuid/setgid whenchownfails), #C2/#M2 (multi-operand non-dir target errors), #C3 (cp continue-on-error + mv characteristics exit-status), #R1/#R2 (rm-d/-vadded), and the panic/yesexpr/errno/symlink-cleanup minors (newplib::locale::is_affirmative); #C4/#C5/#C6 are documented WON'T-FIX. Each phase is independently committed with regression tests; clippy/fmt clean.cp,mv,rmpromoted to README Stage 6 — Audited. Residuals documented: the rare fd-conserving ftwDeferredDirpath lacks a(dev,ino)baseline (fails closed viaO_NOFOLLOW) and #F3's deep-tree reopen still panics on a mid-walk race. -
users/audit.md—id,logname,logger,mesg,newgrp,pwd,tty,write,talk, plus thetalkddaemon (the user/terminal crate; nine POSIX utilities + one implicitly-required daemon —talkdaudited under the project'scrondpolicy: not POSIX-specified, but required by POSIXtalk, so judged againsttalk's implicit requirements + the BSDntalkprotocol + secure-daemon practice). Static spec-vs-code against the sliced POSIX.1-2024 tree, every Critical/Major claim confirmed by reading the cited code and spec lines (andplib/src/curuser.rsfor the shared helpers). Totals: 15 Critical, 26 Major. Four cross-cutting themes: exit-status ladders are ignored (mesgalways exits 0 vs the spec's 0/1/>1 messaging-state ladder;talkexits 130 on SIGINT where the spec mandates 0;lognamenever fails even with no login name); the sharedplib::curuserhelpers diverge (login_name()falls back to$USERthen"unknown"and never fails —lognameinherits this;tty()searches stdin→stdout→stderr wherettymust report stdin only);setlocaleis wired everywhere but runtime diagnostics are hardcoded English (LC_MESSAGESinert); and the security/correctness-critical utilities (newgrp,mesg,pwd,logname,talkd's wire path) have zero tests. Headline defects:newgrpis fundamentally broken — in-lmode it execs the login shell with the old GID before any group change (blockingstatus()atset_login_environment), in normal mode it never creates a shell at all, the mandatory-but-should-be-optionalgroupoperand makes "no operand = restore login groups" unreachable, and group-password verification is gshadow/Linux-only with a weak empty-string compare;writeroutes the typed alert and erase/kill output to the sender's own stdout instead of the recipient's terminal and panics (.expect) on a closed recipient tty;talkwrites its UI/echo to stderr, sets raw mode in a thread-local scope that isn't restored on most exit paths, ignoresAnswer::PermissionDenied/NotHere, and never checks stdout-is-a-terminal;talkd'sANNOUNCEis a self-admitted stub that never writes to the recipient tty (the daemon's entire purpose), validates no callee/mesg/privilege, binds a Unix socket not UDP port 518 (no interop), and keeps an unbounded invitation table (DoS);loggerimplements none of the-i/-f/-p/-toptions or stdin reading and defaults touser.errnotuser.notice;id -Gcan omit a distinct effective GID;pwd -Pis a dead flag (no last-one-wins). All findings have since been remediated on theusers-auditbranch across 12 themed, independently-committed phases (build +clippy --all-targets+fmtclean, tests green per phase). A shared foundation landed first —plib::curuser::{login_name_strict, ttyname_of}, a newplib::exec::exec_error_exit(POSIX 126/127), a portedportable-ptyintegration harness (users/tests/common), and a crate-wide migration toplib::diag+gettext. Highlights:newgrpwas rewritten toexeca new shell in both modes with the invoke-anyway guarantee, no-operand login-group restore, and fail-closed gshadow+group-DB password verification with a kept privilege-drop (the audit's "removesetuid" note was refuted as a security regression);writewas rebuilt around the spec's canonical-input model (per-character rendering, alert→recipient, superuser override, no panic paths, SIGHUP/SIGPIPE,/devchar-device validation);mesgnow honors the 0/1/>1 exit ladder (the audit's #MG3 "before the command" framing was refuted by behavioral check against the systemmesg);loggergained-i/-f/-p/-t+ stdin bodies + theuser.noticedefault;id-Gemits the full {gid,egid}∪getgroups() union;pwdimplements-L/-Plast-wins;ttyreports stdin's terminal only;lognameenforces the strictgetlogin()contract; andtalkdbecame a functional hardened local daemon (announce-to-tty with passwd/utmp/mesgvalidation, bounded invitation table, 0600 symlink-safe socket, daemonization,OnceLocksignal path, syslog) with the no-UDP-518 transport documented WON'T-FIX. Eight utilities —id,logname,logger,mesg,newgrp,pwd,tty,write— are promoted to README Stage 6 — Audited.talkis deliberately NOT promoted (stays Stage 3 with its bundledtalkd): its Criticals (#TK1 SIGINT→0, #TK2 stderr-UI, #TK3 terminal-restore) and Majors (#TK5 answer handling, #TK6 stdout check, #TK8 termination) are fixed, but #TK7 (full POSIX character-processing) and Minors #TK9/#TK10/#TK14 are deferred — the thread-heavy full-screen curses/input engine cannot be behaviorally verified in CI, so it was not rewritten blind. Two audit findings were refuted during remediation and recorded inline:mesg#MG3 (exit reflects the resulting state, not the pre-command state) andnewgrp#NG6 (thesetuid(getuid())is the privilege drop, not dead code). -
uucp/audit.md—uucp,uux,uustat(theuucp/crate, audited under the project's "UUCP is dead — functional but absolutely minimal" stance; static spec-vs-code with light behavioral confirmation, no reference UUCP installed). This implementation uses SSH as the transport rather than the legacyg/f/tprotocols +uucicodaemon, so findings are partitioned into POSIX-mandated surface gaps vs accepted architecture divergences. The CLI is already option-minimal (zero non-POSIX flags). No Critical defects. One Major:uuxcross-system output-file routing is an unimplemented TODO, and a null-system (!) output redirect is routed to the execution host instead of local, so POSIXuuxEXAMPLE 3 does not fully work. Minors: hardcoded-English diagnostics (LC_MESSAGESinert),.unwrap()on locale setup, throwaway-jjob IDs (no persistent job for immediate transfers;uuxnever persists one), and$USER-based identity/ownership inuustat -k/-r. Accepted by design (DIVERGES, no action):uucp -rqueues aJ.*record but no daemon ever drains it (so the file never transfers);-c/-Care inert without spool staging; multi-hop routes (a!b!path) are rejected; remote wildcard expansion is unsupported;uuxdiscards un-redirected command stdout. Only non-POSIX extension is theUUCP_SPOOLenv var (kept for tests).shell_escapeis sound and consistently applied to SSH command construction. All actionable findings have since been remediated (5 phases): #UX1 fixed minimal-correct (null-system⇒local +ssh_fetch_file/ssh_send_filedelivery, third remote system a hard error); #G1 diagnostics routed throughgettext(); #G2 locale-setup.unwrap()→.ok(); #G3 real-login identity (getpwuid(getuid())) +getuid()==0root check foruustatownership; #UC1 unified-jjob ID (the-r -jID is the oneuustatlists; immediate-transfer IDs documented informational); #G4 newline-in-destination rejected; #UC2 documented WON'T-FIX (single-quoted remote paths). All three utilities promoted to README "Stage 6 — Audited". -
text/audit.md— the fulltext/crate: 22 utilities (asa,comm,csplit,cut,diff,expand,fold,grep,head,join,nl,paste,patch,pr,sed,sort,tail,tr,tsort,unexpand,uniq,wc), static spec-vs-code against the sliced POSIX.1-2024 tree with every claim grep-verified, one subagent per utility. ~25 Critical, ~60 Major, ~75 Minor across the crate. Headline defects:sortused Rust byte order instead ofstrcoll, concatenated rather than merged under-m, broke-ufor 0/3+ keys, usedf64for-n, and processed only two-kkeys;joinwas an O(N×M) stub with the wrong default reconstruction, single-value-a/-v, panicking-o 0, and byte-equal keys;csplitdropped each split file's trailing newline (corrupting output and the byte count), reset its line counter (breaking absolute line numbers), and never consumed a bare line-number operand;sednever implemented the POSIXlcommand, set the-Eflag after compiling patterns, appendeda/rtext into the pattern space, cleared the hold space onD, and lackeds///i;patchsilently appended a newline to no-newline-at-EOF files and never honored/dev/nulldeletions;diffhad wrong context single-line ranges and a missing unified<frac>/<zone>; the column tools (expand/fold/unexpand) andwc -m/-w/cut -c/trclasses were ASCII-only rather thanLC_CTYPE-aware; and-was honored only as a sole operand across many utilities. All actionable findings have since been remediated on thetext-auditbranch across 18 themed, independently-committed phases (each with regression tests; per-phasebuild/clippy --all-targets/fmt/posixutils-textsuite clean, and every data-affecting change cross-checked byte-for-byte against GNU coreutils 9.4 in C and UTF-8 locales). Foundation:plib::localegainedwcwidth_char+ libc-backed ctype classifiers + anMbDecoder, and a-→stdin sweep routed dashed operands throughplib::io::input_stream_dashed. 20 of 22 utilities are promoted to README "Stage 6 — Audited":asa,comm,cut,diff,expand,fold,grep,head,join,nl,paste,patch,pr,sed,sort,tail,tsort,unexpand,uniq,wc.csplitandtrdeliberately stay at Stage 3:csplithas two open items (#4a SIGINT created-file-cleanup handler,#8erroring when an operand references a line past EOF — its file output is already byte-for-byte GNU-correct, only the exit status differs);tris fully POSIX-conformant in the C/POSIX locale but its multibyte items (-cvs-C,LC_CTYPEcharacter classes,[=equiv=]expansion,LC_COLLATErange order) are documented POSIX-locale limitations requiring a predicate-based class-matching rewrite (the[:upper:]↔[:lower:]case pairing can't be made locale-aware without it). Deferred tree-wide: shipping.mocatalogs, soLC_MESSAGEStext stays English even where diagnostics now route throughplib::diag. -
xform/audit.md—cksum,compress(+uncompress/zcatviaargv[0]),uuencode,uudecode(the data-transformation crate; static spec-vs-code against the sliced POSIX.1-2024 tree, every "absent" claim grep-verified —isatty/is_terminal,chown, newline-in-pathname checks all confirmed absent).cksumis the cleanest (no Critical/Major — its CRC core is a line-for-line transcription of the POSIX model program). The other three each have real defects. Headline risks:uudecodepanics (exit 101) on malformed/binary input (String::from_utf8().unwrap()plus a cluster ofexpect/panic!/index sites), never honors the-magic cookie (Austin Group Defect 1544 — only/dev/stdoutis special-cased), does not "scan…searching for" the begin line (header must be input line 1, so mail-wrapped data aborts), uses a strict Base64 decoder that rejects CRLF/whitespace transport artifacts, and skips the existing-file write-permission check while treating a failedset_permissionsas fatal;uuencodemis-parses the single-operand form (… | uuencode decode_pathname) because the optionalfileoperand is positionally first, so clap binds the lone operand tofileand defaults the decode pathname to/dev/stdout(and the requireddecode_pathnameis unenforced);compressnever checks whether stdin is a terminal before prompting for overwrite (spec: non-terminal + no-f→ diagnostic + exit >0, no prompt), runs its hard-link guard even under-c(which removes nothing), has a suffix-less-file decompress path that can delete the decompressed output (data loss), and its-bLZW validation range (9–14) contradicts the actual default (16). Cross-cutting: locale is initialized everywhere but runtime diagnostics are hardcoded English (LC_MESSAGESinert), and the Austin-Group-251 newline-in-pathname FUTURE DIRECTION is unimplemented. Totals: 1 Critical, 9 Major, 14 Minor. All findings have since been remediated across themed, independently-committed phases (build +clippy --all-targets+fmtclean, tests green); all six utilities promoted to README "Stage 6 — Audited". Seexform/audit.md.
When you finish a new audit, add the link here.