Skip to content

The config API mutates one process and rewrites the whole configuration file with secrets in plaintext #1752

Description

@edwinyyyu

What happened

With MEMMACHINE_CONFIG_API or --with-config-api (server/app.py), the PUT routes and the resource POST and DELETE routes in server/api_v2/config_router.py call ConfigService methods that edit the process's own Configuration object in place and then _persist_config() (server/api_v2/config_service.py:394-400; called from add_embedder, add_language_model, remove_embedder, remove_language_model, update_memory_config, update_episodic_memory_config, update_long_term_memory_config, update_short_term_memory_config and update_semantic_memory_config). Configuration.save (common/configuration/__init__.py, write_text at :619) re-serializes every section with to_yaml and overwrites the file the process was loaded from.

Consequences:

  • Only the replica that handled the request changes. The others keep the old values, so a new session's episodic defaults depend on which replica serves POST /projects (create_session merges the process's episodic_memory configuration).
  • Each worker writes the file from its own in-memory copy, so one worker's write reverts another's change. The Helm chart mounts the file from a ConfigMap subPath (deployments/helm/templates/memmachine-deployment.yaml:101), which Kubernetes mounts read-only, so the write fails with a logged warning and the change is lost on restart; docker-compose mounts it read-write (docker-compose.yml:136).
  • to_yaml unwraps every SecretStr (common/configuration/mixin_confs.py:207), and environment references such as api_key: $OPENAI_API_KEY were resolved at load (:66), so the rewritten file contains the literal secrets and loses the references, along with comments and key order.

Expected

Runtime configuration either lives in the database and is read per request by every replica, or the API is documented as single-process and stays off by default. In no case should a save replace environment references with resolved secrets.

Notes

Code read at d6068cdbf (main), paths under packages/server/src/memmachine_server/. The API is opt-in; recorded because MEMMACHINE_WORKERS already makes the per-process mutation observable on one host.


🤖 Written by Claude Code (Claude Fable 5.1) on behalf of @edwinyyyu.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    horizontal scalingWrong or unsafe when more than one server process serves the same backends (replicas or workers)securitySecurity-related tasks that come from private reports, code scanning, and vulnerability checks.

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions