HOW TO SECURE MONGODB - SECURITY GUIDE | VIBEEVAL

MongoDB Security History

MongoDB shipped versions for years that bound to 0.0.0.0 with no auth by default. The result was tens of thousands of databases compromised by drive-by scanners — Shodan still indexes leftover instances. Modern versions are saner (auth required, localhost-only by default), but every self-hosted instance needs explicit configuration. The recurring incident shape today: a developer spins up MongoDB in a Docker container, exposes the port “for testing,” forgets, and a scanner finds it within hours.

Security Checklist

1. Always enable authentication

In mongod.conf: security.authorization: enabled. Create a user with the userAdminAnyDatabase role first; create per-database roles after. Never run a Mongo instance reachable from any network without auth — the time-to-compromise is measured in hours.

2. Restrict network access

In mongod.conf: net.bindIp: 127.0.0.1 for app-on-same-host, or a private VPC IP for app-on-other-host. Never bindIp: 0.0.0.0 without a firewall in front. For Atlas: configure IP allowlist / VPC peering, never 0.0.0.0/0 in the network access list.

3. Enable TLS for all connections

mongod.conf: net.tls.mode: requireTLS, with a valid cert. Connection strings must use tls=true (or ssl=true on older drivers). Without TLS, every query and credential transits in plaintext on the network path.

4. Use role-based access control

Create per-application roles with the minimum collections / actions needed:

db.createRole({
  role: "appReadWrite",
  privileges: [
    { resource: { db: "myapp", collection: "users" }, actions: ["find", "insert", "update"] }
  ],
  roles: []
});

Avoid dbOwner / root for application connections. The principle: a compromised app credential should not be able to drop the DB.

5. Prevent NoSQL injection

The classic MongoDB injection: db.users.findOne({ email: req.body.email, password: req.body.password }) — if the body is { "email": "x@y.com", "password": { "$ne": null } }, the query becomes “find any user with this email and any non-null password.” The fix:

  • Validate types: email must be string, password must be string.
  • Use a typed schema layer (Mongoose / Zod / Pydantic) at the API boundary.
  • Reject objects in fields that should be primitives.

6. Configure MongoDB Atlas security features

For Atlas (managed): enable Network Peering or Private Endpoint, IP allowlist limited to app IPs, MongoDB user auth via SCRAM-SHA-256, encryption-at-rest with customer-managed keys (Enterprise tier), audit logs streamed to your SIEM. Atlas defaults are safer than self-hosted but the advanced features need explicit configuration.

7. Configure audit logging

mongod.conf: auditLog.destination: file and auditLog.path: /var/log/mongo/audit.log. Audit auth events, role changes, and DDL. For Atlas, audit logs are configured at the cluster level and stream via M10+ tiers.

8. Enable encryption at rest

For Enterprise self-hosted: WiredTiger encryption with KMIP. For Atlas: encryption is on by default; customer-managed keys via Atlas Encryption at Rest with KMS.

9. Store connection strings securely

mongodb+srv://user:password@cluster.mongodb.net/db contains credentials inline. Store in a secret manager, not in .env files committed anywhere, never in client-side code. Rotate after any team-member departure.

10. Configure automated backups

For self-hosted: mongodump on a schedule, encrypted, stored off the same host. For Atlas: continuous backup is on by default for M10+ — verify the retention window matches your requirement and the restore path actually works (test once).

11. Use field-level encryption for sensitive PII

For SSN, credit cards, medical info: client-side field-level encryption (CSFLE). Encrypt the field with a key in your KMS before insert; decrypt on read. The data is encrypted in MongoDB even if the entire database is exfiltrated.

12. Set query timeouts

In your driver: maxTimeMS: 30000 on long-running queries. Server-side: --maxTimeMS in your serverParameter config. Prevents an attacker from triggering an expensive query that locks the collection.

13. Audit indexes

Indexes don’t directly affect security but a missing index means an unindexed query, which scans the full collection. An attacker who finds the unindexed query can DoS the cluster. Define indexes for every query path your app uses; review with db.collection.getIndexes().

14. Enable query analysis

db.setProfilingLevel(1, { slowms: 100 }) logs slow queries. Review the profile collection weekly for queries you don’t recognize — they’re either an opportunity to add an index or a sign of probing.

15. Configure replica set security

For replica sets: security.keyFile: /path/to/keyfile for inter-node auth. The keyfile is shared secret material — protect it the same as a credential. With keyfile auth, all internal traffic is mutually authenticated.

16. Set up alerting

Atlas Alerts (or Datadog / Grafana for self-hosted): alert on auth failure spikes, connection count anomalies, replica lag, and unusual disk I/O. Monitoring isn’t security, but it’s how you find out about an incident before the user does.

Free Self-Audit Suite

Five free scanners.

Vibe Coding Security Risk Guide

Full risk catalogue.

Naked Databases

The recurring “exposed database” pattern that affects self-hosted Mongo more than any other backend.

Automate Your Security Checks

VibeEval scans applications using MongoDB backends for NoSQL-injection patterns, exposed connection strings, and BOLA across collection queries.

SCAN YOUR APP

14-day trial. No card. Results in under 60 seconds.

START FREE SCAN