0.1.0a9
Pre-release
Pre-release
Release 0.1.0a9 — security/privacy hardening sweep across all six plugins, aggregating #71, #74, #75, #76, #77.
Breaking changes
- The gateway
ENC:v3command/reply wire (#71): a v3-capable external Mordred Extension must be deployed together with this version. Legacy v1/v2 helpers remain for the WebSocket API/history paths only.keyvault enable-seno longer accepts--unattended(#76): the authorization policy is chosen at key generation, not helper install. UseMORDRED_SEKEY_UNATTENDED=1on init/recovery instead; scripts passing the old flag now exit 2.
Changes
- Audit/privacy (#71, #76): process-wide, encryption-aware, conflict-safe audit writer; shared
_audit_ioprimitives (O_NOFOLLOW/O_NONBLOCKopens, inode-stability checks, sidecarflock, no-follow gzip rotation); cross-process serialized whole-entry appends with truncate rollback;audit purge/decryptbind anO_NOFOLLOWdirectory descriptor andpurgerequires--yes. - Policy enforcement (#71, #76): strict provider/network policy enforced against the effective runtime request (repeated gateway calls, exact loopback local-LLM endpoints, verified Tor/provider transport); strict mode binds cloud routes to provider-owned endpoints including ambient SDK overrides (
ANTHROPIC_BASE_URL,OPENAI_BASE_URL, …); newauxiliary_guardcovers Hermes 0.19's auxiliary client resolvers that never emitpre_api_request; sibling-disable integrity checks registered from every runtime Mordred plugin. - Extension/gateway (#71, #74, #75, #76): context-bound gateway E2E v3 (direction/platform/channel/thread AAD, channel-key binding, persistent replay protection, single-token grammar, Slack
:lock:normalization, multiplex profile routing, Discord auto-thread canonicalization); hardened Host/Origin/token/WebAuthn lifecycle checks with stale pairing-generation revocation; WebAuthn split from pairing state with lazy extension submodules (pairing/help paths work without aiohttp); pairing commit ordered against CLI cancellation under one state lock; JSON-RPC responses bounded (2 MiB) and envelope-validated;wallet.jsonvalidated, locked, atomically written. - Keyvault (#76): profile-scoped native wrapping-key ids (two
HERMES_HOMEprofiles can no longer collide in the machine-global native store);keyvault_lockgains an out-of-tree lifecycle lock, fork-safe descriptors, and reentrancy;export_backupverifies the passphrase before opening any envelope;import_backuprequires a fresh destination and rolls back only what it created;.env/config.yamlreseal captures the live inode atomically; native helper installers stage/verify before atomic rename. - Network (#74, #75, #76): centralized provider resolution and network-setting validation across registration, hooks, and wizard; every network-path subprocess runs under an explicit timeout (
SubprocessRunneris aProtocol); Tor picks an adjacent free (SOCKS, ControlPort) pair; process-global Tor/VPN routing kept alive across Hermes turns and concurrent gateway sessions. - Runtime integrity (#74): new
MordredIntegrityRefused(BaseException)policy signal so Hermes'except Exceptionhook wrapper cannot swallow strict refusals (stderr-printed before raising, #75). - Release/CI (#71): pinned GitHub Actions, restored CI/release gates, artifact validation, declared direct runtime dependencies (incl. PySocks).
- Version (#77): bump to 0.1.0a9 across all pinned surfaces.
Fixes
- Strict mode refused every allow-listed cloud provider on its SDK-default endpoint (#76): absent
base_urlnow means "the vendor default" and is accepted when the provider owns one; tenant/region-scoped providers (azure-foundry,bedrock,vertex) still fail closed. - An interrupted
configuresilently forced strict mode forever (#76): a stranded policy-write transaction marker now surfaces instatus/policy showwith the remedy. - A stranded audit wrapping key left the audit log permanently plaintext (#76): provisioning now discards the untrusted key so the next attempt succeeds, and
statusreports audit-log encryption state. - Tor liveness (#74, #75): two-stage circuit-status probe — a
BUILTcircuit is healthy on its own; empty/in-progress replies resolve viaGETINFO network-liveness— so idle Tor sessions are no longer sticky-dropped and a running-but-circuit-less Tor is still detected; bootstrap reader now works on Windows (thread+queue instead of selectors-on-pipe). - WebAuthn (#74, #75): registration keys validated as DER EC P-256 before persistence with byte-for-byte preservation of the prior credential on rejection;
webauthnregistered in the lazy-import registry with pre-split patch seams mirrored. - Wallet (#71, #76): transactions canonicalized and validated before approval, then only the exact approved representation is signed;
signapproval requires a literal booleantrue(the JSON string"false"no longer crosses the approval boundary);fee_datafalls back on HTTP-level method rejection too. - Keyvault portability (#75):
fcntlguarded so the extension stack imports off POSIX (with POSIX re-raise);O_NOFOLLOWand parent-dir fsync made portable. - Misc (#76): BIP39 mnemonics canonicalized before validation;
mullvad status/lockdown-modeparsing requires exact tokens and never conflates query failure with OFF;policy=offrestores the pre-runtime proxy environment;workspace purgeno longer refuses on a stray.DS_Store; E2E replay capacity exhaustion reports recovery;provider_overridespreserved through configure/upgrade/OpenClaw migration (#71); broken pairing installs present as exit-2ExtensionGatewayUnavailableinstead of a raw traceback (#75).