The db-mcp SQLite MCP server implements comprehensive security measures to protect your databases across both WASM and Native backends.
db-mcp offers two backend options β both with layered security:
- β WASM (sql.js) β runs in-process with zero native dependencies; 115 tools
- β Native (better-sqlite3) β full-featured with native bindings; 139 tools
Both backends apply security-relevant PRAGMAs on initialization:
- β
PRAGMA foreign_keys = ON β enforces referential integrity and
ON DELETE CASCADE - β PRAGMA journal_mode = WAL β auto-enabled for file-based databases (high concurrency, non-blocking reads)
- β
PRAGMA busy_timeout β configurable wait to avoid
SQLITE_BUSYerrors under contention - β
Parameterized queries β all user input bound via
?placeholders
- β
Data directory:
700(full access for owner only) in Docker - β
Non-root user (
appuser:appgroup) owns data directory
- β Parameterized queries used throughout β never string interpolation
- β Input validation via Zod schemas before database operations
- β
WHERE clause validation with 10 dangerous pattern detections:
- Subquery injection (
SELECTinside WHERE) - Statement termination (
;) - SQL comments (
--,/*) - UNION injection (
UNION SELECT) - Extension loading (
load_extension()) - Database attachment (
ATTACH DATABASE) - PRAGMA injection
- File I/O (
writefile(),readfile()) - Tokenizer exploitation (
fts3_tokenizer()) - Hex blob injection (
X'...')
- Subquery injection (
- β Identifier sanitization β table, column, and index names validated against injection
- β
FTS5 / LIKE pattern sanitization β escapes
%,_,\wildcards
Every tool returns structured error responses β never raw exceptions or internal details:
{
"success": false,
"error": "Descriptive message with context",
"code": "MODULE_ERROR_CODE",
"category": "VALIDATION_ERROR",
"suggestion": "Actionable remediation hint",
"recoverable": true
}Error codes are module-prefixed (e.g., JSON_PARSE_FAILED, VECTOR_DIMENSION_MISMATCH). Internal stack traces are logged server-side but never exposed to clients.
Code Mode (sqlite_execute_code) runs user-supplied JavaScript in a secure sandbox:
| Mode | Environment Variable | Security Level |
|---|---|---|
| Worker (default) | CODEMODE_ISOLATION=worker |
Enhanced β worker_threads with MessagePort RPC |
| VM | CODEMODE_ISOLATION=vm |
Standard β node:vm context isolation |
- β
No filesystem access β
fs,path,child_processare unavailable - β
No network access β
fetch,http,netmodules are unavailable - β
No global mutation β
setTimeout,setInterval,process,requireare removed from the sandbox context - β Execution timeout β 30-second hard limit per execution (configurable, max 30s)
- β Idle timeout β sandbox instances auto-dispose after 60 seconds of inactivity
- β MessagePort RPC bridge β in Worker mode, API calls cross a serialization boundary; no shared memory
Code Mode exposes only the typed sqlite.* SDK β agents can compose queries and chain operations but cannot escape the sandbox boundary.
When running in HTTP mode (--transport http), the following security measures apply:
- β
Configurable origins via
--cors-originsflag (comma-separated) - β
Wildcard subdomain matching (e.g.,
*.example.commatchesapp.example.com) β οΈ Default:*(allow all origins) for backward compatibility- π Recommended: Set specific origins for production deployments
# Restrict CORS to specific origins
db-mcp --transport http --cors-origins "http://localhost:3000,https://my-app.com"- β
DNS Rebinding Protection β
localhostHostValidationmiddleware from MCP SDK - β
Strict-Transport-Security (HSTS) β max-age=31536000; includeSubDomains (opt-in via
--enable-hsts) - β 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 data
- β Referrer-Policy: no-referrer β prevents referrer leakage
- β Permissions-Policy: camera=(), microphone=(), geolocation=() β restricts browser APIs
β οΈ 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) - β
Health check exempt β
/healthendpoint bypasses rate limiting - β
Trust Proxy β opt-in
--trust-proxyfor X-Forwarded-For IP extraction behind reverse proxies - β Server Timeouts β Request, keep-alive, and headers timeouts prevent slowloris-style DoS
- β UUID-based session IDs (cryptographically random)
- β
Explicit session termination via
DELETE /mcp - β
Cross-protocol guard β SSE session IDs rejected on
/mcpand vice versa
- β
Configurable body limit via
--max-body-bytes(default: 1 MB) β prevents memory exhaustion DoS
Lightweight authentication for development or single-tenant deployments:
db-mcp --transport http --auth-token my-secret --sqlite-native ./database.db- β
Clients must include
Authorization: Bearer <token>on all requests - β
/healthand/endpoints are exempt - β
Unauthenticated requests receive
401withWWW-Authenticate: Bearerper RFC 6750
Full OAuth 2.1 for production multi-tenant deployments:
- β
RFC 9728 Protected Resource Metadata (
/.well-known/oauth-protected-resource) - β RFC 8414 Authorization Server Discovery with caching
- β JWT validation with JWKS support
- β
Granular scopes:
read,write,admin,db:{name},table:{db}:{table} - β
Priority: When both
--auth-tokenand--oauth-enabledare set, OAuth takes precedence
db-mcp --transport http --oauth-enabled \
--oauth-issuer http://localhost:8080/realms/db-mcp \
--oauth-audience db-mcp-server \
--sqlite-native ./database.db- β
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
- β
Production pruning:
npm prune --omit=devafter build - β
Health check: Built-in
HEALTHCHECKinstruction - β Process isolation from host system
The Dockerfile patches npm-bundled transitive dependencies for Docker Scout compliance:
- β
diff@8.0.3β GHSA-73rr-hh4g-fpgx - β
@isaacs/brace-expansion@5.0.1β CVE-2026-25547 - β
tar@7.5.11β CVE-2026-23950, CVE-2026-24842, CVE-2026-26960 - β
minimatch@10.2.4β CVE-2026-26996 - β
protobufjs/cliremoved β CVE-2019-10790, CVE-2025-54798, CVE-2025-5889
# Secure volume mounting
docker run -v ./data:/app/data:rw,noexec,nosuid,nodev writenotenow/db-mcp:latest# Apply resource limits
docker run --memory=1g --cpus=1 writenotenow/db-mcp:latest- β CodeQL analysis β automated static analysis on push/PR
- β Docker Scout β container image vulnerability scanning (hard-fail on fixable critical/high)
- β npm audit β dependency vulnerability checking (audit-level: moderate)
- β Dependabot β automated dependency update PRs
- β E2E transport parity β Playwright suite validates HTTP/SSE security behavior
- Set a CORS origin when exposing the HTTP transport on a network
- Use authentication β configure
--auth-tokenor--oauth-enabledfor HTTP deployments - Keep Node.js updated: Use Node.js 24+ (LTS)
- Secure host system: Ensure your host machine is secure
- Use tool filtering: Expose only the tools you need (
--tool-filter) - Limit network access: Don't expose the HTTP transport to untrusted networks
- Use resource limits: Apply Docker
--memoryand--cpuslimits
- Parameterized queries only β never interpolate user input into SQL strings
- Zod validation β all tool inputs validated via schemas at tool boundaries
- No secrets in code β use environment variables (
.envfiles are gitignored) - Typed error classes β descriptive messages with context; don't expose internals
- Regular updates: Keep Node.js and npm dependencies updated
- Security scanning: Regularly scan Docker images for vulnerabilities
- Parameterized SQL queries throughout
- WHERE clause validation with 10 dangerous pattern detections
- Identifier sanitization (table, column, index names)
- FTS5 / LIKE pattern sanitization
- Input validation via Zod schemas
- Code Mode sandbox isolation (Worker + VM modes)
- Code Mode execution timeout (30s hard limit)
- HTTP body size limit (configurable, default 1 MB)
- Configurable CORS with wildcard subdomain matching
- Rate limiting (100 req/min per IP, sliding window)
- DNS rebinding protection (MCP SDK middleware)
- Security headers (CSP, X-Content-Type-Options, X-Frame-Options, Cache-Control, Referrer-Policy, Permissions-Policy)
- HSTS (opt-in)
- Server timeouts (request, keep-alive, headers)
- Bearer token authentication (RFC 6750)
- OAuth 2.1 with JWT/JWKS validation (RFC 9728, RFC 8414)
- Granular scope enforcement (
read,write,admin,db:*,table:*:*) - Non-root Docker user
- Multi-stage Docker build with production pruning
- Transitive dependency CVE patching in Dockerfile
- CI/CD security pipeline (CodeQL, Docker Scout, npm audit)
- Structured error responses (no internal details leaked)
- Comprehensive security documentation
| Version | Supported |
|---|---|
| 1.x.x | β |
| < 1.0 | β |
If you discover a security vulnerability:
- Do not open a public GitHub issue
- Email security concerns to: admin@adamic.tech
- Include detailed reproduction steps and potential impact
- Allow reasonable time for a fix before public disclosure
- Initial Response: Within 48 hours
- Status Update: Within 7 days
- Fix Timeline: Depends on severity
We appreciate responsible disclosure and will acknowledge your contribution in our release notes (unless you prefer to remain anonymous).
- 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 db-mcp SQLite MCP server is designed with security-first principles to protect your databases while maintaining excellent performance and full SQLite capability.