do-memory-mcp 0.1.46

Model Context Protocol (MCP) server for AI agents
# Security Analysis: Memory MCP Server

## Overview

This document describes the security posture of the `do-memory-mcp` server as
it exists today. It is a security analysis of the **live** boundaries —
transport, authentication, authorization, rate limiting, audit logging,
input validation, and the fail-closed code-execution policy — not of a removed
sandbox.

> **Code execution is fail-closed.** `execute_agent_code` is unavailable in
> production: it is not advertised by `tools/list`, direct calls are rejected,
> and there is no WASM/Wasmtime/Javy execution backend. See
> [ADR-073]../plans/adr/ADR-073-Capability-Enforced-Agent-Code-Execution.md
> and [ADR-052]../plans/adr/ADR-052-Comprehensive-Analysis-v0.1.29.md.
> An earlier WASM sandbox was removed in v0.1.29; no production sandbox
> behavior is promised or implemented.

## Threat Model

### Attacker Capabilities

We assume an attacker can:

- Send arbitrary MCP JSON-RPC requests to the server's transport.
- Attempt to invoke tools with malformed, oversized, or hostile arguments.
- Attempt to invoke `execute_agent_code` or other unavailable tools.
- Attempt to exhaust CPU, memory, or storage through query/ingest pressure.
- Attempt to inject SQL or otherwise tamper with storage queries.
- Attempt to exfiltrate secrets through logs or tool responses.

### Assets to Protect

1. **Stored memory**: episodes, patterns, tags, and relationships.
2. **Host system**: files, processes, network, and environment.
3. **Credentials**: OAuth JWKS/secret material and embedding provider keys.
4. **System resources**: CPU, memory, disk, and network bandwidth.
5. **Audit integrity**: trustworthy, tamper-resistant security event records.

## Security Boundaries

### 1. Transport

- The server communicates over **stdio using JSON-RPC 2.0**
  (`src/bin/memory-mcp-server.rs`). There is no network listener bound by the
  default binary.
- Requests are parsed defensively; malformed JSON yields JSON-RPC error
  responses rather than panics.

### 2. Authentication & Authorization (OAuth 2.1, opt-in)

- OAuth 2.1 bearer-token validation lives in `src/bin/server_impl/oauth.rs` and
  is compiled only with the `oauth` feature.
- Configuration is read from environment variables:
  `MCP_OAUTH_ENABLED`, `MCP_OAUTH_AUDIENCE`, `MCP_OAUTH_ISSUER`,
  `MCP_OAUTH_SCOPES`, `MCP_OAUTH_JWKS_URI`, `MCP_OAUTH_TOKEN_SECRET`.
- When enabled, tokens are validated (JWT signature verification, issuer,
  audience, and scope checks) and failures produce `WWW-Authenticate`
  challenges.
- When the `oauth` feature is disabled, the server logs that OAuth is disabled
  and continues; deployments that require authentication MUST enable it.

### 3. Code Execution (fail-closed)

- `execute_agent_code` is **not** a working execution backend. It is absent from
  tool discovery and direct calls are rejected
  (`src/bin/server_impl/handlers/call_tool.rs`,
  `src/bin/server_impl/handlers/batch_execute.rs`).
- The handler in `src/bin/server_impl/tools/memory_handlers.rs` audit-logs the
  attempt and returns a "no longer available" error.
- No WASM, Wasmtime, Javy, or rquickjs dependency or feature exists in this
  crate; the `wasmtime-backend`, `javy-backend`, and `wasm-rquickjs` names were
  removed in v0.1.29.

#### `sandbox-dev` (trusted local experimentation only)

A legacy Node.js `CodeSandbox` (`src/sandbox/`) remains compiled **only** behind
the non-default `sandbox-dev` feature. It is **not** a production sandbox and
MUST NOT receive untrusted input.

**Enforced:** execution timeout with `kill_on_drop`, 100 KB code-length cap,
static regex source screening (filesystem/network/subprocess/malicious), and
global shadowing/deletion in the generated JavaScript wrapper.

**Not enforced:** OS-level isolation (`src/sandbox/isolation.rs` exposes
`apply_isolation`, but the execution path never calls it), memory and CPU
limits (configuration-only), output sanitization, and runtime capability
enforcement. Regex screening is heuristic and bypassable via runtime
obfuscation.

### 4. Rate Limiting

- Token-bucket per-client rate limiting (`src/server/rate_limiter/`) protects the
  server from DoS. Limits are configurable via `MCP_RATE_LIMIT_*` environment
  variables (read/write RPS and burst, cleanup interval, stale threshold).
- Read and write operations are limited separately.

### 5. Audit Logging

- Structured JSON audit logging (`src/server/audit/`) records security-relevant
  events: authentication, rate-limit violations, security violations,
  configuration changes, episode deletion, and rejected code-execution attempts.
- Sensitive fields are recursively redacted by key
  (`src/server/audit/redaction.rs`); the redaction field list is configurable
  via `AUDIT_LOG_REDACT_FIELDS`.
- Configuration is read from `AUDIT_LOG_*` environment variables (enable,
  destination, file path, rotation, level).

### 6. Input Validation & Storage

- All database access uses **parameterized SQL** via the Turso/libSQL and redb
  storage backends; queries are never built by string concatenation.
- Tool parameters are validated against their schemas, including length and
  range constraints, before use.
- Episode and pattern identifiers are validated and malformed IDs rejected
  consistently across core, MCP, and CLI.

### 7. Data Protection

- Credentials are read from environment variables and are never persisted or
  echoed in responses, warnings, errors, or audit fields.
- Embedding activation is atomic; failed activation leaves the prior provider
  unchanged.
- Transport security for external storage (Turso) is handled by TLS at the
  client layer.

## Attack Scenarios

### 1. SQL Injection

**Attack**: Supply crafted episode IDs or filters to alter queries.

**Defense**: Parameterized statements across all backends; identifiers are
validated. ✅ **MITIGATED**

### 2. Unauthorized Tool Use

**Attack**: Invoke `execute_agent_code` or other privileged operations without
authorization.

**Defense**: `execute_agent_code` is rejected fail-closed; when OAuth is
enabled, tools require a valid bearer token with the appropriate scope.
✅ **MITIGATED** (with `oauth` enabled for authenticated deployments)

### 3. Resource Exhaustion

**Attack**: Flood the server with requests or large payloads.

**Defense**: Per-client token-bucket rate limiting, input size limits, and
schema constraints. ⚠️ **PARTIAL** — limit tuning is deployment-specific.

### 4. Secret Leakage via Logs or Responses

**Attack**: Cause secrets to be written to logs or returned in tool output.

**Defense**: Credentials are read from env and never stored or echoed; audit
metadata is redacted by key. ⚠️ **PARTIAL** — redaction depends on configured
field names.

### 5. Prompt Injection via Stored Memory

**Attack**: Store adversarial content in episodes that later influences an
agent.

**Defense**: Out of scope for the server's authentication boundary; memory
content is treated as untrusted by clients. ⚠️ **NOT MITIGATED** at the server
layer — consumers must treat retrieved memory as untrusted data.

## Deployment Recommendations

### Container Hardening

Run the server with a non-root user, dropped capabilities, a read-only root
filesystem, and explicit resource limits:

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: do-memory-mcp-server
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
  containers:
  - name: mcp-server
    image: do-memory-mcp:latest
    resources:
      limits:
        memory: "256Mi"
        cpu: "500m"
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop: ["ALL"]
```

Because there is no in-process sandbox for arbitrary code, resource limits are
enforced by the deployment substrate (cgroups, container limits), not by the
MCP server.

### Configuration

- Enable OAuth (`oauth` feature + `MCP_OAUTH_*`) for any shared deployment.
- Keep rate limiting enabled and tuned (`MCP_RATE_LIMIT_*`).
- Enable audit logging to a durable, access-controlled destination
  (`AUDIT_LOG_*`) and set `AUDIT_LOG_REDACT_FIELDS`.
- Do **not** enable `sandbox-dev` in production.

## Security Checklist

Before deploying:

- [ ] OAuth enabled with correct issuer/audience/scopes (if shared)
- [ ] Rate limiting enabled and tuned
- [ ] Audit logging enabled with redaction fields configured
- [ ] Dependencies audited (`cargo audit`)
- [ ] No hardcoded secrets; credentials via environment variables
- [ ] TLS configured for Turso connections
- [ ] Container runs non-root with dropped capabilities and resource limits
- [ ] `sandbox-dev` feature disabled
- [ ] Log rotation configured
- [ ] Incident response plan documented
- [ ] Backup/recovery tested

## Incident Response

If a security breach is suspected:

1. **Contain**: restrict access to the server and its transports.
2. **Isolate**: quarantine affected host and storage.
3. **Analyze**: review audit logs and execution history (respecting redaction).
4. **Remediate**: patch and redeploy.
5. **Monitor**: watch for similar patterns.
6. **Report**: document the incident and lessons learned.

## Responsible Disclosure

Security vulnerabilities should be reported privately via the repository's
GitHub Security Advisory workflow. Do NOT create public issues for security
vulnerabilities.

## Conclusion

The server's production security posture rests on a stdio-only transport,
optional OAuth 2.1 authentication, per-client rate limiting, structured and
redacted audit logging, parameterized storage access, and a **fail-closed**
code-execution policy. There is no production sandbox for arbitrary agent code;
deployments that need to run untrusted code must do so in an external,
separately hardened runner.

**Last Updated**: 2026-09-30