The Memory Journal MCP server implements comprehensive security measures to protect your personal journal data.
The server uses the native better-sqlite3 driver with sqlite-vec for vector operations, running directly against the filesystem.
- ✅ PRAGMA foreign_keys = ON — enforces referential integrity and
ON DELETE CASCADE - ✅ Parameterized queries — all user input bound via
?placeholders - ✅ WAL journal mode — high concurrency with non-blocking reads (
PRAGMA journal_mode = WAL) - ✅ Synchronous Normal — optimized durability and performance (
PRAGMA synchronous = NORMAL)
- ✅ Data directory:
700(full access for owner only) in Docker - ✅ Non-root user (
appuser:appgroup) owns data directory
- Journal entries: 50,000 characters maximum
- Tags: 100 characters maximum
- Entry types: 50 characters maximum
- Significance types: 50 characters maximum
- HTTP request body: 1MB maximum (prevents memory exhaustion)
Tags are stored as-is via parameterized queries. Special characters in tags are safely handled by the database layer and do not pose injection risks.
- ✅ No Raw SQL Execution — All raw SQL methods (
_executeRawQueryUnsafe) have been removed. All handlers must use strict, parameterized methods defined byIDatabaseAdapter. - ✅ Parameterized queries used throughout
- ✅ Input validation via Zod schemas before database operations
- ✅ Warning system for potentially dangerous content patterns
- ✅ FTS5 / LIKE pattern sanitization (escapes
%,_,\wildcards and handles FTS5 syntax errors gracefully) - ✅ Date format whitelisting (prevents strftime injection)
- ✅ Explicit Filesystem Boundaries — Filesystem access MUST be explicitly granted via
ALLOWED_IO_ROOTS. The server operates in a fail-closed mode (ALLOWED_IO_ROOTS=[]) by default if not explicitly configured, preventing all filesystem interaction. - ✅ Implicit Authority Disabled — The server no longer derives ambient filesystem authority from the location of database files.
- ✅ Backup filenames validated - rejects
/,\,..in paths - ✅ Typed security errors with consistent error codes
When running in HTTP mode (--transport http), the following security measures apply:
- ✅ Configurable multiple origins via comma-separated
--cors-originflag orMCP_CORS_ORIGINenvironment variable - ✅ Exact-match verification (no wildcard matching for custom domains)
- 🔒 Default: None (no external origins allowed by default). You MUST explicitly configure CORS for browsers.
- 🔒 Required: Set specific origins for production deployments, or wildcard (
*) will only be accepted if HTTP Authentication is enabled.
# Restrict CORS to specific origins
memory-journal-mcp --transport http --cors-origin "http://localhost:3000,https://my-app.com"
# Or via environment variable
export MCP_CORS_ORIGIN="http://localhost:3000,https://my-app.com"- ✅ DNS Rebinding Protection —
hostHeaderValidationmiddleware prevents CVE-2025-66414 - ✅ Strict-Transport-Security (HSTS) — max-age=31536000; includeSubDomains (opt-in via
--enable-hsts). Note: Only effective when deployed behind a reverse proxy handling HTTPS. - ✅ X-Content-Type-Options: nosniff — prevents MIME sniffing
- ✅ X-Frame-Options: DENY — prevents clickjacking
- ✅ Content-Security-Policy: default-src 'none'; frame-ancestors 'none' — prevents XSS and framing
- ✅ Cache-Control: no-store, no-cache, must-revalidate — prevents caching of sensitive journal data
- ✅ Referrer-Policy: no-referrer — prevents referrer leakage
⚠️ CORS wildcard warning — server logs a warning when CORS origin is*
- ✅ Built-in Rate Limiting — 100 requests/minute per IP (sliding window with
Retry-Afterheader) - ✅ HTTP Timeouts — Request timeout (120s), keep-alive timeout (65s), headers timeout (66s)
- ✅ UUID-based session IDs (cryptographically random)
- ✅ 30-minute session timeout - idle sessions automatically expired
- ✅ 5-minute sweep interval - periodic cleanup of abandoned sessions
- ✅ Explicit session termination via
DELETE /mcp
- ✅ 1MB body limit on JSON requests (prevents memory exhaustion DoS)
- ✅ Environment variables only - tokens never stored in config files
- ✅ Error message scrubbing - Authorization headers stripped from error logs
- ✅ Optional integration - server works fully offline without GitHub token
- ✅ Minimal scopes - only requires
repo,project,read:org
# Required for Authentication (Must not be the placeholder token)
MCP_AUTH_TOKEN="your-secure-token-here"
# Required for Filesystem Tools (Export, Backup)
ALLOWED_IO_ROOTS="/path/to/allow1,/path/to/allow2"
# Required for GitHub features
GITHUB_TOKEN=ghp_... # GitHub personal access token
# Optional
GITHUB_ORG_TOKEN=ghp_... # For organization projects
PROJECT_REGISTRY='{"my-repo":{"path":"/path/to/repo","project_number":1}}' # Multi-project routing
DEFAULT_PROJECT_NUMBER=1 # Default project for issue assignment
MCP_CORS_ORIGIN= # CORS origin (default: none)
MCP_HOST=localhost # Server bind host
AUTO_REBUILD_INDEX=true # Rebuild vector index on startup- ✅ Dedicated user:
appuser(UID 1001) with minimal privileges - ✅ Restricted group:
appgroup(GID 1001) - ✅ Restricted data directory:
700permissions
- ✅ Minimal base image:
node:24-alpine - ✅ Multi-stage build: Build dependencies not in production image
- ✅ Process isolation from host system
- ✅ No shell access needed for production
# Secure volume mounting
docker run -v ./data:/app/data:rw,noexec,nosuid,nodev memory-journal-mcp# Apply resource limits
docker run --memory=1g --cpus=1 memory-journal-mcp- ✅ Full data ownership: SQLite database stays on your machine
- ✅ No telemetry: No data sent to external telemetry endpoints
⚠️ External Services: If configured, communicates with GitHub API and fetches OAuth discovery (JWKS) endpoints.⚠️ Semantic search: ML models are executed locally via@huggingface/transformers, but the model weights are downloaded from the Hugging Face registry on first run if not cached locally.
- ✅ Git context: Only reads local repository information
- ✅ No sensitive data: Doesn't access private keys or credentials
- ✅ Optional GitHub integration: Only if explicitly configured with token
- ✅ CodeQL analysis - automated static analysis on push/PR
- ✅ Trivy container scanning - Docker image vulnerability detection
- ✅ TruffleHog - secret scanning on push/PR
- ✅ npm audit - dependency vulnerability checking
- ✅ Dependabot - automated dependency update PRs
- Set a CORS origin when exposing the HTTP transport on a network
- Keep Node.js updated: Use Node.js 24+ (LTS)
- Secure host system: Ensure your host machine is secure
- Regular backups: Use the
backup_journaltool or back up your.dbfile - Limit network access: Don't expose the HTTP transport to untrusted networks
- Use resource limits: Apply Docker
--memoryand--cpuslimits
- Regular updates: Keep Node.js and npm dependencies updated
- Security scanning: Regularly scan Docker images for vulnerabilities
- Code review: All database operations use parameterized queries
- Input validation: All tool inputs validated via Zod schemas
- Foreign key enforcement (
PRAGMA foreign_keys = ON) - Input validation and length limits (Zod schemas)
- Parameterized SQL queries
- SQL injection detection heuristics (defense-in-depth)
- Path traversal protection (
assertNoPathTraversal) - Explicit Filesystem Boundaries (
ALLOWED_IO_ROOTSenforcement) - Strict Authentication Tokens (Placeholder rejection)
- FTS5 / LIKE pattern sanitization (
sanitizeSearchQuery) - Date format whitelisting (
validateDateFormatPattern) - HTTP body size limit (1MB)
- Configurable CORS multi-origin with exact-match enforcement
- HTTP timeouts and built-in rate limiter (100 req/min)
- DNS rebinding protection and strict HSTS
- Security headers (CSP, X-Content-Type-Options, X-Frame-Options, Cache-Control, Referrer-Policy, Permissions-Policy)
- Session timeout (30 minutes)
- Non-root Docker user
- Multi-stage Docker build
- Local-first data architecture
- GitHub token error scrubbing
- CI/CD security pipeline (CodeQL, Trivy, secret scanning)
- Comprehensive security documentation
If you discover a security vulnerability, please:
- Do not open a public GitHub issue
- Contact the maintainers privately
- Provide detailed information about the vulnerability
- Allow time for the issue to be addressed before public disclosure
- Container updates: Rebuild Docker images when base images are updated
- Dependency updates: Keep npm packages updated via
npm auditand Dependabot - Database maintenance: Run
ANALYZEandPRAGMA optimizeregularly - Security patches: Apply host system security updates
The Memory Journal MCP server is designed with security-first principles to protect your personal journal data while maintaining excellent performance and usability.