Skip to content

0.1.0a9

Pre-release
Pre-release

Choose a tag to compare

@spiderings spiderings released this 30 Jul 14:55
· 72 commits to dev since this release
11cee82

Release 0.1.0a9 — security/privacy hardening sweep across all six plugins, aggregating #71, #74, #75, #76, #77.

Breaking changes

  • The gateway ENC:v3 command/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-se no longer accepts --unattended (#76): the authorization policy is chosen at key generation, not helper install. Use MORDRED_SEKEY_UNATTENDED=1 on 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_io primitives (O_NOFOLLOW/O_NONBLOCK opens, inode-stability checks, sidecar flock, no-follow gzip rotation); cross-process serialized whole-entry appends with truncate rollback; audit purge/decrypt bind an O_NOFOLLOW directory descriptor and purge requires --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, …); new auxiliary_guard covers Hermes 0.19's auxiliary client resolvers that never emit pre_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.json validated, locked, atomically written.
  • Keyvault (#76): profile-scoped native wrapping-key ids (two HERMES_HOME profiles can no longer collide in the machine-global native store); keyvault_lock gains an out-of-tree lifecycle lock, fork-safe descriptors, and reentrancy; export_backup verifies the passphrase before opening any envelope; import_backup requires a fresh destination and rolls back only what it created; .env/config.yaml reseal 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 (SubprocessRunner is a Protocol); 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 Exception hook 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_url now 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 configure silently forced strict mode forever (#76): a stranded policy-write transaction marker now surfaces in status/policy show with 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 status reports audit-log encryption state.
  • Tor liveness (#74, #75): two-stage circuit-status probe — a BUILT circuit is healthy on its own; empty/in-progress replies resolve via GETINFO 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; webauthn registered 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; sign approval requires a literal boolean true (the JSON string "false" no longer crosses the approval boundary); fee_data falls back on HTTP-level method rejection too.
  • Keyvault portability (#75): fcntl guarded so the extension stack imports off POSIX (with POSIX re-raise); O_NOFOLLOW and parent-dir fsync made portable.
  • Misc (#76): BIP39 mnemonics canonicalized before validation; mullvad status/lockdown-mode parsing requires exact tokens and never conflates query failure with OFF; policy=off restores the pre-runtime proxy environment; workspace purge no longer refuses on a stray .DS_Store; E2E replay capacity exhaustion reports recovery; provider_overrides preserved through configure/upgrade/OpenClaw migration (#71); broken pairing installs present as exit-2 ExtensionGatewayUnavailable instead of a raw traceback (#75).