Security Hardening
Memory Service is often placed behind agent applications and identity infrastructure. Treat the service as a sensitive data plane: it stores conversation content, attachment bytes, index material, and administrative metadata. This page is an operational checklist for deploying and maintaining that data plane.
Baseline Runtime
- Run the container as non-root. The published image uses UID/GID
10001. - Use a read-only root filesystem and mount only the paths that must be writable.
- Mount
MEMORY_SERVICE_TEMP_DIRon a writable volume such as/var/lib/memory-service/tmp. - Drop Linux capabilities and set
allowPrivilegeEscalation: false. - Disable Kubernetes service-account token mounting unless the pod explicitly needs the Kubernetes API.
- Pin deployment images by immutable version or digest in production. The repository Kustomize
examples keep deployment images paired with
@sha256:digests, and Compose pins pulled third-party images while using non-latestlocal tags for services it builds locally.
Secrets
- Generate unique values per environment for database passwords, API keys, OIDC client secrets, attachment store credentials, and encryption keys. Attachment download signing keys are derived from the configured encryption provider material; do not configure a separate attachment signing secret.
- Use
dek,kms, orvaultas the primary encryption provider for production data.MEMORY_SERVICE_ENCRYPTION_ALLOW_PLAIN=trueis an explicit unsafe opt-in. - Store production secrets in a secret manager or Kubernetes
Secretmanaged by your deployment system. - Rotate any value that was checked into source control, printed in logs, or shared in a support bundle.
Network Exposure
- Treat the repository
compose.yamlas local-development infrastructure, not as a production network boundary. - Keep Prometheus, Grafana, databases, object storage consoles, and management endpoints off the public gateway.
- Put browser-facing traffic behind TLS and configure
MEMORY_SERVICE_BASE_URLto the externally reachable HTTPS origin. - Choose one transport per TCP listener outside testing mode: either disable plaintext when
Memory Service terminates TLS, or disable in-process TLS when plaintext is restricted to an
internal listener behind a TLS terminator. Set
MEMORY_SERVICE_ALLOW_NON_LOOPBACK_PLAINTEXT=trueonly for the latter deployment boundary. - Keep request body deadlines enabled. Ordinary REST request bodies default to
30s; multipart attachment uploads default to5m. - Configure forwarded client-IP trust with
MEMORY_SERVICE_TRUSTED_PROXY_CIDRS. The resolved client IP keys pre-authentication source and authentication-failure rate limits. Trusting spoofable forwarded addresses lets callers evade those limits by changing their reported IP; failing to trust the actual proxy makes its clients share one rate-limit bucket. Leave the setting unset to trust no proxies. Universal ranges (0.0.0.0/0,::/0) intentionally accept forwarded client IPs from every peer and are appropriate only when direct callers choosing their reported IP is acceptable or a network boundary forces traffic through a controlled proxy. - Configure
MEMORY_SERVICE_MANAGEMENT_PORTorMEMORY_SERVICE_MANAGEMENT_UNIX_SOCKEToutside testing mode. UseMEMORY_SERVICE_MANAGEMENT_ON_MAIN_LISTENER=trueonly when the main listener is already inside an appropriate internal network boundary. UseMEMORY_SERVICE_MANAGEMENT_ALLOW_NON_LOOPBACK=trueonly with network policy or firewall rules that keep unauthenticated health and metrics endpoints internal.
Authentication
- Require OIDC audience checks for production issuers.
- Keep API-key clients scoped to the least privilege required by each agent or processor.
- Disable wildcard credentialed CORS; list exact browser origins.
- Keep admin APIs on a separate network path when possible.
- Keep
MEMORY_SERVICE_DEVELOPER_FRONTEND_AUTH_MODE=oidcin production. Theapi-keymode exposes its admin credential to browsers through/developer/config.jsonand is only intended for isolated local development.
Trusted User Assertion
- Treat
MEMORY_SERVICE_TRUSTED_USER_ID_CLIENTSas a security boundary. Use exact client IDs and trust only agent applications that authenticate end users before settingX-User-IDor gRPCx-user-idmetadata. - Keep assertion trust separate from
MEMORY_SERVICE_ROLES_ADMIN_CLIENTS, auditor roles, and indexer roles. Trusting a client to select a user must not grant administrative access. - Require a valid API key or OIDC token on every asserted request.
X-User-IDis identity context, not a credential. - Strip public callers’ inbound
X-User-IDat gateways unless they are intended to control the asserted identity. Memory Service’s trusted-client check remains mandatory even behind a gateway. - Protect API keys as secrets and rotate them independently of the trusted-client allowlist. Removing a client from the allowlist should stop delegation without invalidating its other authorized client operations.
- Preserve both the authenticated client identity and effective user in security logs, but never log bearer tokens or API keys.
- Attach user metadata per request or per derived gRPC stub. Do not mutate a shared client stub or global header map where concurrent users could leak identity into one another’s calls.
- Verify that admin and system APIs ignore asserted-user metadata and that assertions from untrusted clients behave exactly like absent metadata.
Rate Limits and Diagnostics
- Preserve
X-Request-IDthrough ingress and gateway layers and include it in support workflows. REST error bodies include the samerequestId; gRPC returnsx-request-idmetadata. - Keep local process rate limits enabled unless an ingress or gateway limiter already covers
the same boundary.
MEMORY_SERVICE_RATE_LIMIT_MODE=offis an explicit unsafe opt-out and exportsmemory_service_security_unsafe_config{reason="rate_limits_off"} 1. - Treat local limits as per-replica protection. In multi-replica deployments, enforce cluster-wide quotas at the ingress, gateway, or service mesh.
Attachments
- Use S3-compatible storage for durable multi-node deployments.
- Serve browser-downloadable attachments through the service so response headers can force safe content type and disposition decisions.
Upgrade and Rollback
- Test the exact production configuration in staging before upgrading. Startup validation may now reject plaintext encryption, issuer-only OIDC trust, wildcard credentialed CORS, malformed proxy CIDRs, dual plaintext/TLS TCP listeners, missing management-listener decisions, non-loopback management binds without an explicit acknowledgement, or a missing developer frontend base URL.
- Stop all old replicas before the breaking release. Mixed old/new binaries are unsupported.
- Take coordinated database and attachment-object backups, then reset the datastore and attachment store before startup initializes schema version 1.
- Rollback requires restoring both backups; the breaking release does not read pre-release schemas, MSEH v1 fields, or MSEH v2 attachment streams.