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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.