Bug#1146080: trixie-pu: package mongo-c-driver/1.30.4-1+deb13u3
"Roberto C. Sanchez" <[email protected]>
| Newsgroups | gmane.linux.debian.devel.release |
|---|---|
| Message-ID | <178801961927.66636.5412383079259432879.reportbug__21769.8846639664$1788019772$gmane$org@miami.connexer.com> |
Package: release.debian.org Severity: normal Tags: trixie User: [email protected] Usertags: pu -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA512 [ Reason ] Address the following issue: * Fix CVE-2026-81524: validate db and collection names [ Impact ] Without this fix, users and applications integrating libmongocrypt components may be vulnerable to potential information modification or disclosure. [ Tests ] The affected/changed code went through upstream code reviews. Also, accompanying unit tests were implemented and executed in upstream's extensive CI environment. [ Risks ] Code changes are minimal (to the extent possible), extensively reviewed/tested, and low risk. There are no work arounds. [ Checklist ] [x] *all* changes are documented in the d/changelog [x] I reviewed all changes and I approve them [x] attach debdiff against the package in (old)stable [x] the issue is verified as fixed in unstable [ Changes ] Backport the following upstream change: https://github.com/mongodb/mongo-c-driver/commit/81d0f794d07224c53f815ceb59daed28103dcf3d [ Other info ] N/A -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEEIYZ1DR4ae5UL01q7ldFmTdL1kUIFAmqTA6MACgkQldFmTdL1 kUL9OA/9H4GmIrMIkngE2ZATKuHBXhlCv+5SnWQy2HB4zi+rFHn3sEg0eNfXTR7w qKRxWfD/XJsMU1owt9wtVj79bP+m/AAaNMgbjrqm0HT6eGG6npJwiCISH1WsBysb U1EDRu2IgS06SaVsk2+MWONdP6K5jhQgv1s/VgPSrRjdN9y2rP2l+B1GKV+7w34f c0Q+Q+YNfn+B0N89Xq0UN3ALse+EigXIyv6Li9nb9KjOk4FQKuEVzMMDW6ar6xeI CsGTTGvGMsrBYCliEDOF3dNFhgKosv8JNgGs2Vbtq2IgItNQZHOeIw+z7mRM0ew1 JzSsf8LrCboM9zF9gaFsufkDcEWRGsaeHb2nG/cWzo5HQEZ4epYrReu1I3yrOPpX rKtAz6aW9E4PFdJ1j4YME9Se5vLzRtyzFEe9Pg0xGznTx1l30OsbV0pintbwJwm8 DQKb2479hcAHhczoZhAdm1cO8JH5cDJxOySxaD5LPbtGiGIY2oia2CTzt7mqQklc E322eFR8V7iMUsi11srb3HTyYWn/3vq72BJJBONZ5NBXFLQp1HgjcgNgQH8O7hSZ jBTxt3UVmA6affa6j4MY/J5aBfbleDD/eixW7hBhlVBMI91b46mgFM76+XaMFqyR zTla4LhLwYqigsWbqO2X4rEuBpiM1Q/ItytI7ikRPqBcP6yNqOo= =cqRe -----END PGP SIGNATURE-----
mongo-c-driver_1.30.4-1+deb13u2_1.30.4-1+deb13u3.diff
(text/plain, 16.7 KB)
diff -Nru mongo-c-driver-1.30.4/debian/changelog mongo-c-driver-1.30.4/debian/changelog --- mongo-c-driver-1.30.4/debian/changelog 2026-04-27 11:48:27.000000000 -0400 +++ mongo-c-driver-1.30.4/debian/changelog 2026-08-29 11:06:27.000000000 -0400 @@ -1,3 +1,9 @@ +mongo-c-driver (1.30.4-1+deb13u3) trixie; urgency=medium + + * Fix CVE-2026-81524: validate db and collection names + + -- Roberto C. Sanchez <[email protected]> Sat, 29 Aug 2026 11:06:27 -0400 + mongo-c-driver (1.30.4-1+deb13u2) trixie; urgency=medium * Fix CVE-2026-6231: bson_validate may skip validation when processing diff -Nru mongo-c-driver-1.30.4/debian/patches/0009_CVE-2026-81524.patch mongo-c-driver-1.30.4/debian/patches/0009_CVE-2026-81524.patch --- mongo-c-driver-1.30.4/debian/patches/0009_CVE-2026-81524.patch 1969-12-31 19:00:00.000000000 -0500 +++ mongo-c-driver-1.30.4/debian/patches/0009_CVE-2026-81524.patch 2026-08-29 11:06:27.000000000 -0400 @@ -0,0 +1,443 @@ +From 81d0f794d07224c53f815ceb59daed28103dcf3d Mon Sep 17 00:00:00 2001 +From: Kevin Albertson <[email protected]> +Date: Fri, 14 Aug 2026 12:39:43 -0400 +Subject: [PATCH] CDRIVER-6424 validate db and collection names + +--- + src/libmongoc/src/mongoc/mongoc-aggregate-private.h | 1 + src/libmongoc/src/mongoc/mongoc-aggregate.c | 8 + + src/libmongoc/src/mongoc/mongoc-client-side-encryption.c | 12 ++ + src/libmongoc/src/mongoc/mongoc-client.c | 4 + src/libmongoc/src/mongoc/mongoc-cmd.c | 7 + + src/libmongoc/src/mongoc/mongoc-collection.c | 13 ++ + src/libmongoc/src/mongoc/mongoc-cursor-private.h | 4 + src/libmongoc/src/mongoc/mongoc-cursor.c | 15 ++ + src/libmongoc/src/mongoc/mongoc-database.c | 2 + src/libmongoc/src/mongoc/mongoc-gridfs-bucket.c | 16 +++ + src/libmongoc/src/mongoc/mongoc-uri.c | 20 +++ + src/libmongoc/src/mongoc/mongoc-util-private.h | 34 ++++++ + src/libmongoc/src/mongoc/mongoc-util.c | 76 +++++++++++++++ + 13 files changed, 211 insertions(+), 1 deletion(-) + create mode 100644 src/libmongoc/tests/test-mongoc-ns-validation.c + +--- a/src/libmongoc/src/mongoc/mongoc-aggregate-private.h ++++ b/src/libmongoc/src/mongoc/mongoc-aggregate-private.h +@@ -34,6 +34,7 @@ + mongoc_cursor_t * + _mongoc_aggregate (mongoc_client_t *client, + const char *ns, ++ const char *db, + mongoc_query_flags_t flags, + const bson_t *pipeline, + const bson_t *opts, +--- a/src/libmongoc/src/mongoc/mongoc-aggregate.c ++++ b/src/libmongoc/src/mongoc/mongoc-aggregate.c +@@ -185,6 +185,7 @@ + * information on how to build aggregation pipelines. + * + * Parameters: ++ * @db: Database name used. Separated from @ns to validate. + * @ns: Namespace (or database name for database-level aggregation). + * @flags: Bitwise or of mongoc_query_flags_t or 0. + * @pipeline: A bson_t containing the pipeline request. @pipeline +@@ -210,6 +211,7 @@ + + mongoc_cursor_t * + _mongoc_aggregate (mongoc_client_t *client, ++ const char *db, + const char *ns, + mongoc_query_flags_t flags, + const bson_t *pipeline, +@@ -237,6 +239,7 @@ + + BSON_ASSERT (client); + BSON_ASSERT (ns); ++ BSON_ASSERT_PARAM(db); + BSON_ASSERT (pipeline); + + bson_init (&cursor_opts); +@@ -274,6 +277,11 @@ + GOTO (done); + } + ++ // `ns` is already joined and cannot be split back into `db` reliably. Check `db` while it is still separate. ++ if (!_mongoc_cursor_check_db_name(cursor, db)) { ++ GOTO(done); ++ } ++ + if (!_mongoc_read_prefs_validate (cursor->read_prefs, &cursor->error)) { + GOTO (done); + } +--- a/src/libmongoc/src/mongoc/mongoc-client-side-encryption.c ++++ b/src/libmongoc/src/mongoc/mongoc-client-side-encryption.c +@@ -1787,6 +1787,10 @@ + GOTO (fail); + } + ++ if (!_mongoc_validate_db_name(opts->keyvault_db, -1, error)) { ++ GOTO(fail); ++ } ++ + if (!opts->kms_providers) { + bson_set_error ( + error, MONGOC_ERROR_CLIENT, MONGOC_ERROR_CLIENT_INVALID_ENCRYPTION_ARG, "KMS providers option required"); +@@ -1918,6 +1922,10 @@ + GOTO (fail); + } + ++ if (!_mongoc_validate_db_name(opts->keyvault_db, -1, error)) { ++ GOTO(fail); ++ } ++ + if (!opts->kms_providers) { + bson_set_error ( + error, MONGOC_ERROR_CLIENT, MONGOC_ERROR_CLIENT_INVALID_ENCRYPTION_ARG, "KMS providers option required"); +@@ -2027,6 +2035,10 @@ + goto fail; + } + ++ if (!_mongoc_validate_db_name(opts->keyvault_db, -1, error)) { ++ goto fail; ++ } ++ + if (!opts->kms_providers) { + bson_set_error ( + error, MONGOC_ERROR_CLIENT, MONGOC_ERROR_CLIENT_INVALID_ENCRYPTION_ARG, "KMS providers option required"); +--- a/src/libmongoc/src/mongoc/mongoc-client.c ++++ b/src/libmongoc/src/mongoc/mongoc-client.c +@@ -1407,6 +1407,10 @@ + prefix = "fs"; + } + ++ if (!_mongoc_validate_db_name(db, -1, error)) { ++ return NULL; ++ } ++ + return _mongoc_gridfs_new (client, db, prefix, error); + } + +--- a/src/libmongoc/src/mongoc/mongoc-cmd.c ++++ b/src/libmongoc/src/mongoc/mongoc-cmd.c +@@ -730,6 +730,13 @@ + BSON_ASSERT (!parts->assembled.command); + BSON_ASSERT (bson_empty (&parts->assembled_body)); + ++ // The database name is sent as "$db" for OP_MSG or as "<db>.$cmd" for OP_QUERY. ++ // Reject a name the driver cannot forward faithfully, rather than silently targeting a different database. ++ BSON_ASSERT(parts->assembled.db_name); ++ if (!_mongoc_validate_db_name(parts->assembled.db_name, -1, error)) { ++ GOTO(done); ++ } ++ + /* begin with raw flags/cmd as assembled flags/cmd, might change below */ + parts->assembled.command = parts->body; + /* unused in OP_MSG: */ +--- a/src/libmongoc/src/mongoc/mongoc-collection.c ++++ b/src/libmongoc/src/mongoc/mongoc-collection.c +@@ -288,6 +288,7 @@ + { + return _mongoc_aggregate (collection->client, + collection->ns, ++ collection->db, + flags, + pipeline, + opts, +@@ -440,8 +441,12 @@ + + bson_clear (&collection->gle); + +- return _mongoc_cursor_find_new ( ++ mongoc_cursor_t *const cursor = _mongoc_cursor_find_new( + collection->client, collection->ns, filter, opts, read_prefs, collection->read_prefs, collection->read_concern); ++ ++ _mongoc_cursor_check_db_name(cursor, collection->db); ++ ++ return cursor; + } + + +@@ -1621,6 +1626,7 @@ + /* No read preference. Index Enumeration Spec: "run listIndexes on the + * primary node in replicaSet mode". */ + cursor = _mongoc_cursor_cmd_new (collection->client, collection->ns, &cmd, opts, NULL, NULL, NULL); ++ _mongoc_cursor_check_db_name(cursor, collection->db); + + if (!mongoc_cursor_error (cursor, &error)) { + _mongoc_cursor_prime (cursor); +@@ -2899,6 +2905,11 @@ + return false; + } + ++ // The "to" field below is a joined namespace, which the server splits at the first ".". ++ if (new_db && !_mongoc_validate_db_name(new_db, -1, error)) { ++ return false; ++ } ++ + newns = bson_strdup_printf ("%s.%s", new_db ? new_db : collection->db, new_name); + + BSON_APPEND_UTF8 (&cmd, "renameCollection", collection->ns); +--- a/src/libmongoc/src/mongoc/mongoc-cursor-private.h ++++ b/src/libmongoc/src/mongoc/mongoc-cursor-private.h +@@ -165,6 +165,10 @@ + _mongoc_n_return (mongoc_cursor_t *cursor); + void + _mongoc_set_cursor_ns (mongoc_cursor_t *cursor, const char *ns, uint32_t nslen); ++// Set an error on the cursor if `db` is not a valid database name. ++// Useful since `_mongoc_set_cursor_ns` does not know if a "." is in the db (invalid) or collection (valid). ++bool ++_mongoc_cursor_check_db_name(mongoc_cursor_t *cursor, const char *db); + bool + _mongoc_cursor_get_opt_bool (const mongoc_cursor_t *cursor, const char *option); + void +--- a/src/libmongoc/src/mongoc/mongoc-cursor.c ++++ b/src/libmongoc/src/mongoc/mongoc-cursor.c +@@ -174,6 +174,21 @@ + } + + ++bool ++_mongoc_cursor_check_db_name(mongoc_cursor_t *cursor, const char *db) ++{ ++ BSON_ASSERT_PARAM(cursor); ++ BSON_ASSERT_PARAM(db); ++ ++ // Preserve an error already recorded by cursor construction. ++ if (CURSOR_FAILED(cursor)) { ++ return false; ++ } ++ ++ return _mongoc_validate_db_name(db, -1, &cursor->error); ++} ++ ++ + /* return first key beginning with $, or NULL. precondition: bson is valid. */ + static const char * + _first_dollar_field (const bson_t *bson) +--- a/src/libmongoc/src/mongoc/mongoc-database.c ++++ b/src/libmongoc/src/mongoc/mongoc-database.c +@@ -137,6 +137,7 @@ + { + return _mongoc_aggregate (db->client, + db->name, ++ db->name, + MONGOC_QUERY_NONE, + pipeline, + opts, +@@ -755,6 +756,7 @@ + /* Enumerate Collections Spec: "run listCollections on the primary node in + * replicaset mode" */ + cursor = _mongoc_cursor_cmd_new (database->client, database->name, &cmd, opts, NULL, NULL, NULL); ++ _mongoc_cursor_check_db_name(cursor, database->name); + if (cursor->error.domain == 0) { + _mongoc_cursor_prime (cursor); + } +--- a/src/libmongoc/src/mongoc/mongoc-gridfs-bucket.c ++++ b/src/libmongoc/src/mongoc/mongoc-gridfs-bucket.c +@@ -25,6 +25,7 @@ + #include <mongoc/mongoc-stream-gridfs-download-private.h> + #include <mongoc/mongoc-stream-gridfs-upload-private.h> + #include <mongoc/mongoc-stream-private.h> ++#include <mongoc/mongoc-util-private.h> + #include <mongoc/mongoc-write-concern-private.h> + + /*-------------------------------------------------------------------------- +@@ -94,6 +95,21 @@ + return NULL; + } + ++ // Validate `bucketName` from the BSON options since it may contain an embedded NUL. ++ { ++ bson_iter_t iter; ++ ++ if (opts && bson_iter_init_find(&iter, opts, "bucketName") && BSON_ITER_HOLDS_UTF8(&iter)) { ++ uint32_t bucket_name_len; ++ const char *const bucket_name = bson_iter_utf8(&iter, &bucket_name_len); ++ ++ if (!_mongoc_validate_collection_name(bucket_name, bucket_name_len, error)) { ++ _mongoc_gridfs_bucket_opts_cleanup(&gridfs_opts); ++ return NULL; ++ } ++ } ++ } ++ + /* Initialize the bucket fields */ + if (strlen (gridfs_opts.bucketName) + strlen (".chunks") + 1 > sizeof (buf)) { + bson_set_error (error, +--- a/src/libmongoc/src/mongoc/mongoc-uri.c ++++ b/src/libmongoc/src/mongoc/mongoc-uri.c +@@ -1296,6 +1296,15 @@ + source = bson_iter_utf8 (&iter, NULL); + } + ++ // Validate `authSource`: ++ { ++ bson_error_t validate_error; ++ if (source && !_mongoc_validate_db_name(source, -1, &validate_error)) { ++ MONGOC_URI_ERROR(error, "%s", validate_error.message); ++ return false; ++ } ++ } ++ + if (mongoc_uri_get_auth_mechanism (uri)) { + /* authSource with GSSAPI or X509 should always be external */ + if (!strcasecmp (mongoc_uri_get_auth_mechanism (uri), "GSSAPI") || +@@ -1937,6 +1946,12 @@ + return false; + } + ++ // Match the validation applied to a database name parsed from the URI path. `_parse_path` rejects a larger set of ++ // characters; a "." is rejected here because it would silently retarget the namespace. ++ if (!_mongoc_validate_db_name_or_log(database)) { ++ return false; ++ } ++ + if (uri->database) { + bson_free (uri->database); + } +@@ -1992,6 +2007,11 @@ + return false; + } + ++ // `authSource` is a database name. See `mongoc_uri_finalize_auth`. ++ if (!_mongoc_validate_db_name_or_log(value)) { ++ return false; ++ } ++ + mongoc_uri_bson_append_or_replace_key (&uri->credentials, MONGOC_URI_AUTHSOURCE, value); + + return true; +--- a/src/libmongoc/src/mongoc/mongoc-util-private.h ++++ b/src/libmongoc/src/mongoc/mongoc-util-private.h +@@ -98,6 +98,40 @@ + bool + _mongoc_validate_replace (const bson_t *insert, bson_validate_flags_t vflags, bson_error_t *error); + ++/** ++ * @brief Validate a database name argument. ++ * ++ * Rejects a "." (the driver joins `db + "." + collection` into a namespace that the server splits at the first ".", ++ * so the server would never see the intended database name) and an embedded NUL byte (the name is truncated by the ++ * C string and wire protocol cstring encodings). Other characters prohibited by the MongoDB manual are forwarded ++ * faithfully and are left for the server to reject. ++ * ++ * @param db The database name to validate. ++ * @param db_len The length of @p db in bytes, or a negative value if @p db is NUL-terminated. ++ * @param error Optional out-parameter for the error. ++ * @return true if @p db is a usable database name. ++ */ ++bool ++_mongoc_validate_db_name(const char *db, int64_t db_len, bson_error_t *error); ++ ++/** ++ * @brief Validate a collection name argument. ++ * ++ * Rejects an embedded NUL byte. A "." is permitted in a collection name. ++ * ++ * @param collection The collection name to validate. ++ * @param collection_len The length of @p collection in bytes, or a negative value if @p collection is NUL-terminated. ++ * @param error Optional out-parameter for the error. ++ * @return true if @p collection is a usable collection name. ++ */ ++bool ++_mongoc_validate_collection_name(const char *collection, int64_t collection_len, bson_error_t *error); ++ ++// _mongoc_validate_db_name_or_log validates a NUL-terminated database name, logging the error at the ERROR level if ++// invalid. For use by APIs that have no `bson_error_t` out-parameter. ++bool ++_mongoc_validate_db_name_or_log(const char *db); ++ + bool + _mongoc_validate_update (const bson_t *update, bson_validate_flags_t vflags, bson_error_t *error); + +--- a/src/libmongoc/src/mongoc/mongoc-util.c ++++ b/src/libmongoc/src/mongoc/mongoc-util.c +@@ -18,6 +18,7 @@ + #define _CRT_RAND_S + #endif + ++#include <limits.h> + #include <string.h> + + #include <bson/bson.h> +@@ -464,6 +465,81 @@ + } + + return true; ++} ++ ++ ++// _validate_name checks a database or collection name argument for characters the driver's own encoding cannot ++// faithfully forward to the server. See `_mongoc_validate_db_name` and `_mongoc_validate_collection_name`. ++static bool ++_validate_name(const char *name, int64_t name_len, bool is_db, bson_error_t *error) ++{ ++ BSON_ASSERT_PARAM(name); ++ BSON_OPTIONAL_PARAM(error); ++ ++ size_t len = 0; ++ if (name_len < 0) { ++ len = strlen(name); ++ } else if (mcommon_in_range_signed(size_t, name_len)) { ++ len = (size_t)name_len; ++ } else { ++ bson_set_error(error, ++ MONGOC_ERROR_NAMESPACE, ++ MONGOC_ERROR_NAMESPACE_INVALID, ++ "%s name invalid: too large", ++ is_db ? "database" : "collection"); ++ return false; ++ } ++ ++ if (memchr(name, '\0', len)) { ++ bson_set_error(error, ++ MONGOC_ERROR_NAMESPACE, ++ MONGOC_ERROR_NAMESPACE_INVALID, ++ "%s name invalid: contains a NUL byte", ++ is_db ? "database" : "collection"); ++ return false; ++ } ++ ++ if (is_db && memchr(name, '.', len)) { ++ const int print_len = mcommon_in_range_signed(int, len) ? (int)len : INT_MAX; ++ ++ bson_set_error(error, ++ MONGOC_ERROR_NAMESPACE, ++ MONGOC_ERROR_NAMESPACE_INVALID, ++ "database name \"%.*s\" invalid: contains \".\"", ++ print_len, ++ name); ++ return false; ++ } ++ ++ return true; ++} ++ ++ ++bool ++_mongoc_validate_db_name(const char *db, int64_t db_len, bson_error_t *error) ++{ ++ return _validate_name(db, db_len, true /* is_db */, error); ++} ++ ++ ++bool ++_mongoc_validate_collection_name(const char *collection, int64_t collection_len, bson_error_t *error) ++{ ++ return _validate_name(collection, collection_len, false /* is_db */, error); ++} ++ ++ ++bool ++_mongoc_validate_db_name_or_log(const char *db) ++{ ++ bson_error_t error; ++ ++ if (!_mongoc_validate_db_name(db, -1, &error)) { ++ MONGOC_ERROR("%s", error.message); ++ return false; ++ } ++ ++ return true; + } + + diff -Nru mongo-c-driver-1.30.4/debian/patches/series mongo-c-driver-1.30.4/debian/patches/series --- mongo-c-driver-1.30.4/debian/patches/series 2026-04-27 11:48:27.000000000 -0400 +++ mongo-c-driver-1.30.4/debian/patches/series 2026-08-29 11:06:27.000000000 -0400 @@ -7,3 +7,4 @@ 0006_CVE-2025-14911.patch 0007_CVE-2025-14911.patch 0008_CVE-2026-6691.patch +0009_CVE-2026-81524.patch