Connection
What to set on the MongoClient, on the database user and on the server for an app that uses MongoZod.
MongoZod uses the driver's connection as it is: a MongoClient, and the Db each model takes
(see db). This page lists what to set on each side, from the
MongoDB security checklist
and the
Node.js security best practices,
with what matters to MongoZod.
The client
import { MongoClient } from 'mongodb'
const client = new MongoClient(process.env.MONGODB_URI ?? 'mongodb://localhost:27017', {
appName: 'blog'
})
const db = client.db('blog')The driver connects on the first operation, so a module can create the client and the Db without
awaiting connect(), and the models take that Db.
- The connection string comes from the environment, with the credentials of the
application's user and TLS:
mongodb+srv://turns it on, and amongodb://string takestls=true. useBigInt64: truewhen a schema has az.bigint(): without it, the driver reads a long as a number, so every operation of that model throws (see Schemas).maxTimeMSgoes per operation, in the options a model method takes: it stops a query that runs too long, such as a$regexa client sent (see Cost).ignoreUndefinedis not a protection. With it, the driver drops a key whose value isundefinedinstead of sendingnull, sofindOne({ email: undefined })becomesfindOne({})and matches the first document. MongoZod dropsundefinedkeys when it writes and in the builders ofmongozod/mzod, and throws aZodErrorfor anundefinedvalue in a filter (see Values that skip the builders), so a project that uses it doesn't needignoreUndefined.- Leave
promoteBuffersoff: it reads everyBinaryas aBuffer, UUIDs included, where the field types ofmongozod/mzodreturn aBinaryand aUUID.
The user
Connect with a user that has only what the application needs, as the checklist's principle of
least privilege says: readWrite on its database. It includes createIndex, so sync() creates
the indexes a model declares with it.
sync() with jsonSchema applies the validator with
collMod, an action of dbAdmin, not of readWrite
(built-in roles). Run sync() from
a deploy step with a user that has dbAdmin too, and keep the application's user at readWrite:
// mongosh, as a user administrator
db.createUser({ user: 'blog', pwd: passwordPrompt(), roles: [{ role: 'readWrite', db: 'blog' }] })
db.createUser({
user: 'blog-deploy',
pwd: passwordPrompt(),
roles: [
{ role: 'readWrite', db: 'blog' },
{ role: 'dbAdmin', db: 'blog' }
]
})The server
- Server-side JavaScript: MongoZod never runs it, and
mz.filterrejects$where. But a filter of a model, anaggregatepipeline and an update withupdatePipeline: truereach the server as you write them,$where,$functionand$accumulatorincluded. When the application doesn't use them, disable server-side scripting, as the checklist says:security.javascriptEnabled: falsein the configuration file, or--noscriptingon the command line. - Access control on, with
bindIpand a firewall that leave the server reachable from the application only.
security:
authorization: enabled
javascriptEnabled: falseWhat follows is the deployment's, outside MongoZod: TLS on every connection, encryption at rest, auditing, a dedicated system user and the CVEs of MongoDB. The checklist covers each one. On Atlas, most of it is set up for you.
Next steps
Last updated on
MongoZod is an independent open-source project. It is not affiliated with, endorsed by or sponsored by MongoDB, Inc. MongoDB® is a registered trademark of MongoDB, Inc.