Skip to content

v0.2.5

Choose a tag to compare

@het0814 het0814 released this 06 Jul 15:19
· 452 commits to main since this release
5121fff

Release Notes for v0.2.5

This release is a major security hardening pass across the API, CLI, and Web UI: path-traversal fixes wherever agent_id/session_id/dates flow into filesystem paths, a CORS credential-exposure fix, localhost-only gating for destructive UI endpoints, unpredictable session-secret generation, stricter session-token validation, and a large cleanup that collapses the legacy scope/namespace model down to a single agent_id.

Security

  • Path traversal via agent_id / session_id / dates (memanto/app/utils/validation.py,
    memanto/app/services/{session_service,memory_export_service,daily_analysis_service}.py)

    • Unsanitized agent_id/session_id values were concatenated directly into
      pathlib.Path expressions (e.g. sessions_dir / f"{agent_id}.json"),
      letting a caller escape the storage directory with input like
      "../../etc/passwd". All filesystem call-sites now run through
      validate_safe_id().
    • Extended the same guard to memory_export_service, daily_analysis_service
      (including the date parameter used in glob patterns and JSON output paths),
      and the --output-path CLI flag (anchored to a base dir via relative_to()
      containment checks).
  • CORS reflected-origin credential exposure (memanto/app/main.py)

    • Default ALLOWED_ORIGINS=["*"] combined with allow_credentials=True
      caused Starlette to mirror any request Origin back in
      Access-Control-Allow-Origin while also sending
      Access-Control-Allow-Credentials: true — letting any website make
      credentialed cross-origin requests to the Memanto API. Fixed to stop
      mirroring arbitrary origins when credentials are allowed.
  • Sensitive Web UI endpoints gated to localhost-only (memanto/app/ui/routes/ui_router.py)

    • POST /api/ui/shutdown, GET /api/ui/browse, PATCH /api/ui/config,
      PUT /api/ui/api-key, POST /api/ui/onprem/restart, plus the
      connections and migrate endpoints, were reachable from any network host
      with no authentication (remote DoS, arbitrary file listing, config/API-key
      overwrite). Added a _require_local() dependency that returns 403 for any
      caller that isn't 127.0.0.1/::1 (including IPv4-mapped IPv6 loopback),
      and blocked glob-pattern injection in the browse endpoint.
  • Unpredictable session secret (memanto/app/config.py, memanto/app/services/session_service.py)

    • Removed the hardcoded default JWT signing secret
      ("memanto-default-secret-change-in-production"). When
      MEMANTO_SECRET_KEY isn't set, a per-instance random secret is now
      generated (secrets.token_hex(32)) and persisted locally instead of
      falling back to a publicly-known constant.
  • Session token lifecycle hardening (memanto/app/services/session_service.py,
    memanto/app/routes/memory.py, memanto/cli/client/{direct_client,sdk_client}.py)

    • Deactivated/terminated session tokens are now rejected outright (401)
      instead of continuing to authorize writes.
    • Cross-agent session/agent mismatches now consistently raise
      AuthorizationError → HTTP 403 (was a generic 500) across all
      session-scoped endpoints.
    • CLI clients now validate cached sessions before reuse instead of trusting
      a stale cached token.
    • TypeScript SDK resets its local session state after deleteAgent().

Improvements

  • Legacy scope model collapsed to agent_id (memanto/app/core.py,
    memanto/app/models/__init__.py, memanto/app/constants.py,
    memanto/app/services/*.py)

    • Removed the scope_type/scope_id pair (and the underlying
      MemoryScope/namespace-parsing machinery) in favor of a single agent_id
      field; namespaces are now built by one free function
      (agent_namespace(agent_id)). Dead code from this and prior cleanups moved
      to memanto/app/legacy/ (excluded from CI lint/type-check).
    • Removed orphaned "trust" fields that were never populated by any live
      write/read path (superseded_by, validation_count,
      contradiction_detected, etc.) and the unused ValidationPolicy class.
  • Confidence filtering bug fix (memanto/app/services/memory_read_service.py)

    • Numeric min_confidence filtering in memory search previously relied on
      Moorcheh keyword syntax that never matched; it's now applied as a
      post-filter on the numeric confidence field, fixing a zero-threshold
      edge case that silently returned nothing.
  • Manual conflict resolution validation (memanto/app/models/__init__.py)

    • ConflictResolveRequest now requires non-empty manual_content when
      action == "manual", both on the API and in the UI (blank submissions show
      a warning toast and refocus the textarea).
  • Timestamp normalization (memanto/app/utils/temporal_helpers.py)

    • Parsed ISO timestamps are now consistently normalized to UTC, whether the
      input has an explicit offset or is naive.
  • CLI: honor custom title for short memories (memanto/cli/commands/memory.py)

    • memanto remember no longer overrides an explicit --title with an
      auto-truncated content snippet when the memory content is short.
  • Memory deletion response handling (memanto/app/services/memory_write_service.py)

    • Tightened success/failure detection for memory deletion and update-then-delete
      flows so partial or malformed backend responses aren't reported as success.
  • TypeScript SDK & CI — updated dependencies, CI workflow permissions,
    regenerated openapi.json, and added an npm publishing workflow
    (.github/workflows/publish.yml).

Tests

  • New tests/test_cors_fix.py, tests/test_output_path_traversal.py,
    tests/test_ui_auth.py, tests/test_remaining_ui_auth.py covering the CORS,
    path-traversal, and localhost-gating fixes.
  • New tests/test_memory_read_confidence.py and tests/test_temporal_helpers.py.
  • Expanded tests/test_api.py, tests/test_cli.py, tests/test_unit.py for
    session-secret generation, inactive-token rejection, and deletion handling.

Full Changelog

Full Changelog: v0.2.4...v0.2.5