diff --git a/Cargo.lock b/Cargo.lock index 8d91fece..7965a0ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -67,6 +67,19 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "ammonia" +version = "4.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17e913097e1a2124b46746c980134e8c954bc17a6a59bb3fde96f088d126dde6" +dependencies = [ + "cssparser", + "html5ever", + "maplit", + "tendril", + "url", +] + [[package]] name = "anstream" version = "0.6.20" @@ -119,9 +132,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.99" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "async-trait" @@ -298,9 +311,9 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cc" -version = "1.2.36" +version = "1.2.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5252b3d2648e5eedbc1a6f501e3c795e07025c1e93bbf8bbdd6eef7f447a6d54" +checksum = "80f41ae168f955c12fb8960b057d70d0ca153fb83182b57d86380443527be7e9" dependencies = [ "find-msvc-tools", "jobserver", @@ -326,9 +339,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.47" +version = "4.5.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eac00902d9d136acd712710d71823fb8ac8004ca445a89e73a41d45aa712931" +checksum = "e2134bb3ea021b78629caa971416385309e0131b351b25e01dc16fb54e1b5fae" dependencies = [ "clap_builder", "clap_derive", @@ -336,9 +349,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.47" +version = "4.5.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ad9bbf750e73b5884fb8a211a9424a1906c1e156724260fdae972f31d70e1d6" +checksum = "c2ba64afa3c0a6df7fa517765e31314e983f51dda798ffba27b988194fb65dc9" dependencies = [ "anstream", "anstyle", @@ -436,6 +449,29 @@ dependencies = [ "typenum", ] +[[package]] +name = "cssparser" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e901edd733a1472f944a45116df3f846f54d37e67e68640ac8bb69689aca2aa" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf", + "smallvec", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn", +] + [[package]] name = "ctr" version = "0.9.2" @@ -502,8 +538,9 @@ checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" [[package]] name = "defguard-proxy" -version = "1.5.0" +version = "1.5.1" dependencies = [ + "ammonia", "anyhow", "axum", "axum-client-ip", @@ -620,6 +657,21 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" +[[package]] +name = "dtoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6add3b8cff394282be81f3fc1a0605db594ed69890078ca6e2cab1c408bcf04" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + [[package]] name = "either" version = "1.15.0" @@ -650,9 +702,9 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "find-msvc-tools" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fd99930f64d146689264c637b5af2f0233a933bef0d8570e2526bf9e083192d" +checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959" [[package]] name = "fixedbitset" @@ -701,6 +753,16 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + [[package]] name = "futures-channel" version = "0.3.31" @@ -791,7 +853,7 @@ dependencies = [ "js-sys", "libc", "r-efi", - "wasi 0.14.5+wasi-0.2.4", + "wasi 0.14.7+wasi-0.2.4", "wasm-bindgen", ] @@ -896,6 +958,12 @@ dependencies = [ "foldhash", ] +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + [[package]] name = "headers" version = "0.4.1" @@ -926,6 +994,17 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "html5ever" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55d958c2f74b664487a2035fe1dadb032c48718a03b63f3ab0b8537db8549ed4" +dependencies = [ + "log", + "markup5ever", + "match_token", +] + [[package]] name = "http" version = "1.3.1" @@ -1016,9 +1095,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" +checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" dependencies = [ "bytes", "futures-channel", @@ -1150,12 +1229,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.11.1" +version = "2.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206a8042aec68fa4a62e8d3f7aa4ceb508177d9324faf261e1959e495b7a1921" +checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" dependencies = [ "equivalent", - "hashbrown 0.15.5", + "hashbrown 0.16.0", ] [[package]] @@ -1211,9 +1290,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.78" +version = "0.3.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0b063578492ceec17683ef2f8c5e89121fbd0b172cbc280635ab7567db2738" +checksum = "852f13bec5eba4ba9afbeb93fd7c13fe56147f055939ae21c43a29a0ecb2702e" dependencies = [ "once_cell", "wasm-bindgen", @@ -1286,6 +1365,40 @@ dependencies = [ "serde", ] +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "maplit" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" + +[[package]] +name = "markup5ever" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "311fe69c934650f8f19652b3946075f0fc41ad8757dbb68f1ca14e7900ecc1c3" +dependencies = [ + "log", + "tendril", + "web_atoms", +] + +[[package]] +name = "match_token" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac84fd3f360fcc43dc5f5d186f02a94192761a080e8bc58621ad4d12296a58cf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "matchers" version = "0.2.0" @@ -1349,6 +1462,12 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + [[package]] name = "nonempty" version = "0.7.0" @@ -1469,6 +1588,58 @@ dependencies = [ "indexmap", ] +[[package]] +name = "phf" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +dependencies = [ + "phf_macros", + "phf_shared", +] + +[[package]] +name = "phf_codegen" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" +dependencies = [ + "phf_shared", + "rand 0.8.5", +] + +[[package]] +name = "phf_macros" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project" version = "1.1.10" @@ -1509,9 +1680,9 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "plist" -version = "1.7.4" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3af6b589e163c5a788fab00ce0c0366f6efbb9959c2f9874b224936af7fce7e1" +checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07" dependencies = [ "base64", "indexmap", @@ -1562,6 +1733,12 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + [[package]] name = "prettyplease" version = "0.2.37" @@ -1870,9 +2047,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.31" +version = "0.23.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" +checksum = "cd3c25631629d034ce7cd9940adc9d45762d46de2b0f57193c4443b92c6d4d40" dependencies = [ "log", "once_cell", @@ -1906,9 +2083,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.4" +version = "0.103.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" +checksum = "8572f3c2cb9934231157b45499fc41e1f58c589fdfb81a844ba873265e80f8eb" dependencies = [ "ring", "rustls-pki-types", @@ -1953,9 +2130,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "security-framework" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b369d18893388b345804dc0007963c99b7d665ae71d275812d828c6f089640" +checksum = "cc198e42d9b7510827939c9a15f5062a0c913f3371d765977e586d2fe6c16f4a" dependencies = [ "bitflags", "core-foundation", @@ -1976,27 +2153,38 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" dependencies = [ "serde", + "serde_core", ] [[package]] name = "serde" -version = "1.0.219" +version = "1.0.226" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dca6411025b24b60bfa7ec1fe1f8e710ac09782dca409ee8237ba74b51295fd" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.226" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "ba2ba63999edb9dac981fb34b3e5c0d111a69b0924e253ed29d83f7c99e966a4" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.226" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "8db53ae22f34573731bafa1db20f04027b2d25e02d8205921b569171699cdb33" dependencies = [ "proc-macro2", "quote", @@ -2005,33 +2193,35 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.143" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", "memchr", "ryu", "serde", + "serde_core", ] [[package]] name = "serde_path_to_error" -version = "0.1.17" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a" +checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" dependencies = [ "itoa", "serde", + "serde_core", ] [[package]] name = "serde_spanned" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83" +checksum = "5417783452c2be558477e104686f7de5dae53dba813c28435e0e70f82d9b04ee" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -2083,6 +2273,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + [[package]] name = "slab" version = "0.4.11" @@ -2120,6 +2316,31 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "string_cache" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" +dependencies = [ + "new_debug_unreachable", + "parking_lot", + "phf_shared", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", +] + [[package]] name = "strsim" version = "0.11.1" @@ -2162,9 +2383,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.22.0" +version = "3.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84fa4d11fadde498443cca10fd3ac23c951f0dc59e080e9f4b93d4df4e4eea53" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" dependencies = [ "fastrand", "getrandom 0.3.3", @@ -2173,6 +2394,17 @@ dependencies = [ "windows-sys 0.61.0", ] +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + [[package]] name = "thiserror" version = "1.0.69" @@ -2224,11 +2456,12 @@ dependencies = [ [[package]] name = "time" -version = "0.3.43" +version = "0.3.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83bde6f1ec10e72d583d91623c939f623002284ef622b87de38cfd546cbf2031" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" dependencies = [ "deranged", + "itoa", "libc", "num-conv", "num_threads", @@ -2295,9 +2528,9 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.2" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +checksum = "05f63835928ca123f1bef57abbcd23bb2ba0ac9ae1235f1e65bda0d06e7786bd" dependencies = [ "rustls", "tokio", @@ -2341,11 +2574,11 @@ dependencies = [ [[package]] name = "toml" -version = "0.9.5" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75129e1dc5000bfbaa9fee9d1b21f974f9fbad9daec557a521ee6e080825f6e8" +checksum = "00e5e5d9bf2475ac9d4f0d9edab68cc573dc2fd644b0dba36b0c30a92dd9eaa0" dependencies = [ - "serde", + "serde_core", "serde_spanned", "toml_datetime", "toml_parser", @@ -2354,18 +2587,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bade1c3e902f58d73d3f294cd7f20391c1cb2fbcb643b73566bc773971df91e3" +checksum = "32f1085dec27c2b6632b04c80b3bb1b4300d6495d1e129693bdda7d91e72eec1" dependencies = [ - "serde", + "serde_core", ] [[package]] name = "toml_parser" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b551886f449aa90d4fe2bdaa9f4a2577ad2dde302c61ecf262d80b116db95c10" +checksum = "4cf893c33be71572e0e9aa6dd15e6677937abd686b066eac3f8cd3531688a627" dependencies = [ "winnow", ] @@ -2748,27 +2981,27 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" -version = "0.14.5+wasi-0.2.4" +version = "0.14.7+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4494f6290a82f5fe584817a676a34b9d6763e8d9d18204009fb31dceca98fd4" +checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" dependencies = [ "wasip2", ] [[package]] name = "wasip2" -version = "1.0.0+wasi-0.2.4" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03fa2761397e5bd52002cd7e73110c71af2109aca4e521a9f40473fe685b0a24" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.101" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e14915cadd45b529bb8d1f343c4ed0ac1de926144b746e2710f9cd05df6603b" +checksum = "ab10a69fbd0a177f5f649ad4d8d3305499c42bab9aef2f7ff592d0ec8f833819" dependencies = [ "cfg-if", "once_cell", @@ -2778,9 +3011,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.101" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28d1ba982ca7923fd01448d5c30c6864d0a14109560296a162f80f305fb93bb" +checksum = "0bb702423545a6007bbc368fde243ba47ca275e549c8a28617f56f6ba53b1d1c" dependencies = [ "bumpalo", "log", @@ -2792,9 +3025,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.101" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c3d463ae3eff775b0c45df9da45d68837702ac35af998361e2c84e7c5ec1b0d" +checksum = "fc65f4f411d91494355917b605e1480033152658d71f722a90647f56a70c88a0" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2802,9 +3035,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.101" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bb4ce89b08211f923caf51d527662b75bdc9c9c7aab40f86dcb9fb85ac552aa" +checksum = "ffc003a991398a8ee604a401e194b6b3a39677b3173d6e74495eb51b82e99a32" dependencies = [ "proc-macro2", "quote", @@ -2815,18 +3048,18 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.101" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f143854a3b13752c6950862c906306adb27c7e839f7414cec8fea35beab624c1" +checksum = "293c37f4efa430ca14db3721dfbe48d8c33308096bd44d80ebaa775ab71ba1cf" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.78" +version = "0.3.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77e4b637749ff0d92b8fad63aa1f7cff3cbe125fd49c175cd6345e7272638b12" +checksum = "fbe734895e869dc429d78c4b433f8d17d95f8d05317440b4fad5ab2d33e596dc" dependencies = [ "js-sys", "wasm-bindgen", @@ -2842,6 +3075,18 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web_atoms" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57ffde1dc01240bdf9992e3205668b235e59421fd085e8a317ed98da0178d414" +dependencies = [ + "phf", + "phf_codegen", + "string_cache", + "string_cache_codegen", +] + [[package]] name = "winapi" version = "0.3.9" @@ -3058,9 +3303,9 @@ checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" [[package]] name = "wit-bindgen" -version = "0.45.1" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c573471f125075647d03df72e026074b7203790d41351cd6edc96f46bcccd36" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "writeable" diff --git a/Cargo.toml b/Cargo.toml index 067a2ffa..d04ad4cb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "defguard-proxy" -version = "1.5.0" +version = "1.5.1" edition = "2021" license = "Apache-2.0" homepage = "https://github.com/DefGuard/proxy" @@ -51,6 +51,7 @@ mime_guess = "2.0" base64 = "0.22" tower = "0.5" futures-util = "0.3" +ammonia = "4.1.1" [build-dependencies] tonic-prost-build = "0.14" diff --git a/build.rs b/build.rs index 28a7705c..18bca343 100644 --- a/build.rs +++ b/build.rs @@ -6,6 +6,22 @@ fn main() -> Result<(), Box> { Emitter::default().add_instructions(&git2)?.emit()?; tonic_prost_build::configure() + // These types contain sensitive data. + .skip_debug([ + "ActivateUserRequest", + "AuthInfoResponse", + "AuthenticateRequest", + "AuthenticateResponse", + "ClientMfaFinishResponse", + "CodeMfaSetupStartResponse", + "CodeMfaSetupFinishResponse", + "CoreRequest", + "CoreResponse", + "DeviceConfigResponse", + "InstanceInfoResponse", + "NewDevice", + "PasswordResetRequest", + ]) // Enable optional fields. .protoc_arg("--experimental_allow_proto3_optional") // Make all messages serde-serializable. diff --git a/src/enterprise/handlers/desktop_client_mfa.rs b/src/enterprise/handlers/desktop_client_mfa.rs index 91ef58e4..e4e98faa 100644 --- a/src/enterprise/handlers/desktop_client_mfa.rs +++ b/src/enterprise/handlers/desktop_client_mfa.rs @@ -95,7 +95,10 @@ pub(super) async fn mfa_auth_callback( info!("MFA authentication callback completed successfully"); Ok(private_cookies) } else { - error!("Received invalid gRPC response type during handling the MFA OpenID authentication callback: {payload:#?}"); + error!( + "Received invalid gRPC response type during handling the MFA OpenID authentication \ + callback" + ); Err(ApiError::InvalidResponseType) } } diff --git a/src/enterprise/handlers/openid_login.rs b/src/enterprise/handlers/openid_login.rs index a0390649..ea0af22b 100644 --- a/src/enterprise/handlers/openid_login.rs +++ b/src/enterprise/handlers/openid_login.rs @@ -94,7 +94,7 @@ async fn auth_info( .send(core_request::Payload::AuthInfo(request), device_info)?; let payload = get_core_response(rx).await?; if let core_response::Payload::AuthInfo(response) = payload { - debug!("Received auth info {response:?}"); + debug!("Received auth info response"); let nonce_cookie = Cookie::build((NONCE_COOKIE_NAME, response.nonce)) // .domain(cookie_domain) @@ -117,7 +117,7 @@ async fn auth_info( let auth_info = AuthInfo::new(response.url, response.button_display_name); Ok((private_cookies, Json(auth_info))) } else { - error!("Received invalid gRPC response type: {payload:#?}"); + error!("Received invalid gRPC response type"); Err(ApiError::InvalidResponseType) } } @@ -188,7 +188,10 @@ async fn auth_callback( debug!("Received auth callback response {url:?} {token:?}"); Ok((private_cookies, Json(CallbackResponseData { url, token }))) } else { - error!("Received invalid gRPC response type during handling the OpenID authentication callback: {payload:#?}"); + error!( + "Received invalid gRPC response type during handling the OpenID authentication \ + callback" + ); Err(ApiError::InvalidResponseType) } } diff --git a/src/grpc.rs b/src/grpc.rs index e57ac529..e1fef7ec 100644 --- a/src/grpc.rs +++ b/src/grpc.rs @@ -1,4 +1,5 @@ use std::{ + any::Any, collections::HashMap, net::SocketAddr, sync::{ @@ -21,7 +22,6 @@ use crate::{ // connected clients type ClientMap = HashMap>>; -#[derive(Debug)] pub(crate) struct ProxyServer { current_id: Arc, clients: Arc>, @@ -45,7 +45,7 @@ impl ProxyServer { /// Sends message to the other side of RPC, with given `payload` and optional `device_info`. /// Returns `tokio::sync::oneshot::Reveicer` to let the caller await reply. - #[instrument(name = "send_grpc_message", level = "debug", skip(self))] + #[instrument(name = "send_grpc_message", level = "debug", skip(self, payload))] pub(crate) fn send( &self, payload: core_request::Payload, @@ -127,13 +127,13 @@ impl proxy_server::Proxy for ProxyServer { loop { match stream.message().await { Ok(Some(response)) => { - debug!("Received message from Defguard core: {response:?}"); + debug!("Received message from Defguard Core ID={}", response.id); connected.store(true, Ordering::Relaxed); // Discard empty payloads. if let Some(payload) = response.payload { if let Some(rx) = results.lock().unwrap().remove(&response.id) { if let Err(err) = rx.send(payload) { - error!("Failed to send message to rx: {err:?}"); + error!("Failed to send message to rx {:?}", err.type_id()); } } else { error!("Missing receiver for response #{}", response.id); diff --git a/src/handlers/desktop_client_mfa.rs b/src/handlers/desktop_client_mfa.rs index ce00a383..4c333b61 100644 --- a/src/handlers/desktop_client_mfa.rs +++ b/src/handlers/desktop_client_mfa.rs @@ -151,7 +151,7 @@ async fn start_client_mfa( info!("Started desktop client authorization {req:?}"); Ok(Json(response)) } else { - error!("Received invalid gRPC response type: {payload:#?}"); + error!("Received invalid gRPC response type"); Err(ApiError::InvalidResponseType) } } @@ -170,7 +170,7 @@ async fn finish_client_mfa( if let core_response::Payload::ClientMfaFinish(response) = payload { Ok(Json(response)) } else { - error!("Received invalid gRPC response type: {payload:#?}"); + error!("Received invalid gRPC response type"); Err(ApiError::InvalidResponseType) } } @@ -210,7 +210,7 @@ async fn finish_remote_mfa( Err(ApiError::Unexpected(String::new())) } } else { - error!("Received invalid gRPC response type: {payload:#?}"); + error!("Received invalid gRPC response type"); Err(ApiError::InvalidResponseType) } } diff --git a/src/handlers/enrollment.rs b/src/handlers/enrollment.rs index 7d8b99b2..788df218 100644 --- a/src/handlers/enrollment.rs +++ b/src/handlers/enrollment.rs @@ -59,12 +59,12 @@ async fn start_enrollment_process( Ok((private_cookies.add(cookie), Json(response))) } else { - error!("Received invalid gRPC response type: {payload:#?}"); + error!("Received invalid gRPC response type"); Err(ApiError::InvalidResponseType) } } -#[instrument(level = "debug", skip(state))] +#[instrument(level = "debug", skip(state, req))] async fn activate_user( State(state): State, device_info: DeviceInfo, @@ -94,12 +94,12 @@ async fn activate_user( } Ok(private_cookies) } else { - error!("Received invalid gRPC response type: {payload:#?}"); + error!("Received invalid gRPC response type"); Err(ApiError::InvalidResponseType) } } -#[instrument(level = "debug", skip(state))] +#[instrument(level = "debug", skip(state, req))] async fn create_device( State(state): State, device_info: DeviceInfo, @@ -122,7 +122,7 @@ async fn create_device( info!("Added new device {name} {pubkey}"); Ok(Json(response)) } else { - error!("Received invalid gRPC response type: {payload:#?}"); + error!("Received invalid gRPC response type"); Err(ApiError::InvalidResponseType) } } @@ -150,7 +150,7 @@ async fn get_network_info( info!("Got network info for device {pubkey}"); Ok(Json(response)) } else { - error!("Received invalid gRPC response type: {payload:#?}"); + error!("Received invalid gRPC response type"); Err(ApiError::InvalidResponseType) } } diff --git a/src/handlers/mobile_client.rs b/src/handlers/mobile_client.rs index 1480d808..b39c2e98 100644 --- a/src/handlers/mobile_client.rs +++ b/src/handlers/mobile_client.rs @@ -58,7 +58,7 @@ pub(crate) async fn register_mobile_auth( info!("Registered mobile device for auth"); Ok(()) } else { - error!("Received invalid gRPC response type: {payload:#?}"); + error!("Received invalid gRPC response type"); Err(ApiError::InvalidResponseType) } } diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index 97a2da74..c01763c5 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -35,7 +35,9 @@ where let user_agent = TypedHeader::::from_request_parts(parts, state) .await .map(|v| v.to_string()) - .ok(); + .ok() + // sanitize user-agent + .filter(|agent| !ammonia::is_html(agent)); let ip_address = forwarded_for_ip .or(insecure_ip) @@ -55,7 +57,7 @@ where pub(crate) async fn get_core_response(rx: Receiver) -> Result { debug!("Fetching core response..."); if let Ok(core_response) = timeout(CORE_RESPONSE_TIMEOUT, rx).await { - debug!("Got gRPC response from Defguard core: {core_response:?}"); + debug!("Got gRPC response from Defguard Core"); if let Ok(Payload::CoreError(core_error)) = core_response { if core_error.status_code == Code::FailedPrecondition as i32 && core_error.message == "no valid license" @@ -76,3 +78,105 @@ pub(crate) async fn get_core_response(rx: Receiver) -> ResultCLICK HERE", + "", + "

CLICK HERE", + ]; + + struct DummyState; + + #[tokio::test] + async fn test_user_agent_sanitization_dg25_16() { + let state = DummyState; + + // valid user agents + for agent in VALID_USER_AGENTS { + let req = Request::builder() + .header("User-Agent", *agent) + .header("X-Forwarded-For", "10.0.0.1") + .body(Body::empty()) + .unwrap(); + let (parts, _) = req.into_parts(); + let mut parts = parts; + + let device_info = DeviceInfo::from_request_parts(&mut parts, &state) + .await + .expect("should succeed"); + + assert_eq!(device_info.user_agent, Some(agent.to_string())); + } + + // invalid user agents + for agent in INVALID_USER_AGENTS { + let req = Request::builder() + .header("User-Agent", *agent) + .header("X-Forwarded-For", "10.0.0.1") + .body(Body::empty()) + .unwrap(); + let (parts, _) = req.into_parts(); + let mut parts = parts; + + let device_info = DeviceInfo::from_request_parts(&mut parts, &state) + .await + .expect("should succeed"); + + assert!(device_info.user_agent.is_none()); + } + + // no user agent + let req = Request::builder() + .header("X-Forwarded-For", "10.0.0.1") + .body(Body::empty()) + .unwrap(); + let (parts, _) = req.into_parts(); + let mut parts = parts; + + let device_info = DeviceInfo::from_request_parts(&mut parts, &state) + .await + .expect("should succeed"); + + assert!(device_info.user_agent.is_none()); + } +} diff --git a/src/handlers/password_reset.rs b/src/handlers/password_reset.rs index 76e122e6..855b3830 100644 --- a/src/handlers/password_reset.rs +++ b/src/handlers/password_reset.rs @@ -36,7 +36,7 @@ async fn request_password_reset( info!("Started password reset request for {}", req.email); Ok(()) } else { - error!("Received invalid gRPC response type: {payload:#?}"); + error!("Received invalid gRPC response type"); Err(ApiError::InvalidResponseType) } } @@ -70,12 +70,12 @@ async fn start_password_reset( info!("Started password reset process"); Ok((private_cookies.add(cookie), Json(response))) } else { - error!("Received invalid gRPC response type: {payload:#?}"); + error!("Received invalid gRPC response type"); Err(ApiError::InvalidResponseType) } } -#[instrument(level = "debug", skip(state))] +#[instrument(level = "debug", skip(state, req))] async fn reset_password( State(state): State, device_info: DeviceInfo, @@ -100,7 +100,7 @@ async fn reset_password( } Ok(private_cookies) } else { - error!("Received invalid gRPC response type: {payload:#?}"); + error!("Received invalid gRPC response type"); Err(ApiError::InvalidResponseType) } } diff --git a/src/handlers/polling.rs b/src/handlers/polling.rs index 435dcee6..673e097a 100644 --- a/src/handlers/polling.rs +++ b/src/handlers/polling.rs @@ -24,7 +24,7 @@ pub(crate) async fn info( info!("Retrieved info for polling request"); Ok(Json(response)) } else { - error!("Received invalid gRPC response type: {payload:#?}"); + error!("Received invalid gRPC response type"); Err(ApiError::InvalidResponseType) } } diff --git a/web/src/pages/enrollment/steps/DataVerificationStep/DataVerificationStep.tsx b/web/src/pages/enrollment/steps/DataVerificationStep/DataVerificationStep.tsx index 9929b23a..cbee41b8 100644 --- a/web/src/pages/enrollment/steps/DataVerificationStep/DataVerificationStep.tsx +++ b/web/src/pages/enrollment/steps/DataVerificationStep/DataVerificationStep.tsx @@ -10,11 +10,10 @@ import { FormInput } from '../../../../shared/components/Form/FormInput/FormInpu import { Card } from '../../../../shared/components/layout/Card/Card'; import { MessageBoxOld } from '../../../../shared/components/layout/MessageBox/MessageBoxOld'; import { MessageBoxType } from '../../../../shared/components/layout/MessageBox/types'; +import { patternValidPhoneNumber } from '../../../../shared/patterns'; import { EnrollmentStepIndicator } from '../../components/EnrollmentStepIndicator/EnrollmentStepIndicator'; import { useEnrollmentStore } from '../../hooks/store/useEnrollmentStore'; -const phonePattern = /^\+?[0-9]+( [0-9]+)?$/; - export const DataVerificationStep = () => { const { LL } = useI18nContext(); const submitRef = useRef(null); @@ -38,7 +37,7 @@ export const DataVerificationStep = () => { .trim() .refine((val) => { if (val && typeof val === 'string' && val.length > 0) { - return phonePattern.test(val); + return patternValidPhoneNumber.test(val); } return true; }, LL.form.errors.invalid()),