Bug#1146079: trixie-pu: package libmongocrypt/1.13.2-1+deb13u1

"Roberto C. Sanchez" <[email protected]>
Newsgroups gmane.linux.debian.devel.release
Message-ID <178801944599.66376.3374982926861342424.reportbug__45397.5986967393$1788019655$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-81523: 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/libmongocrypt/commit/0f8d744a8c5e1877e40efd1c8b440e4eed1e2462

[ Other info ]
N/A


-----BEGIN PGP SIGNATURE-----

iQIzBAEBCgAdFiEEIYZ1DR4ae5UL01q7ldFmTdL1kUIFAmqTAvUACgkQldFmTdL1
kUKkkA//esD+6cjeZ1BQd02CK+fEKxbx0v6cAHB9BMH7193s/SWqe8f0gQo0r53h
MHMw8l49riPzr/gabY+RgV1t1t+0QOs/6DxPfneR4WHonR8RCfZfhSocQSIexUov
T9TJ3WyVAWxU401eIWhKapwDGNaszssut0kKH/Ii1kFk8cd1QMgPICz9YmFOshXk
v8lW2YGpxusqqQUSfPVJ6gJEI30VDgei8X3g8LYFdkPXJsgPlKgE+RqvmBX6kxlC
jMYpYDGN0SSYmKLvpn2QVCcPaPkcTSQQPYnVsHPcjnWG+aU6Ju+Xdpaj9EGfmIm4
mCMMw9nGff3+B9yC16ZKAz8HTEPadfBun3yzyDtabN3iUr1Fm1nNQgUGEkd8iXh4
srncjW6M1rvFZmfdgDnk0h4IWhIC8YC6T2TgtocUeur6Epq76Z46qGF51NtRPN5j
AbAXPjbx8caztIpZUzF6oQyi5FnhfpcCKjUNKSRUeb4O7w4Ojahq4xU/ZiCSr9o9
cLAiNOQGb7o5237bzOX9SNd6vJqOFzSgoOzlggTur4R9IwAcH2IAVzlkyNuxXwW6
iwTMuNkF/Z67hcgOll2bkVe6AolCrzEzGOPFrdE2uErDca6C8VKC1Y39lqSqB5Go
6NiZNDheuH4uu4ECrcbrC0CEAoDIKhDQYV4ZUh/IyhnPm9mzEfA=
=TYdC
-----END PGP SIGNATURE-----
libmongocrypt_1.13.2-1_1.13.2-1+deb13u1.diff (text/plain, 14.1 KB)
diff -Nru libmongocrypt-1.13.2/debian/changelog libmongocrypt-1.13.2/debian/changelog
--- libmongocrypt-1.13.2/debian/changelog	2025-04-11 00:41:45.000000000 -0400
+++ libmongocrypt-1.13.2/debian/changelog	2026-08-29 11:20:33.000000000 -0400
@@ -1,3 +1,9 @@
+libmongocrypt (1.13.2-1+deb13u1) trixie; urgency=medium
+
+  * Fix CVE-2026-81523: validate db and collection names
+
+ -- Roberto C. Sanchez <[email protected]>  Sat, 29 Aug 2026 11:20:33 -0400
+
 libmongocrypt (1.13.2-1) unstable; urgency=medium
 
   * New upstream release.
diff -Nru libmongocrypt-1.13.2/debian/gbp.conf libmongocrypt-1.13.2/debian/gbp.conf
--- libmongocrypt-1.13.2/debian/gbp.conf	2025-04-11 00:41:45.000000000 -0400
+++ libmongocrypt-1.13.2/debian/gbp.conf	2026-08-29 11:20:33.000000000 -0400
@@ -12,9 +12,9 @@
     third_party_rm_files=\"$([ -d third-party ] && find third-party/ -mindepth 1 -maxdepth 1 -printf '%p ')\" &&
     # Create upstream tarball from reference, exclude items that do not belong
     pushd $GBP_GIT_DIR/.. &&
-    git archive --format=tar --prefix=libmongocrypt-\${upstream_version}/ HEAD | tar -f - --delete libmongocrypt-\${upstream_version}/debian \$third_party_filter_files | gzip > $GBP_BUILD_DIR/../libmongocrypt_\${upstream_version}.orig.tar.gz &&
+    ( [ -f $GBP_BUILD_DIR/../libmongocrypt_\${upstream_version}.orig.tar.gz ] || git archive --format=tar --prefix=libmongocrypt-\${upstream_version}/ HEAD | tar -f - --delete libmongocrypt-\${upstream_version}/debian \$third_party_filter_files | gzip > $GBP_BUILD_DIR/../libmongocrypt_\${upstream_version}.orig.tar.gz ) &&
     popd &&
     rm -rf \$third_party_rm_files"
 
 upstream-tag = %(version)s
-debian-branch = debian/unstable
+debian-branch = debian/trixie
diff -Nru libmongocrypt-1.13.2/debian/patches/0001_CVE-2026-81523.patch libmongocrypt-1.13.2/debian/patches/0001_CVE-2026-81523.patch
--- libmongocrypt-1.13.2/debian/patches/0001_CVE-2026-81523.patch	1969-12-31 19:00:00.000000000 -0500
+++ libmongocrypt-1.13.2/debian/patches/0001_CVE-2026-81523.patch	2026-08-29 11:20:33.000000000 -0400
@@ -0,0 +1,273 @@
+From 0f8d744a8c5e1877e40efd1c8b440e4eed1e2462 Mon Sep 17 00:00:00 2001
+From: Kevin Albertson <[email protected]>
+Date: Wed, 19 Aug 2026 07:48:21 -0400
+Subject: [PATCH] MONGOCRYPT-977 validate db and collection
+
+Reject NUL and dot in db.
+Reject NUL in collection.
+---
+ src/mc-schema-broker.c             |   12 +++
+ src/mongocrypt-ctx-encrypt.c       |   29 ++++++++-
+ src/mongocrypt-private.h           |    5 +
+ src/mongocrypt.c                   |   11 +++
+ test/test-mongocrypt-ctx-encrypt.c |  114 +++++++++++++++++++++++++++++++++++++
+ 5 files changed, 165 insertions(+), 6 deletions(-)
+
+--- a/src/mc-schema-broker.c
++++ b/src/mc-schema-broker.c
+@@ -323,7 +323,11 @@
+             CLIENT_ERR("failed to find 'name' in collinfo in database: %s", sb->db);
+             return false;
+         }
+-        coll = bson_iter_utf8(&name_iter, NULL);
++        uint32_t coll_len;
++        coll = bson_iter_utf8(&name_iter, &coll_len);
++        if (!_mongocrypt_check_no_embedded_nul(coll, coll_len, "collection name in collinfo", status)) {
++            return false;
++        }
+     }
+ 
+     // Cache the received collinfo.
+@@ -511,7 +515,11 @@
+         CLIENT_ERR("Failed to get collection name from command");
+         return false;
+     }
+-    const char *coll = bson_iter_utf8(&iter, NULL);
++    uint32_t coll_len;
++    const char *coll = bson_iter_utf8(&iter, &coll_len);
++    if (!_mongocrypt_check_no_embedded_nul(coll, coll_len, "collection name", status)) {
++        return false;
++    }
+ 
+     // Check if schema was requested.
+     mc_schema_entry_t *found = NULL;
+--- a/src/mongocrypt-ctx-encrypt.c
++++ b/src/mongocrypt-ctx-encrypt.c
+@@ -2017,7 +2017,11 @@
+         return false;
+     }
+ 
+-    const char *target_ns = bson_iter_utf8(&ns_iter, NULL /* length */);
++    uint32_t target_ns_len;
++    const char *target_ns = bson_iter_utf8(&ns_iter, &target_ns_len);
++    if (!_mongocrypt_check_no_embedded_nul(target_ns, target_ns_len, "namespace in `bulkWrite` command", status)) {
++        return false;
++    }
+     // Parse `target_ns` into "<db>.<coll>"
+     const char *dot = strstr(target_ns, ".");
+     if (!dot) {
+@@ -2089,7 +2093,12 @@
+     }
+ 
+     if (BSON_ITER_HOLDS_UTF8(&target_coll_iter)) {
+-        *target_coll = bson_strdup(bson_iter_utf8(&target_coll_iter, NULL));
++        uint32_t target_coll_len;
++        const char *target_coll_str = bson_iter_utf8(&target_coll_iter, &target_coll_len);
++        if (!_mongocrypt_check_no_embedded_nul(target_coll_str, target_coll_len, "collection name", status)) {
++            return false;
++        }
++        *target_coll = bson_strdup(target_coll_str);
+     } else {
+         *target_coll = NULL;
+     }
+@@ -2277,7 +2286,11 @@
+                                    stage_key);
+                         return false;
+                     }
+-                    const char *from = bson_iter_utf8(&lookup_iter, NULL);
++                    uint32_t from_len;
++                    const char *from = bson_iter_utf8(&lookup_iter, &from_len);
++                    if (!_mongocrypt_check_no_embedded_nul(from, from_len, "'from' collection name", status)) {
++                        return false;
++                    }
+                     if (!mc_schema_broker_request(sb, db, from, status)) {
+                         return false;
+                     }
+@@ -2336,7 +2349,11 @@
+                                    stage_key);
+                         return false;
+                     }
+-                    const char *coll = bson_iter_utf8(&unionWith_iter, NULL);
++                    uint32_t coll_len;
++                    const char *coll = bson_iter_utf8(&unionWith_iter, &coll_len);
++                    if (!_mongocrypt_check_no_embedded_nul(coll, coll_len, "'coll' collection name", status)) {
++                        return false;
++                    }
+                     if (!mc_schema_broker_request(sb, db, coll, status)) {
+                         return false;
+                     }
+@@ -2428,6 +2445,10 @@
+         return _mongocrypt_ctx_fail_w_msg(ctx, "invalid db");
+     }
+ 
++    if (strchr(ectx->cmd_db, '.')) {
++        return _mongocrypt_ctx_fail_w_msg(ctx, "invalid db: must not contain a dot");
++    }
++
+     if (0 == strcmp(ectx->cmd_name, "bulkWrite")) {
+         // Handle `bulkWrite` as a special case.
+         // `bulkWrite` includes the target namespaces in an `nsInfo` field.
+--- a/src/mongocrypt-private.h
++++ b/src/mongocrypt-private.h
+@@ -153,6 +153,11 @@
+ 
+ bool _mongocrypt_validate_and_copy_string(const char *in, int32_t in_len, char **out) MONGOCRYPT_WARN_UNUSED_RESULT;
+ 
++/* _mongocrypt_check_no_embedded_nul returns false and sets @status if @str contains an embedded null byte. See
++ * MONGOCRYPT-977. */
++bool _mongocrypt_check_no_embedded_nul(const char *str, uint32_t len, const char *what, mongocrypt_status_t *status)
++    MONGOCRYPT_WARN_UNUSED_RESULT;
++
+ char *_mongocrypt_new_string_from_bytes(const void *in, int len);
+ 
+ char *_mongocrypt_new_json_string_from_binary(mongocrypt_binary_t *binary);
+--- a/src/mongocrypt.c
++++ b/src/mongocrypt.c
+@@ -985,6 +985,17 @@
+     return crypt->csfle.get_version();
+ }
+ 
++bool _mongocrypt_check_no_embedded_nul(const char *str, uint32_t len, const char *what, mongocrypt_status_t *status) {
++    BSON_ASSERT_PARAM(str);
++    BSON_ASSERT_PARAM(what);
++
++    if (strlen(str) != (size_t)len) {
++        CLIENT_ERR("%s must not contain an embedded null byte", what);
++        return false;
++    }
++    return true;
++}
++
+ bool _mongocrypt_validate_and_copy_string(const char *in, int32_t in_len, char **out) {
+     BSON_ASSERT_PARAM(out);
+ 
+--- a/test/test-mongocrypt-ctx-encrypt.c
++++ b/test/test-mongocrypt-ctx-encrypt.c
+@@ -360,6 +360,119 @@
+     mongocrypt_destroy(crypt);
+ }
+ 
++/* Test that a db name containing a dot or an embedded NUL is rejected.
++ * A db name like "a.b" would otherwise produce the namespace "a.b.coll",
++ * retargeting the operation at database "a" and collection "b.coll".
++ * Regression test for MONGOCRYPT-977. */
++static void _test_encrypt_init_invalid_db_collection(_mongocrypt_tester_t *tester) {
++    mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT);
++
++    {
++        /* Dot in db name. */
++        mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt);
++        ASSERT_FAILS(mongocrypt_ctx_encrypt_init(ctx, "a.b", -1, TEST_FILE("./test/example/cmd.json")),
++                     ctx,
++                     "invalid db");
++        mongocrypt_ctx_destroy(ctx);
++    }
++
++    {
++        /* Embedded NUL in db name. */
++        const char db[] = "a\0b";
++        mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt);
++        ASSERT_FAILS(mongocrypt_ctx_encrypt_init(ctx, db, 3, TEST_FILE("./test/example/cmd.json")), ctx, "invalid db");
++        mongocrypt_ctx_destroy(ctx);
++    }
++
++    {
++        /* A dot in a collection name is legal, and must keep working. */
++        mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt);
++        ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "test", -1, TEST_BSON("{'find': 'a.b'}")), ctx);
++        mongocrypt_ctx_destroy(ctx);
++    }
++
++    {
++        /* Embedded NUL in the collection name of the command. */
++        bson_t *cmd = bson_new();
++        BSON_ASSERT(bson_append_utf8(cmd, "find", -1, "a\0b", 3));
++        mongocrypt_binary_t *bin = mongocrypt_binary_new_from_data((uint8_t *)bson_get_data(cmd), cmd->len);
++        mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt);
++        ASSERT_FAILS(mongocrypt_ctx_encrypt_init(ctx, "test", -1, bin),
++                     ctx,
++                     "collection name must not contain an embedded null byte");
++        mongocrypt_ctx_destroy(ctx);
++        mongocrypt_binary_destroy(bin);
++        bson_destroy(cmd);
++    }
++
++    {
++        /* Embedded NUL in the `bulkWrite` nsInfo namespace. */
++        bson_t *cmd = bson_new();
++        bson_array_builder_t *nsInfo;
++        bson_t ns0;
++        BSON_ASSERT(BSON_APPEND_INT32(cmd, "bulkWrite", 1));
++        BSON_ASSERT(BSON_APPEND_ARRAY_BUILDER_BEGIN(cmd, "nsInfo", &nsInfo));
++        BSON_ASSERT(bson_array_builder_append_document_begin(nsInfo, &ns0));
++        BSON_ASSERT(bson_append_utf8(&ns0, "ns", -1, "db.coll\0evil", 12));
++        BSON_ASSERT(bson_array_builder_append_document_end(nsInfo, &ns0));
++        BSON_ASSERT(bson_append_array_builder_end(cmd, nsInfo));
++        mongocrypt_binary_t *bin = mongocrypt_binary_new_from_data((uint8_t *)bson_get_data(cmd), cmd->len);
++        mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt);
++        ASSERT_FAILS(mongocrypt_ctx_encrypt_init(ctx, "test", -1, bin), ctx, "must not contain an embedded null byte");
++        mongocrypt_ctx_destroy(ctx);
++        mongocrypt_binary_destroy(bin);
++        bson_destroy(cmd);
++    }
++
++    {
++        /* Embedded NUL in a $lookup 'from' collection name. */
++        bson_t *cmd = bson_new();
++        bson_array_builder_t *pipeline;
++        bson_t stage, lookup;
++        BSON_ASSERT(BSON_APPEND_UTF8(cmd, "aggregate", "coll"));
++        BSON_ASSERT(BSON_APPEND_ARRAY_BUILDER_BEGIN(cmd, "pipeline", &pipeline));
++        BSON_ASSERT(bson_array_builder_append_document_begin(pipeline, &stage));
++        BSON_ASSERT(BSON_APPEND_DOCUMENT_BEGIN(&stage, "$lookup", &lookup));
++        BSON_ASSERT(bson_append_utf8(&lookup, "from", -1, "a\0b", 3));
++        BSON_ASSERT(bson_append_document_end(&stage, &lookup));
++        BSON_ASSERT(bson_array_builder_append_document_end(pipeline, &stage));
++        BSON_ASSERT(bson_append_array_builder_end(cmd, pipeline));
++        mongocrypt_binary_t *bin = mongocrypt_binary_new_from_data((uint8_t *)bson_get_data(cmd), cmd->len);
++        mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt);
++        ASSERT_FAILS(mongocrypt_ctx_encrypt_init(ctx, "test", -1, bin),
++                     ctx,
++                     "'from' collection name must not contain an embedded null byte");
++        mongocrypt_ctx_destroy(ctx);
++        mongocrypt_binary_destroy(bin);
++        bson_destroy(cmd);
++    }
++
++    {
++        /* Embedded NUL in a $unionWith 'coll' collection name. */
++        bson_t *cmd = bson_new();
++        bson_array_builder_t *pipeline;
++        bson_t stage, unionWith;
++        BSON_ASSERT(BSON_APPEND_UTF8(cmd, "aggregate", "coll"));
++        BSON_ASSERT(BSON_APPEND_ARRAY_BUILDER_BEGIN(cmd, "pipeline", &pipeline));
++        BSON_ASSERT(bson_array_builder_append_document_begin(pipeline, &stage));
++        BSON_ASSERT(BSON_APPEND_DOCUMENT_BEGIN(&stage, "$unionWith", &unionWith));
++        BSON_ASSERT(bson_append_utf8(&unionWith, "coll", -1, "a\0b", 3));
++        BSON_ASSERT(bson_append_document_end(&stage, &unionWith));
++        BSON_ASSERT(bson_array_builder_append_document_end(pipeline, &stage));
++        BSON_ASSERT(bson_append_array_builder_end(cmd, pipeline));
++        mongocrypt_binary_t *bin = mongocrypt_binary_new_from_data((uint8_t *)bson_get_data(cmd), cmd->len);
++        mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt);
++        ASSERT_FAILS(mongocrypt_ctx_encrypt_init(ctx, "test", -1, bin),
++                     ctx,
++                     "'coll' collection name must not contain an embedded null byte");
++        mongocrypt_ctx_destroy(ctx);
++        mongocrypt_binary_destroy(bin);
++        bson_destroy(cmd);
++    }
++
++    mongocrypt_destroy(crypt);
++}
++
+ static void _test_encrypt_need_collinfo(_mongocrypt_tester_t *tester) {
+     mongocrypt_t *crypt;
+     mongocrypt_ctx_t *ctx;
+@@ -5796,6 +5909,7 @@
+ void _mongocrypt_tester_install_ctx_encrypt(_mongocrypt_tester_t *tester) {
+     INSTALL_TEST(_test_explicit_encrypt_init);
+     INSTALL_TEST(_test_encrypt_init);
++    INSTALL_TEST(_test_encrypt_init_invalid_db_collection);
+     INSTALL_TEST(_test_encrypt_need_collinfo);
+     INSTALL_TEST(_test_encrypt_need_markings);
+     INSTALL_TEST(_test_encrypt_csfle_no_needs_markings);
diff -Nru libmongocrypt-1.13.2/debian/patches/series libmongocrypt-1.13.2/debian/patches/series
--- libmongocrypt-1.13.2/debian/patches/series	1969-12-31 19:00:00.000000000 -0500
+++ libmongocrypt-1.13.2/debian/patches/series	2026-08-29 11:20:33.000000000 -0400
@@ -0,0 +1 @@
+0001_CVE-2026-81523.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.