github manuelschipper/nah v0.6.3

14 hours ago

Added

  • Wildcard support in classify entries — classify entries now accept a trailing * wildcard on the last token. mcp__github* matches every tool under the github MCP server, letting one line cover a whole MCP server instead of enumerating each tool. Exact entries always beat wildcard entries at equal prefix length, so a specific override still wins over a server-wide rule. Invalid patterns (leading *, mid-string *, bare *, multi-*) are rejected at nah classify write time and skipped with a stderr warning if they appear in hand-edited YAML. FD-024 semantics — implicit prefix matching remains forbidden, wildcards must be written explicitly — are preserved. Requested in #76 (nah-875)

Fixed

  • Atomic config writes_write_config in src/nah/remember.py now writes to a sibling temp file and os.replaces it over the target. Previously it called open(path, "w") which truncates the file to zero bytes before writing; concurrent Claude Code sessions calling _read_config during that window could observe an empty file, parse it as {}, and later persist a single rule as the whole config — a full config wipe was reported in production. The fix resolves symlinks on the target (preserving dotfile-managed links), preserves the file's existing mode (or defaults to 0o644), writes with explicit UTF-8 encoding, fsyncs the tempfile before rename, and fsyncs the parent directory on POSIX as a durability hedge. All six _write_config call sites (write_action, write_classify, write_trust_host, write_allow_path, etc.) inherit the fix without modification. Lost-update races where two writers both persist stale state are explicitly deferred — that requires advisory file locking. Reported by @0reo (#66, nah-876)
  • Intra-chain $VAR expansion before sensitive-path checks — Bash classification now propagates literal env assignments across && / || / ; stages and expands $NAME / ${NAME} in later consumer tokens, so BAD=/etc/shadow && cat "$BAD" blocks where it previously allowed. Pipe | clears the var map (subshell boundary); unsafe RHS values ($, backticks, command substitution) are never propagated; the executed command string is never mutated. Covers bare and export NAME=value assignment forms. Bypass identified by srgvg (#74, nah-874)

Don't miss a new nah release

NewReleases is sending notifications on new releases.