-
Type:
Task
-
Resolution: Done
-
Priority:
Critical - P2
-
Affects Version/s: None
-
Component/s: None
-
None
-
0.4
-
Dotnet Drivers
-
Not Needed
-
None
-
None
-
None
-
None
-
None
-
None
Summary
Apps that put the database name in the connection string get no field encryption at all — sensitive fields land in MongoDB as readable plaintext, silently.
Impact
All fields the model declares as queryable-encrypted are silently persisted and queried in plaintext, fully exposing them to database operators, backup holders, and any future server compromise, while the application believes encryption is active.
Severity: critical
Exploitability: exploitable — The failure is deterministic — every deployment using this documented configuration style writes all declared-encrypted fields as plaintext on every save, with no error or warning; an observer merely reads the database or a backup.
Customer data: pii, phi, pci, customer_content (backup)
Location
- src/MongoDB.EntityFrameworkCore/Storage/MongoClientWrapper.cs:160 in GetOrCreateMongoClient
- src/MongoDB.EntityFrameworkCore/Infrastructure/MongoClientSettingsHelper.cs:78 in CreateSettings
- src/MongoDB.EntityFrameworkCore/Extensions/MongoDbContextOptionsExtensions.cs:106 in UseMongoDB(connectionString)
- src/MongoDB.EntityFrameworkCore/Storage/MongoClientWrapper.cs:69 in Database
Reproduction / trigger path
Analyzed trigger path from static analysis — not an executed PoC. Confirm with a concrete repro before handing off.
Attacker controls: None required to trigger — the application's own supported configuration (database name in the connection string path plus an encrypted model) deterministically disables encryption; the observer needs read access to the database, its snapshots, or backups.
- (source) src/MongoDB.EntityFrameworkCore/Extensions/MongoDbContextOptionsExtensions.cs:106 in UseMongoDB(connectionString) — Documented overload accepting a connection string that 'must include a database name'; it sets only ConnectionString, leaving the DatabaseName option null.
- (hop) src/MongoDB.EntityFrameworkCore/Storage/MongoClientWrapper.cs:135 in GetOrCreateMongoClient — Effective database name is parsed from the connection string into _databaseName; options.DatabaseName remains null.
- (hop) src/MongoDB.EntityFrameworkCore/Storage/MongoClientWrapper.cs:160 in GetOrCreateMongoClient — CreateSettings receives the raw options object (DatabaseName == null) instead of the resolved _databaseName; the schema is active because the default mode ApplyToClient != Ignore (line 143-144).
- (sink) src/MongoDB.EntityFrameworkCore/Infrastructure/MongoClientSettingsHelper.cs:78 in CreateSettings — encryptedFieldsMap keys built as options?.DatabaseName + '.' + collection yield '.collection' — a namespace that never matches any real collection, so automatic encryption is configured for namespaces that don't exist.
- (hop) src/MongoDB.EntityFrameworkCore/Storage/MongoClientWrapper.cs:69 in Database — All CRUD runs against Client.GetDatabase(_databaseName) — the real namespace 'appdb.collection' — where the map never matches; collections are also created without server-side encryptedFields (MongoDatabaseCreator.cs:98), so declared-encrypted fields are stored and read as plaintext.
Root cause
- The connection-string-only configuration overload sets only the connection string, never the DatabaseName option (src/MongoDB.EntityFrameworkCore/Extensions/MongoDbContextOptionsExtensions.cs:116-118), and MongoOptionsExtension.Validate is empty (src/MongoDB.EntityFrameworkCore/Infrastructure/MongoOptionsExtension.cs:239-241).
- GetOrCreateMongoClient resolves the effective database name from the connection string URI into _databaseName (src/MongoDB.EntityFrameworkCore/Storage/MongoClientWrapper.cs:129-135) but then passes the raw options object — DatabaseName still null — to CreateSettings (src/MongoDB.EntityFrameworkCore/Storage/MongoClientWrapper.cs:160), discarding the resolved name.
- CreateSettings keys the driver's encryptedFieldsMap as options?.DatabaseName + "." + collection (src/MongoDB.EntityFrameworkCore/Infrastructure/MongoClientSettingsHelper.cs:78), producing keys like '.People' that can never match the real namespace 'appdb.People' used by all operations via Client.GetDatabase(_databaseName) (src/MongoDB.EntityFrameworkCore/Storage/MongoClientWrapper.cs:69).
- No fallback saves it: EnsureCreated creates collections with only user-supplied options (src/MongoDB.EntityFrameworkCore/Storage/MongoDatabaseCreator.cs:98), so because the client map misses, the collections are created without server-side encryptedFields metadata either — automatic encryption never fires and all declared-encrypted fields are read and written as plaintext.
Ownership
Assigned teams: @mongodb/dbx-csharp-dotnet
Filed from Aegis finding 791408b09aff (scan scan-6cd4cd27c8ab) · primitive: Client-side field encryption silently disabled: encryption map keyed under null database name never matches real namespaces, so declared-encrypted fields flow as plaintext. · categories: PII Exposure, Weak Cryptography, Secret Leakage