v0.2.5

bytebot-ai/bytebotv0.2.5Jul 6, 2026by het0814

AI Summary

A major security hardening pass that fixes path traversal vulnerabilities and simplifies the application's scope model.

Key Highlights

  • Fixed path traversal vulnerabilities in `agent_id` and `session_id` handling.
  • Fixed CORS reflected-origin credential exposure.
  • Gated destructive UI endpoints to localhost-only access.
  • Removed hardcoded JWT secret in favor of random generation.
  • Collapsed legacy scope/namespace model to a single `agent_id` field.

Breaking Changes

  • Collapsed legacy scope/namespace model to a single agent_id field

New Features

  • Random session secret generation
  • Localhost-only gating for UI endpoints
  • CORS credential exposure fix

Full Release Notes

# 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: https://github.com/moorcheh-ai/memanto/compare/v0.2.4...v0.2.5