diff --git a/Cargo.lock b/Cargo.lock index 7893ac11..a698910e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -128,9 +128,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.24" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d615619615a650c571269c00dca41db04b9210037fa76ed8239f70404ab56985" +checksum = "40f6024f3f856663b45fd0c9b6f2024034a702f453549449e0d84a305900dad4" dependencies = [ "brotli", "flate2", @@ -138,6 +138,8 @@ dependencies = [ "memchr", "pin-project-lite", "tokio", + "zstd", + "zstd-safe", ] [[package]] @@ -182,7 +184,7 @@ dependencies = [ "futures-lite", "parking", "polling", - "rustix 1.0.7", + "rustix", "slab", "tracing", "windows-sys 0.59.0", @@ -214,7 +216,7 @@ dependencies = [ "cfg-if", "event-listener 5.4.0", "futures-lite", - "rustix 1.0.7", + "rustix", "tracing", ] @@ -230,7 +232,7 @@ dependencies = [ "cfg-if", "futures-core", "futures-io", - "rustix 1.0.7", + "rustix", "signal-hook-registry", "slab", "windows-sys 0.59.0", @@ -310,9 +312,9 @@ checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" [[package]] name = "atomic" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994" +checksum = "a89cbf775b137e9b968e67227ef7f775587cde3fd31b0d8599dbd0f598a48340" dependencies = [ "bytemuck", ] @@ -325,15 +327,15 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "aws-config" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455e9fb7743c6f6267eb2830ccc08686fbb3d13c9a689369562fd4d4ef9ea462" +checksum = "c18d005c70d2b9c0c1ea8876c039db0ec7fb71164d25c73ccea21bf41fd02171" dependencies = [ "aws-credential-types", "aws-runtime", @@ -371,29 +373,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "aws-lc-rs" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fcc8f365936c834db5514fc45aee5b1202d677e6b40e48468aaaa8183ca8c7" -dependencies = [ - "aws-lc-sys", - "zeroize", -] - -[[package]] -name = "aws-lc-sys" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61b1d86e7705efe1be1b569bab41d4fa1e14e220b60a160f78de2db687add079" -dependencies = [ - "bindgen", - "cc", - "cmake", - "dunce", - "fs_extra", -] - [[package]] name = "aws-runtime" version = "1.5.8" @@ -420,9 +399,9 @@ dependencies = [ [[package]] name = "aws-sdk-sso" -version = "1.73.0" +version = "1.74.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ac1674cba7872061a29baaf02209fefe499ff034dfd91bd4cc59e4d7741489" +checksum = "e0a69de9c1b9272da2872af60c7402683e7f45c06267735b4332deacb203239b" dependencies = [ "aws-credential-types", "aws-runtime", @@ -442,9 +421,9 @@ dependencies = [ [[package]] name = "aws-sdk-ssooidc" -version = "1.74.0" +version = "1.75.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a6a22f077f5fd3e3c0270d4e1a110346cddf6769e9433eb9e6daceb4ca3b149" +checksum = "f0b161d836fac72bdd5ac1a4cd1cdc38ab888c7af26cfd95f661be4409505e63" dependencies = [ "aws-credential-types", "aws-runtime", @@ -464,9 +443,9 @@ dependencies = [ [[package]] name = "aws-sdk-sts" -version = "1.74.0" +version = "1.76.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d440e1d368759bd10df0dbdddbfff6473d7cd73e9d9ef2363dc9995ac2d711" +checksum = "cb1cd79a3412751a341a28e2cd0d6fa4345241976da427b075a0c0cd5409f886" dependencies = [ "aws-credential-types", "aws-runtime", @@ -538,29 +517,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "aws-smithy-http-client" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f491388e741b7ca73b24130ff464c1478acc34d5b331b7dd0a2ee4643595a15" -dependencies = [ - "aws-smithy-async", - "aws-smithy-runtime-api", - "aws-smithy-types", - "h2", - "http 1.3.1", - "hyper 1.6.0", - "hyper-rustls", - "hyper-util", - "pin-project-lite", - "rustls 0.23.28", - "rustls-native-certs", - "rustls-pki-types", - "tokio", - "tower", - "tracing", -] - [[package]] name = "aws-smithy-json" version = "0.61.4" @@ -597,7 +553,6 @@ checksum = "14302f06d1d5b7d333fd819943075b13d27c7700b414f574c3c35859bfb55d5e" dependencies = [ "aws-smithy-async", "aws-smithy-http", - "aws-smithy-http-client", "aws-smithy-observability", "aws-smithy-runtime-api", "aws-smithy-types", @@ -761,29 +716,6 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "383d29d513d8764dcdc42ea295d979eb99c3c9f00607b3692cf68a431f7dca72" -[[package]] -name = "bindgen" -version = "0.69.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" -dependencies = [ - "bitflags", - "cexpr", - "clang-sys", - "itertools 0.12.1", - "lazy_static", - "lazycell", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash 1.1.0", - "shlex", - "syn", - "which 4.4.2", -] - [[package]] name = "bitflags" version = "2.9.1" @@ -853,9 +785,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.18.1" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytecount" @@ -978,15 +910,6 @@ dependencies = [ "shlex", ] -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom 7.1.3", -] - [[package]] name = "cfg-if" version = "1.0.1" @@ -1055,26 +978,6 @@ dependencies = [ "inout", ] -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -name = "cmake" -version = "0.1.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" -dependencies = [ - "cc", -] - [[package]] name = "codemap" version = "0.1.3" @@ -1241,9 +1144,9 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "crypto-bigint" @@ -1476,9 +1379,9 @@ dependencies = [ [[package]] name = "diesel" -version = "2.2.10" +version = "2.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff3e1edb1f37b4953dd5176916347289ed43d7119cc2e6c7c3f7849ff44ea506" +checksum = "a917a9209950404d5be011c81d081a2692a822f73c3d6af586f0cab5ff50f614" dependencies = [ "bigdecimal", "bitflags", @@ -1511,9 +1414,9 @@ dependencies = [ [[package]] name = "diesel_derives" -version = "2.2.5" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68d4216021b3ea446fd2047f5c8f8fe6e98af34508a254a01e4d6bc1e844f84d" +checksum = "52841e97814f407b895d836fa0012091dff79c6268f39ad8155d384c21ae0d26" dependencies = [ "diesel_table_macro_syntax", "dsl_auto_type", @@ -1613,12 +1516,6 @@ dependencies = [ "syn", ] -[[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - [[package]] name = "dyn-clone" version = "1.0.19" @@ -1744,12 +1641,12 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -1828,7 +1725,7 @@ version = "0.10.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8cb01cd46b0cf372153850f4c6c272d9cbea2da513e07538405148f95bd789f3" dependencies = [ - "atomic 0.6.0", + "atomic 0.6.1", "pear", "serde", "toml", @@ -1882,12 +1779,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "fs_extra" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" - [[package]] name = "futures" version = "0.3.31" @@ -2115,7 +2006,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d9e3df7f0222ce5184154973d247c591d9aadc28ce7a73c6cd31100c9facff6" dependencies = [ "codemap", - "indexmap 2.9.0", + "indexmap 2.10.0", "lasso", "once_cell", "phf", @@ -2134,9 +2025,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5" +checksum = "17da50a276f1e01e0ba6c029e47b7100754904ee8a278f886546e98575380785" dependencies = [ "atomic-waker", "bytes", @@ -2144,7 +2035,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.3.1", - "indexmap 2.9.0", + "indexmap 2.10.0", "slab", "tokio", "tokio-util", @@ -2633,9 +2524,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" dependencies = [ "equivalent", "hashbrown 0.15.4", @@ -2658,6 +2549,17 @@ dependencies = [ "generic-array", ] +[[package]] +name = "io-uring" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013" +dependencies = [ + "bitflags", + "cfg-if", + "libc", +] + [[package]] name = "ipconfig" version = "0.3.2" @@ -2706,15 +2608,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.15" @@ -2800,12 +2693,6 @@ dependencies = [ "spin", ] -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - [[package]] name = "lettre" version = "0.11.17" @@ -2825,33 +2712,24 @@ dependencies = [ "httpdate", "idna", "mime", - "native-tls", "nom 8.0.0", "percent-encoding", "quoted_printable", + "rustls 0.23.28", + "rustls-native-certs", "serde", "socket2", "tokio", - "tokio-native-tls", + "tokio-rustls 0.26.2", "tracing", "url", ] [[package]] name = "libc" -version = "0.2.173" +version = "0.2.174" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8cfeafaffdbc32176b64fb251369d52ea9f0a8fbc6f8759edffef7b525d64bb" - -[[package]] -name = "libloading" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" -dependencies = [ - "cfg-if", - "windows-targets 0.53.2", -] +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" [[package]] name = "libm" @@ -2880,12 +2758,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - [[package]] name = "linux-raw-sys" version = "0.9.4" @@ -3107,9 +2979,9 @@ dependencies = [ [[package]] name = "mysqlclient-sys" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "412e0aff71806497f00e54197abc1c68b462f1c3096648214dfb276b4b804004" +checksum = "86a34a2bdec189f1060343ba712983e14cad7e87515cfd9ac4653e207535b6b1" dependencies = [ "pkg-config", "semver", @@ -3356,7 +3228,7 @@ dependencies = [ "ed25519-dalek", "hmac", "http 1.3.1", - "itertools 0.10.5", + "itertools", "log", "oauth2", "p256", @@ -3409,9 +3281,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-src" -version = "300.5.0+3.5.0" +version = "300.5.1+3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8ce546f549326b0e6052b649198487d91320875da901e7bd11a06d1ee3f9c2f" +checksum = "735230c832b28c000e3bc117119e6466a663ec73506bc0a9907ea4187508e42a" dependencies = [ "cc", ] @@ -3782,7 +3654,7 @@ dependencies = [ "concurrent-queue", "hermit-abi", "pin-project-lite", - "rustix 1.0.7", + "rustix", "tracing", "windows-sys 0.59.0", ] @@ -3827,16 +3699,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "prettyplease" -version = "0.2.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6837b9e10d61f45f987d50808f83d1ee3d206c66acf650c3e4ae2e1f6ddedf55" -dependencies = [ - "proc-macro2", - "syn", -] - [[package]] name = "primeorder" version = "0.13.6" @@ -3919,6 +3781,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + [[package]] name = "quick-xml" version = "0.37.5" @@ -3940,7 +3808,7 @@ dependencies = [ "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash 2.1.1", + "rustc-hash", "rustls 0.23.28", "socket2", "thiserror 2.0.12", @@ -3960,7 +3828,7 @@ dependencies = [ "lru-slab", "rand 0.9.1", "ring", - "rustc-hash 2.1.1", + "rustc-hash", "rustls 0.23.28", "rustls-pki-types", "slab", @@ -3972,9 +3840,9 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.12" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee4e529991f949c5e25755532370b8af5d114acae52326361d68d47af64aa842" +checksum = "fcebb1209ee276352ef14ff8732e24cc2b02bbac986cd74a4c81bcb2f9881970" dependencies = [ "cfg_aliases", "libc", @@ -4001,9 +3869,9 @@ checksum = "640c9bd8497b02465aeef5375144c26062e0dcd5939dfcbb0f5db76cb8c17c73" [[package]] name = "r-efi" -version = "5.2.0" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "r2d2" @@ -4176,9 +4044,9 @@ dependencies = [ [[package]] name = "reqsign" -version = "0.16.3" +version = "0.16.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9323c0afb30e54f793f4705b10c890395bccc87c6e6ea62c4e7e82d09a380dc6" +checksum = "43451dbf3590a7590684c25fb8d12ecdcc90ed3ac123433e500447c7d77ed701" dependencies = [ "anyhow", "async-trait", @@ -4203,14 +4071,15 @@ dependencies = [ "serde_json", "sha1", "sha2", + "tokio", "toml", ] [[package]] name = "reqwest" -version = "0.12.20" +version = "0.12.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabf4c97d9130e2bf606614eb937e86edac8292eaa6f422f995d7e8de1eb1813" +checksum = "cbc931937e6ca3a06e3b6c0aa7841849b160a90351d6ab467a8b9b9959767531" dependencies = [ "async-compression", "base64 0.22.1", @@ -4237,6 +4106,7 @@ dependencies = [ "pin-project-lite", "quinn", "rustls 0.23.28", + "rustls-native-certs", "rustls-pki-types", "serde", "serde_json", @@ -4322,7 +4192,7 @@ dependencies = [ "either", "figment", "futures", - "indexmap 2.9.0", + "indexmap 2.10.0", "log", "memchr", "multer", @@ -4354,7 +4224,7 @@ checksum = "575d32d7ec1a9770108c879fc7c47815a80073f96ca07ff9525a94fcede1dd46" dependencies = [ "devise", "glob", - "indexmap 2.9.0", + "indexmap 2.10.0", "proc-macro2", "quote", "rocket_http", @@ -4374,7 +4244,7 @@ dependencies = [ "futures", "http 0.2.12", "hyper 0.14.32", - "indexmap 2.9.0", + "indexmap 2.10.0", "log", "memchr", "pear", @@ -4462,12 +4332,6 @@ version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - [[package]] name = "rustc-hash" version = "2.1.1" @@ -4483,19 +4347,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", -] - [[package]] name = "rustix" version = "1.0.7" @@ -4505,7 +4356,7 @@ dependencies = [ "bitflags", "errno", "libc", - "linux-raw-sys 0.9.4", + "linux-raw-sys", "windows-sys 0.59.0", ] @@ -4527,7 +4378,7 @@ version = "0.23.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7160e3e10bf4535308537f3c4e1641468cd0e485175d6163087c0393c7d46643" dependencies = [ - "aws-lc-rs", + "log", "once_cell", "ring", "rustls-pki-types", @@ -4583,7 +4434,6 @@ version = "0.103.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" dependencies = [ - "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -4649,6 +4499,18 @@ dependencies = [ "serde_json", ] +[[package]] +name = "schemars" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1375ba8ef45a6f15d83fa8748f1079428295d403d6ea991d09ab100155fbc06d" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + [[package]] name = "scoped-tls" version = "1.0.1" @@ -4835,16 +4697,17 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf65a400f8f66fb7b0552869ad70157166676db75ed8181f8104ea91cf9d0b42" +checksum = "f2c45cd61fefa9db6f254525d46e392b852e0e61d9a1fd36e5bd183450a556d5" dependencies = [ "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.9.0", - "schemars", + "indexmap 2.10.0", + "schemars 0.9.0", + "schemars 1.0.3", "serde", "serde_derive", "serde_json", @@ -4854,9 +4717,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81679d9ed988d5e9a5e6531dc3f2c28efbd639cbd1dfb628df08edea6004da77" +checksum = "de90945e6565ce0d9a25098082ed4ee4002e047cb59892c318d66821e14bb30f" dependencies = [ "darling", "proc-macro2", @@ -5059,11 +4922,25 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "svg-hush" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d647e9386e34dd750ba80bdb7dae2a2c50b78338515ffeb9fa7bdd3ef803bf2" +dependencies = [ + "base64 0.22.1", + "data-url", + "once_cell", + "quick-error", + "url", + "xml-rs", +] + [[package]] name = "syn" -version = "2.0.103" +version = "2.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4307e30089d6fd6aff212f2da3a1f9e32f3223b1f010fb09b7c95f90f3ca1e8" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" dependencies = [ "proc-macro2", "quote", @@ -5138,7 +5015,7 @@ dependencies = [ "fastrand", "getrandom 0.3.3", "once_cell", - "rustix 1.0.7", + "rustix", "windows-sys 0.59.0", ] @@ -5269,17 +5146,19 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.45.1" +version = "1.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" +checksum = "1140bb80481756a8cbe10541f37433b459c5aa1e727b4c020fbfebdc25bf3ec4" dependencies = [ "backtrace", "bytes", + "io-uring", "libc", "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", + "slab", "socket2", "tokio-macros", "windows-sys 0.52.0", @@ -5390,7 +5269,7 @@ version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.9.0", + "indexmap 2.10.0", "serde", "serde_spanned", "toml_datetime", @@ -5475,9 +5354,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.29" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", @@ -5677,6 +5556,7 @@ dependencies = [ "argon2", "aws-config", "aws-credential-types", + "aws-smithy-runtime-api", "bigdecimal", "bytes", "cached", @@ -5701,6 +5581,7 @@ dependencies = [ "handlebars", "hickory-resolver", "html5gum", + "http 1.3.1", "job_scheduler_ng", "jsonwebtoken", "lettre", @@ -5731,6 +5612,7 @@ dependencies = [ "serde", "serde_json", "subtle", + "svg-hush", "syslog", "time", "tokio", @@ -5740,7 +5622,7 @@ dependencies = [ "url", "uuid", "webauthn-rs", - "which 8.0.0", + "which", "yubico_ng", ] @@ -5921,25 +5803,13 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" +checksum = "8782dd5a41a24eed3a4f40b606249b3e236ca61adf1f25ea4d45c73de122b502" dependencies = [ "rustls-pki-types", ] -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix 0.38.44", -] - [[package]] name = "which" version = "8.0.0" @@ -5947,7 +5817,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3fabb953106c3c8eea8306e4393700d7657561cb43122571b172bbfb7c7ba1d" dependencies = [ "env_home", - "rustix 1.0.7", + "rustix", "winsafe", ] @@ -6083,9 +5953,9 @@ dependencies = [ [[package]] name = "windows-registry" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3bab093bdd303a1240bb99b8aba8ea8a69ee19d34c9e2ef9594e708a4878820" +checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" dependencies = [ "windows-link", "windows-result", @@ -6137,6 +6007,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.2", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -6380,6 +6259,12 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +[[package]] +name = "xml-rs" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62ce76d9b56901b19a74f19431b0d8b3bc7ca4ad685a746dfd78ca8f4fc6bda" + [[package]] name = "xmlparser" version = "0.13.6" @@ -6437,18 +6322,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.25" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.25" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", @@ -6514,3 +6399,31 @@ dependencies = [ "quote", "syn", ] + +[[package]] +name = "zstd" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.15+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml index 5b147df9..39c14980 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ name = "vaultwarden" version = "1.0.0" authors = ["Daniel GarcĂ­a "] edition = "2021" -rust-version = "1.85.0" +rust-version = "1.86.0" resolver = "2" repository = "https://github.com/dani-garcia/vaultwarden" @@ -32,7 +32,7 @@ enable_mimalloc = ["dep:mimalloc"] # You also need to set an env variable `QUERY_LOGGER=1` to fully activate this so you do not have to re-compile # if you want to turn off the logging for a specific run. query_logger = ["dep:diesel_logger"] -s3 = ["opendal/services-s3", "dep:aws-config", "dep:aws-credential-types", "dep:anyhow", "dep:reqsign"] +s3 = ["opendal/services-s3", "dep:aws-config", "dep:aws-credential-types", "dep:aws-smithy-runtime-api", "dep:anyhow", "dep:http", "dep:reqsign"] # OIDC specific features oidc-accept-rfc3339-timestamps = ["openidconnect/accept-rfc3339-timestamps"] @@ -85,7 +85,7 @@ serde = { version = "1.0.219", features = ["derive"] } serde_json = "1.0.140" # A safe, extensible ORM and Query builder -diesel = { version = "2.2.10", features = ["chrono", "r2d2", "numeric"] } +diesel = { version = "2.2.11", features = ["chrono", "r2d2", "numeric"] } diesel_migrations = "2.2.0" diesel_logger = { version = "0.4.0", optional = true } @@ -130,7 +130,7 @@ webauthn-rs = "0.3.2" url = "2.5.4" # Email libraries -lettre = { version = "0.11.17", features = ["smtp-transport", "sendmail-transport", "builder", "serde", "tokio1-native-tls", "hostname", "tracing", "tokio1"], default-features = false } +lettre = { version = "0.11.17", features = ["smtp-transport", "sendmail-transport", "builder", "serde", "hostname", "tracing", "tokio1-rustls", "ring", "rustls-native-certs"], default-features = false } percent-encoding = "2.3.1" # URL encoding library used for URL's in the emails email_address = "0.2.9" @@ -138,7 +138,7 @@ email_address = "0.2.9" handlebars = { version = "6.3.2", features = ["dir_source"] } # HTTP client (Used for favicons, version check, DUO and HIBP API) -reqwest = { version = "0.12.20", features = ["native-tls-alpn", "stream", "json", "gzip", "brotli", "socks", "cookies"] } +reqwest = { version = "0.12.20", features = ["rustls-tls", "rustls-tls-native-roots", "stream", "json", "deflate", "gzip", "brotli", "zstd", "socks", "cookies", "charset", "http2", "system-proxy"], default-features = false} hickory-resolver = "0.25.2" # Favicon extraction libraries @@ -146,6 +146,7 @@ html5gum = "0.7.0" regex = { version = "1.11.1", features = ["std", "perf", "unicode-perl"], default-features = false } data-url = "0.3.1" bytes = "1.10.1" +svg-hush = "0.9.5" # Cache function results (Used for version check and favicon fetching) cached = { version = "0.55.1", features = ["async"] } @@ -173,7 +174,7 @@ semver = "1.0.26" # Allow overriding the default memory allocator # Mainly used for the musl builds, since the default musl malloc is very slow -mimalloc = { version = "0.1.46", features = ["secure"], default-features = false, optional = true } +mimalloc = { version = "0.1.47", features = ["secure"], default-features = false, optional = true } which = "8.0.0" @@ -187,13 +188,15 @@ rpassword = "7.4.0" grass_compiler = { version = "0.13.4", default-features = false } # File are accessed through Apache OpenDAL -opendal = { version = "0.53.3", features = ["services-fs"] } +opendal = { version = "0.53.3", features = ["services-fs"], default-features = false } # For retrieving AWS credentials, including temporary SSO credentials anyhow = { version = "1.0.98", optional = true } -aws-config = { version = "1.8.0", features = ["behavior-version-latest"], optional = true } +aws-config = { version = "1.8.0", features = ["behavior-version-latest", "rt-tokio", "credentials-process", "sso"], default-features = false, optional = true } aws-credential-types = { version = "1.2.3", optional = true } -reqsign = { version = "0.16.3", optional = true } +aws-smithy-runtime-api = { version = "1.8.1", optional = true } +http = { version = "1.3.1", optional = true } +reqsign = { version = "0.16.5", optional = true } # Strip debuginfo from the release builds # The debug symbols are to provide better panic traces @@ -284,7 +287,6 @@ macro_use_imports = "deny" manual_assert = "deny" manual_instant_elapsed = "deny" manual_string_new = "deny" -match_on_vec_items = "deny" match_wildcard_for_single_variants = "deny" mem_forget = "deny" needless_continue = "deny" diff --git a/docker/DockerSettings.yaml b/docker/DockerSettings.yaml index 355d4ac5..e7b9f185 100644 --- a/docker/DockerSettings.yaml +++ b/docker/DockerSettings.yaml @@ -5,7 +5,7 @@ vault_image_digest: "sha256:494be10bd99d9d05c7bec13dad71ad99102ea920de9a5d358752 # We use the linux/amd64 platform shell scripts since there is no difference between the different platform scripts # https://github.com/tonistiigi/xx | https://hub.docker.com/r/tonistiigi/xx/tags xx_image_digest: "sha256:9c207bead753dda9430bdd15425c6518fc7a03d866103c516a2c6889188f5894" -rust_version: 1.87.0 # Rust version to be used +rust_version: 1.88.0 # Rust version to be used debian_version: bookworm # Debian release name to be used alpine_version: "3.22" # Alpine version to be used # For which platforms/architectures will we try to build images diff --git a/docker/Dockerfile.alpine b/docker/Dockerfile.alpine index 3211b096..70388bfd 100644 --- a/docker/Dockerfile.alpine +++ b/docker/Dockerfile.alpine @@ -32,10 +32,10 @@ FROM --platform=linux/amd64 docker.io/vaultwarden/web-vault@sha256:494be10bd99d9 ########################## ALPINE BUILD IMAGES ########################## ## NOTE: The Alpine Base Images do not support other platforms then linux/amd64 ## And for Alpine we define all build images here, they will only be loaded when actually used -FROM --platform=linux/amd64 ghcr.io/blackdex/rust-musl:x86_64-musl-stable-1.87.0 AS build_amd64 -FROM --platform=linux/amd64 ghcr.io/blackdex/rust-musl:aarch64-musl-stable-1.87.0 AS build_arm64 -FROM --platform=linux/amd64 ghcr.io/blackdex/rust-musl:armv7-musleabihf-stable-1.87.0 AS build_armv7 -FROM --platform=linux/amd64 ghcr.io/blackdex/rust-musl:arm-musleabi-stable-1.87.0 AS build_armv6 +FROM --platform=linux/amd64 ghcr.io/blackdex/rust-musl:x86_64-musl-stable-1.88.0 AS build_amd64 +FROM --platform=linux/amd64 ghcr.io/blackdex/rust-musl:aarch64-musl-stable-1.88.0 AS build_arm64 +FROM --platform=linux/amd64 ghcr.io/blackdex/rust-musl:armv7-musleabihf-stable-1.88.0 AS build_armv7 +FROM --platform=linux/amd64 ghcr.io/blackdex/rust-musl:arm-musleabi-stable-1.88.0 AS build_armv6 ########################## BUILD IMAGE ########################## # hadolint ignore=DL3006 diff --git a/docker/Dockerfile.debian b/docker/Dockerfile.debian index 75fc82f0..d343cbff 100644 --- a/docker/Dockerfile.debian +++ b/docker/Dockerfile.debian @@ -36,7 +36,7 @@ FROM --platform=linux/amd64 docker.io/tonistiigi/xx@sha256:9c207bead753dda9430bd ########################## BUILD IMAGE ########################## # hadolint ignore=DL3006 -FROM --platform=$BUILDPLATFORM docker.io/library/rust:1.87.0-slim-bookworm AS build +FROM --platform=$BUILDPLATFORM docker.io/library/rust:1.88.0-slim-bookworm AS build COPY --from=xx / / ARG TARGETARCH ARG TARGETVARIANT diff --git a/macros/Cargo.toml b/macros/Cargo.toml index 2231a6ee..15f2f905 100644 --- a/macros/Cargo.toml +++ b/macros/Cargo.toml @@ -10,7 +10,7 @@ proc-macro = true [dependencies] quote = "1.0.40" -syn = "2.0.101" +syn = "2.0.104" [lints] workspace = true diff --git a/rust-toolchain.toml b/rust-toolchain.toml index c1ab6b32..e09e3cf7 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "1.87.0" +channel = "1.88.0" components = [ "rustfmt", "clippy" ] profile = "minimal" diff --git a/src/api/core/mod.rs b/src/api/core/mod.rs index 9ac8440a..43a29ed4 100644 --- a/src/api/core/mod.rs +++ b/src/api/core/mod.rs @@ -201,15 +201,17 @@ fn get_api_webauthn(_headers: Headers) -> Json { fn config() -> Json { let domain = crate::CONFIG.domain(); // Official available feature flags can be found here: - // Server (v2025.5.0): https://github.com/bitwarden/server/blob/4a7db112a0952c6df8bacf36c317e9c4e58c3651/src/Core/Constants.cs#L102 - // Client (v2025.5.0): https://github.com/bitwarden/clients/blob/9df8a3cc50ed45f52513e62c23fcc8a4b745f078/libs/common/src/enums/feature-flag.enum.ts#L10 - // Android (v2025.4.0): https://github.com/bitwarden/android/blob/bee09de972c3870de0d54a0067996be473ec55c7/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/model/FlagKey.kt#L27 - // iOS (v2025.4.0): https://github.com/bitwarden/ios/blob/956e05db67344c912e3a1b8cb2609165d67da1c9/BitwardenShared/Core/Platform/Models/Enum/FeatureFlag.swift#L7 + // Server (v2025.6.2): https://github.com/bitwarden/server/blob/d094be3267f2030bd0dc62106bc6871cf82682f5/src/Core/Constants.cs#L103 + // Client (web-v2025.6.1): https://github.com/bitwarden/clients/blob/747c2fd6a1c348a57a76e4a7de8128466ffd3c01/libs/common/src/enums/feature-flag.enum.ts#L12 + // Android (v2025.6.0): https://github.com/bitwarden/android/blob/b5b022caaad33390c31b3021b2c1205925b0e1a2/app/src/main/kotlin/com/x8bit/bitwarden/data/platform/manager/model/FlagKey.kt#L22 + // iOS (v2025.6.0): https://github.com/bitwarden/ios/blob/ff06d9c6cc8da89f78f37f376495800201d7261a/BitwardenShared/Core/Platform/Models/Enum/FeatureFlag.swift#L7 let mut feature_states = parse_experimental_client_feature_flags(&crate::CONFIG.experimental_client_feature_flags()); feature_states.insert("duo-redirect".to_string(), true); feature_states.insert("email-verification".to_string(), true); feature_states.insert("unauth-ui-refresh".to_string(), true); + feature_states.insert("enable-pm-flight-recorder".to_string(), true); + feature_states.insert("mobile-error-reporting".to_string(), true); Json(json!({ // Note: The clients use this version to handle backwards compatibility concerns @@ -217,7 +219,7 @@ fn config() -> Json { // We should make sure that we keep this updated when we support the new server features // Version history: // - Individual cipher key encryption: 2024.2.0 - "version": "2025.4.0", + "version": "2025.6.0", "gitHash": option_env!("GIT_REV"), "server": { "name": "Vaultwarden", diff --git a/src/api/core/two_factor/yubikey.rs b/src/api/core/two_factor/yubikey.rs index a6d9898d..293b211d 100644 --- a/src/api/core/two_factor/yubikey.rs +++ b/src/api/core/two_factor/yubikey.rs @@ -145,15 +145,14 @@ async fn activate_yubikey(data: Json, headers: Headers, mut c // Ensure they are valid OTPs for yubikey in &yubikeys { - if yubikey.len() == 12 { - // YubiKey ID + if yubikey.is_empty() || yubikey.len() == 12 { continue; } verify_yubikey_otp(yubikey.to_owned()).await.map_res("Invalid Yubikey OTP provided")?; } - let yubikey_ids: Vec = yubikeys.into_iter().map(|x| (x[..12]).to_owned()).collect(); + let yubikey_ids: Vec = yubikeys.into_iter().filter_map(|x| x.get(..12).map(str::to_owned)).collect(); let yubikey_metadata = YubikeyMetadata { keys: yubikey_ids, diff --git a/src/api/icons.rs b/src/api/icons.rs index acf3943e..30539c34 100644 --- a/src/api/icons.rs +++ b/src/api/icons.rs @@ -14,6 +14,7 @@ use reqwest::{ Client, Response, }; use rocket::{http::ContentType, response::Redirect, Route}; +use svg_hush::{data_url_filter, Filter}; use html5gum::{Emitter, HtmlString, Readable, StringReader, Tokenizer}; @@ -35,11 +36,29 @@ pub fn routes() -> Vec { static CLIENT: Lazy = Lazy::new(|| { // Generate the default headers let mut default_headers = HeaderMap::new(); - default_headers.insert(header::USER_AGENT, HeaderValue::from_static("Links (2.22; Linux X86_64; GNU C; text)")); - default_headers.insert(header::ACCEPT, HeaderValue::from_static("text/html, text/*;q=0.5, image/*, */*;q=0.1")); - default_headers.insert(header::ACCEPT_LANGUAGE, HeaderValue::from_static("en,*;q=0.1")); + default_headers.insert( + header::USER_AGENT, + HeaderValue::from_static( + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36", + ), + ); + default_headers.insert(header::ACCEPT, HeaderValue::from_static("text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7")); + default_headers.insert(header::ACCEPT_LANGUAGE, HeaderValue::from_static("en-US,en;q=0.9")); default_headers.insert(header::CACHE_CONTROL, HeaderValue::from_static("no-cache")); default_headers.insert(header::PRAGMA, HeaderValue::from_static("no-cache")); + default_headers.insert(header::UPGRADE_INSECURE_REQUESTS, HeaderValue::from_static("1")); + + default_headers.insert("Sec-Ch-Ua-Mobile", HeaderValue::from_static("?0")); + default_headers.insert("Sec-Ch-Ua-Platform", HeaderValue::from_static("Linux")); + default_headers.insert( + "Sec-Ch-Ua", + HeaderValue::from_static("\"Not)A;Brand\";v=\"8\", \"Chromium\";v=\"138\", \"Google Chrome\";v=\"138\""), + ); + + default_headers.insert("Sec-Fetch-Site", HeaderValue::from_static("none")); + default_headers.insert("Sec-Fetch-Mode", HeaderValue::from_static("navigate")); + default_headers.insert("Sec-Fetch-User", HeaderValue::from_static("?1")); + default_headers.insert("Sec-Fetch-Dest", HeaderValue::from_static("document")); // Generate the cookie store let cookie_store = Arc::new(Jar::default()); @@ -53,6 +72,7 @@ static CLIENT: Lazy = Lazy::new(|| { .pool_max_idle_per_host(5) // Configure the Hyper Pool to only have max 5 idle connections .pool_idle_timeout(pool_idle_timeout) // Configure the Hyper Pool to timeout after 10 seconds .default_headers(default_headers.clone()) + .http1_title_case_headers() .build() .expect("Failed to build client") }); @@ -561,6 +581,16 @@ async fn download_icon(domain: &str) -> Result<(Bytes, Option<&str>), Error> { if buffer.is_empty() { err_silent!("Empty response or unable find a valid icon", domain); + } else if icon_type == Some("svg+xml") { + let mut svg_filter = Filter::new(); + svg_filter.set_data_url_filter(data_url_filter::allow_standard_images); + let mut sanitized_svg = Vec::new(); + if svg_filter.filter(&*buffer, &mut sanitized_svg).is_err() { + icon_type = None; + buffer.clear(); + } else { + buffer = sanitized_svg.into(); + } } Ok((buffer, icon_type)) @@ -581,6 +611,16 @@ async fn save_icon(path: &str, icon: Vec) { } fn get_icon_type(bytes: &[u8]) -> Option<&'static str> { + fn check_svg_after_xml_declaration(bytes: &[u8]) -> Option<&'static str> { + // Look for SVG tag within the first 1KB + if let Ok(content) = std::str::from_utf8(&bytes[..bytes.len().min(1024)]) { + if content.contains(" Some("png"), [0, 0, 1, 0, ..] => Some("x-icon"), @@ -588,6 +628,8 @@ fn get_icon_type(bytes: &[u8]) -> Option<&'static str> { [255, 216, 255, ..] => Some("jpeg"), [71, 73, 70, 56, ..] => Some("gif"), [66, 77, ..] => Some("bmp"), + [60, 115, 118, 103, ..] => Some("svg+xml"), // Normal svg + [60, 63, 120, 109, 108, ..] => check_svg_after_xml_declaration(bytes), // An svg starting with None, } } @@ -599,6 +641,12 @@ async fn stream_to_bytes_limit(res: Response, max_size: usize) -> Result Result<(), Error> { } } - // Server (v2025.5.0): https://github.com/bitwarden/server/blob/4a7db112a0952c6df8bacf36c317e9c4e58c3651/src/Core/Constants.cs#L102 - // Client (v2025.5.0): https://github.com/bitwarden/clients/blob/9df8a3cc50ed45f52513e62c23fcc8a4b745f078/libs/common/src/enums/feature-flag.enum.ts#L10 - // Android (v2025.4.0): https://github.com/bitwarden/android/blob/bee09de972c3870de0d54a0067996be473ec55c7/app/src/main/java/com/x8bit/bitwarden/data/platform/manager/model/FlagKey.kt#L27 - // iOS (v2025.4.0): https://github.com/bitwarden/ios/blob/956e05db67344c912e3a1b8cb2609165d67da1c9/BitwardenShared/Core/Platform/Models/Enum/FeatureFlag.swift#L7 + // Server (v2025.6.2): https://github.com/bitwarden/server/blob/d094be3267f2030bd0dc62106bc6871cf82682f5/src/Core/Constants.cs#L103 + // Client (web-v2025.6.1): https://github.com/bitwarden/clients/blob/747c2fd6a1c348a57a76e4a7de8128466ffd3c01/libs/common/src/enums/feature-flag.enum.ts#L12 + // Android (v2025.6.0): https://github.com/bitwarden/android/blob/b5b022caaad33390c31b3021b2c1205925b0e1a2/app/src/main/kotlin/com/x8bit/bitwarden/data/platform/manager/model/FlagKey.kt#L22 + // iOS (v2025.6.0): https://github.com/bitwarden/ios/blob/ff06d9c6cc8da89f78f37f376495800201d7261a/BitwardenShared/Core/Platform/Models/Enum/FeatureFlag.swift#L7 // // NOTE: Move deprecated flags to the utils::parse_experimental_client_feature_flags() DEPRECATED_FLAGS const! const KNOWN_FLAGS: &[&str] = &[ @@ -1291,6 +1291,9 @@ fn opendal_operator_for_path(path: &str) -> Result { #[cfg(s3)] fn opendal_s3_operator_for_path(path: &str) -> Result { + use crate::http_client::aws::AwsReqwestConnector; + use aws_config::{default_provider::credentials::DefaultCredentialsChain, provider_config::ProviderConfig}; + // This is a custom AWS credential loader that uses the official AWS Rust // SDK config crate to load credentials. This ensures maximum compatibility // with AWS credential configurations. For example, OpenDAL doesn't support @@ -1303,12 +1306,19 @@ fn opendal_s3_operator_for_path(path: &str) -> Result use aws_credential_types::provider::ProvideCredentials as _; use tokio::sync::OnceCell; - static DEFAULT_CREDENTIAL_CHAIN: OnceCell< - aws_config::default_provider::credentials::DefaultCredentialsChain, - > = OnceCell::const_new(); + static DEFAULT_CREDENTIAL_CHAIN: OnceCell = OnceCell::const_new(); let chain = DEFAULT_CREDENTIAL_CHAIN - .get_or_init(|| aws_config::default_provider::credentials::DefaultCredentialsChain::builder().build()) + .get_or_init(|| { + let reqwest_client = reqwest::Client::builder().build().unwrap(); + let connector = AwsReqwestConnector { + client: reqwest_client, + }; + + let conf = ProviderConfig::default().with_http_client(connector); + + DefaultCredentialsChain::builder().configure(conf).build() + }) .await; let creds = chain.provide_credentials().await?; diff --git a/src/db/models/cipher.rs b/src/db/models/cipher.rs index f9b4b2cf..5e8971c8 100644 --- a/src/db/models/cipher.rs +++ b/src/db/models/cipher.rs @@ -382,6 +382,11 @@ impl Cipher { // the "Read Only" or "Hide Passwords" restrictions for the user. json_object["edit"] = json!(!read_only); json_object["viewPassword"] = json!(!hide_passwords); + // The new key used by clients since v2025.6.0 + json_object["permissions"] = json!({ + "delete": !read_only, + "restore": !read_only, + }); } let key = match self.atype { diff --git a/src/http_client.rs b/src/http_client.rs index 5feeeedd..fc3b1b42 100644 --- a/src/http_client.rs +++ b/src/http_client.rs @@ -244,3 +244,61 @@ impl Resolve for CustomDnsResolver { }) } } + +#[cfg(s3)] +pub(crate) mod aws { + use aws_smithy_runtime_api::client::{ + http::{HttpClient, HttpConnector, HttpConnectorFuture, HttpConnectorSettings, SharedHttpConnector}, + orchestrator::HttpResponse, + result::ConnectorError, + runtime_components::RuntimeComponents, + }; + use reqwest::Client; + + // Adapter that wraps reqwest to be compatible with the AWS SDK + #[derive(Debug)] + pub(crate) struct AwsReqwestConnector { + pub(crate) client: Client, + } + + impl HttpConnector for AwsReqwestConnector { + fn call(&self, request: aws_smithy_runtime_api::client::orchestrator::HttpRequest) -> HttpConnectorFuture { + // Convert the AWS-style request to a reqwest request + let client = self.client.clone(); + let future = async move { + let method = reqwest::Method::from_bytes(request.method().as_bytes()) + .map_err(|e| ConnectorError::user(Box::new(e)))?; + let mut req_builder = client.request(method, request.uri().to_string()); + + for (name, value) in request.headers() { + req_builder = req_builder.header(name, value); + } + + if let Some(body_bytes) = request.body().bytes() { + req_builder = req_builder.body(body_bytes.to_vec()); + } + + let response = req_builder.send().await.map_err(|e| ConnectorError::io(Box::new(e)))?; + + let status = response.status().into(); + let bytes = response.bytes().await.map_err(|e| ConnectorError::io(Box::new(e)))?; + + Ok(HttpResponse::new(status, bytes.into())) + }; + + HttpConnectorFuture::new(Box::pin(future)) + } + } + + impl HttpClient for AwsReqwestConnector { + fn http_connector( + &self, + _settings: &HttpConnectorSettings, + _components: &RuntimeComponents, + ) -> SharedHttpConnector { + SharedHttpConnector::new(AwsReqwestConnector { + client: self.client.clone(), + }) + } + } +} diff --git a/src/sso.rs b/src/sso.rs index 012beeac..bf998fe7 100644 --- a/src/sso.rs +++ b/src/sso.rs @@ -295,7 +295,7 @@ pub async fn authorize_url( "cli" => { let port_regex = Regex::new(r"^http://localhost:([0-9]{4})$").unwrap(); match port_regex.captures(raw_redirect_uri).and_then(|captures| captures.get(1).map(|c| c.as_str())) { - Some(port) => format!("http://localhost:{}", port), + Some(port) => format!("http://localhost:{port}"), None => err!("Failed to extract port number"), } } @@ -351,7 +351,7 @@ pub struct OIDCIdentifier(String); impl OIDCIdentifier { fn new(issuer: &str, subject: &str) -> Self { - OIDCIdentifier(format!("{}/{}", issuer, subject)) + OIDCIdentifier(format!("{issuer}/{subject}")) } } @@ -554,11 +554,11 @@ fn _create_auth_tokens( Err(_) => { let time_now = Utc::now(); let exp = (time_now + *DEFAULT_REFRESH_VALIDITY).timestamp(); - debug!("Non jwt refresh_token (expiration set to {})", exp); + debug!("Non jwt refresh_token (expiration set to {exp})"); (time_now.timestamp(), exp, TokenWrapper::Refresh(rt)) } Ok(refresh_payload) => { - debug!("Refresh_payload: {:?}", refresh_payload); + debug!("Refresh_payload: {refresh_payload:?}"); (refresh_payload.nbf(), refresh_payload.exp, TokenWrapper::Refresh(rt)) } } diff --git a/src/util.rs b/src/util.rs index bf981c83..3048ff92 100644 --- a/src/util.rs +++ b/src/util.rs @@ -61,9 +61,11 @@ impl Fairing for AppHeaders { // The `Cross-Origin-Resource-Policy` header should not be set on images or on the `icon_external` route. // Otherwise some clients, like the Bitwarden Desktop, will fail to download the icons + let mut is_image = true; if !(res.headers().get_one("Content-Type").is_some_and(|v| v.starts_with("image/")) || req.route().is_some_and(|v| v.name.as_deref() == Some("icon_external"))) { + is_image = false; res.set_raw_header("Cross-Origin-Resource-Policy", "same-origin"); } @@ -71,49 +73,56 @@ impl Fairing for AppHeaders { // This can cause issues when some MFA requests needs to open a popup or page within the clients like WebAuthn, or Duo. // This is the same behavior as upstream Bitwarden. if !req_uri_path.ends_with("connector.html") { - // # Frame Ancestors: - // Chrome Web Store: https://chrome.google.com/webstore/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb - // Edge Add-ons: https://microsoftedge.microsoft.com/addons/detail/bitwarden-free-password/jbkfoedolllekgbhcbcoahefnbanhhlh?hl=en-US - // Firefox Browser Add-ons: https://addons.mozilla.org/en-US/firefox/addon/bitwarden-password-manager/ - // # img/child/frame src: - // Have I Been Pwned to allow those calls to work. - // # Connect src: - // Leaked Passwords check: api.pwnedpasswords.com - // 2FA/MFA Site check: api.2fa.directory - // # Mail Relay: https://bitwarden.com/blog/add-privacy-and-security-using-email-aliases-with-bitwarden/ - // app.simplelogin.io, app.addy.io, api.fastmail.com, quack.duckduckgo.com - let csp = format!( - "default-src 'none'; \ - font-src 'self'; \ - manifest-src 'self'; \ - base-uri 'self'; \ - form-action 'self'; \ - object-src 'self' blob:; \ - script-src 'self' 'wasm-unsafe-eval'; \ - style-src 'self' 'unsafe-inline'; \ - child-src 'self' https://*.duosecurity.com https://*.duofederal.com; \ - frame-src 'self' https://*.duosecurity.com https://*.duofederal.com; \ - frame-ancestors 'self' \ - chrome-extension://nngceckbapebfimnlniiiahkandclblb \ - chrome-extension://jbkfoedolllekgbhcbcoahefnbanhhlh \ - moz-extension://* \ - {allowed_iframe_ancestors}; \ - img-src 'self' data: \ - https://haveibeenpwned.com \ - {icon_service_csp}; \ - connect-src 'self' \ - https://api.pwnedpasswords.com \ - https://api.2fa.directory \ - https://app.simplelogin.io/api/ \ - https://app.addy.io/api/ \ - https://api.fastmail.com/ \ - https://api.forwardemail.net \ - {allowed_connect_src};\ - ", - icon_service_csp = CONFIG._icon_service_csp(), - allowed_iframe_ancestors = CONFIG.allowed_iframe_ancestors(), - allowed_connect_src = CONFIG.allowed_connect_src(), - ); + let csp = if is_image { + // Prevent scripts, frames, objects, etc., from loading with images, mainly for SVG images, since these could contain JavaScript and other unsafe items. + // Even though we sanitize SVG images before storing and viewing them, it's better to prevent allowing these elements. + String::from("default-src 'none'; img-src 'self' data:; style-src 'unsafe-inline'; script-src 'none'; frame-src 'none'; object-src 'none") + } else { + // # Frame Ancestors: + // Chrome Web Store: https://chrome.google.com/webstore/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb + // Edge Add-ons: https://microsoftedge.microsoft.com/addons/detail/bitwarden-free-password/jbkfoedolllekgbhcbcoahefnbanhhlh?hl=en-US + // Firefox Browser Add-ons: https://addons.mozilla.org/en-US/firefox/addon/bitwarden-password-manager/ + // # img/child/frame src: + // Have I Been Pwned to allow those calls to work. + // # Connect src: + // Leaked Passwords check: api.pwnedpasswords.com + // 2FA/MFA Site check: api.2fa.directory + // # Mail Relay: https://bitwarden.com/blog/add-privacy-and-security-using-email-aliases-with-bitwarden/ + // app.simplelogin.io, app.addy.io, api.fastmail.com, api.forwardemail.net + format!( + "default-src 'none'; \ + font-src 'self'; \ + manifest-src 'self'; \ + base-uri 'self'; \ + form-action 'self'; \ + object-src 'self' blob:; \ + script-src 'self' 'wasm-unsafe-eval'; \ + style-src 'self' 'unsafe-inline'; \ + child-src 'self' https://*.duosecurity.com https://*.duofederal.com; \ + frame-src 'self' https://*.duosecurity.com https://*.duofederal.com; \ + frame-ancestors 'self' \ + chrome-extension://nngceckbapebfimnlniiiahkandclblb \ + chrome-extension://jbkfoedolllekgbhcbcoahefnbanhhlh \ + moz-extension://* \ + {allowed_iframe_ancestors}; \ + img-src 'self' data: \ + https://haveibeenpwned.com \ + {icon_service_csp}; \ + connect-src 'self' \ + https://api.pwnedpasswords.com \ + https://api.2fa.directory \ + https://app.simplelogin.io/api/ \ + https://app.addy.io/api/ \ + https://api.fastmail.com/ \ + https://api.forwardemail.net \ + {allowed_connect_src};\ + ", + icon_service_csp = CONFIG._icon_service_csp(), + allowed_iframe_ancestors = CONFIG.allowed_iframe_ancestors(), + allowed_connect_src = CONFIG.allowed_connect_src(), + ) + }; + res.set_raw_header("Content-Security-Policy", csp); res.set_raw_header("X-Frame-Options", "SAMEORIGIN"); } else {