Version in base suite: 1.13.2-1 Base version: libmongocrypt_1.13.2-1 Target version: libmongocrypt_1.13.2-1+deb13u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/libm/libmongocrypt/libmongocrypt_1.13.2-1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/libm/libmongocrypt/libmongocrypt_1.13.2-1+deb13u1.dsc changelog | 6 gbp.conf | 4 patches/0001_CVE-2026-81523.patch | 273 ++++++++++++++++++++++++++++++++++++++ patches/series | 1 4 files changed, 282 insertions(+), 2 deletions(-) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmp2yvpqr2_/libmongocrypt_1.13.2-1.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmp2yvpqr2_/libmongocrypt_1.13.2-1+deb13u1.dsc: no acceptable signature found diff -Nru libmongocrypt-1.13.2/debian/changelog libmongocrypt-1.13.2/debian/changelog --- libmongocrypt-1.13.2/debian/changelog 2025-04-11 04:41:45.000000000 +0000 +++ libmongocrypt-1.13.2/debian/changelog 2026-08-29 15:20:33.000000000 +0000 @@ -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 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 04:41:45.000000000 +0000 +++ libmongocrypt-1.13.2/debian/gbp.conf 2026-08-29 15:20:33.000000000 +0000 @@ -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 1970-01-01 00:00:00.000000000 +0000 +++ libmongocrypt-1.13.2/debian/patches/0001_CVE-2026-81523.patch 2026-08-29 15:20:33.000000000 +0000 @@ -0,0 +1,273 @@ +From 0f8d744a8c5e1877e40efd1c8b440e4eed1e2462 Mon Sep 17 00:00:00 2001 +From: Kevin Albertson +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 "." + 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 1970-01-01 00:00:00.000000000 +0000 +++ libmongocrypt-1.13.2/debian/patches/series 2026-08-29 15:20:33.000000000 +0000 @@ -0,0 +1 @@ +0001_CVE-2026-81523.patch