v0.4.1 — security & hardening
Security + hardening release. No tool API changes; one server-side response-header change for unauthenticated requests, plus two new response fields on list_staged_files.
Security
- RFC 6750 bearer challenges on every 401 — the streamable-HTTP endpoint now always returns a
WWW-Authenticate: Bearer ...header on401 Unauthorized. Wrong-token rejections includeerror=\"invalid_token\"per RFC 6750 §3.1 so clients can distinguish bearer rejection from an OAuth-discovery prompt. (#27, #28) transfer_filesource-path allowlist tightened — now restricts to[A-Za-z0-9._-], rejecting NUL bytes, ASCII control chars, shell metacharacters, RTL overrides, and homoglyph scripts that the prior `..` + slash + 255-byte checks missed. (#26 L2, #30)scpstderr scrubbed inScpFailederrors — absolute paths and IPv4 addresses are redacted to `` / `` before reaching the MCP caller. (#26 L1, #31)
Reliability
list_staged_filescapped at 256 entries — caps at `STAGING_DIR_MAX_ENTRIES = 256`, deterministic name-sorted truncation, skips sha256 on excess files. Response gains `staged_files_truncated: bool` and `staged_files_total_found: usize`. (#26 L5, #32)- Per-router serialization for
transfer_file— new `TransferLocks` process-wide map of `Arc<Semaphore(1)>` keyed by router. Different routers proceed in parallel; same router serializes. (#26 L4, #33)
Operability
- Actionable EACCES message on
tokens.json— surfaces file owner uid + mode and running process uid plus a `sudo -u ` / `chown` hint when the daemon can't read the tokens file. README gained a service-user note in the "Mint a token" section. (#22, #23, #29)
Compatibility
- No tool name / argument changes.
- `list_staged_files` response gains two new fields (`staged_files_truncated`, `staged_files_total_found`). Existing fields unchanged.
- `401 Unauthorized` responses now always include `WWW-Authenticate: Bearer ...`. Clients that ignore this header are unaffected.
See CHANGELOG.md for the full entry.