diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1cdac07e9771..0cdcd647b9c6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -97,9 +97,6 @@ jobs: export CARGO_INCREMENTAL=0 cargo clippy --workspace --all-targets --exclude v8 -- -D warnings - - name: Check for banned TLS crates - run: ./scripts/check-no-native-tls.sh - openapi-schema-check: name: Check OpenAPI Schema is Up-to-Date runs-on: ubuntu-latest diff --git a/Cargo.lock b/Cargo.lock index a632c96d9efe..dddcedddfe4e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -164,7 +164,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -175,7 +175,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -204,9 +204,9 @@ dependencies = [ [[package]] name = "arc-swap" -version = "1.8.2" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9f3647c145568cec02c42054e07bdf9a5a698e15b466fb2341bfc393cd24aa5" +checksum = "a07d1f37ff60921c83bdfc7407723bdefe89b44b98a9b772f225c8f9d67141a6" dependencies = [ "rustversion", ] @@ -878,10 +878,13 @@ dependencies = [ "http-body 1.0.1", "hyper 1.8.1", "hyper-util", + "openssl", + "openssl-sys", "pin-project-lite", "rustls", "rustls-pki-types", "tokio", + "tokio-openssl", "tokio-rustls", "tower-service", ] @@ -907,6 +910,12 @@ dependencies = [ "windows-link", ] +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base32" version = "0.5.1" @@ -1015,7 +1024,7 @@ dependencies = [ "bitflags 2.11.0", "cexpr", "clang-sys", - "itertools 0.10.5", + "itertools 0.13.0", "log", "prettyplease", "proc-macro2", @@ -1627,7 +1636,7 @@ dependencies = [ "candle-kernels", "candle-metal-kernels", "candle-ug", - "cudarc 0.19.3", + "cudarc 0.19.4", "float8 0.6.1", "gemm 0.19.0", "half", @@ -2084,7 +2093,7 @@ dependencies = [ "serde-untagged", "serde_core", "serde_json", - "toml 1.0.7+spec-1.1.0", + "toml 1.1.0+spec-1.1.0", "winnow 1.0.0", "yaml-rust2", ] @@ -2401,6 +2410,18 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.7" @@ -2433,15 +2454,42 @@ dependencies = [ [[package]] name = "cudarc" -version = "0.19.3" +version = "0.19.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6468cb7fa330840f3ebcd8df51edc0e7bf5c18df524792ce6004c6821851cdf3" +checksum = "f071cd6a7b5d51607df76aa2d426aaabc7a74bc6bdb885b8afa63a880572ad9b" dependencies = [ "float8 0.7.0", "half", "libloading 0.9.0", ] +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "darling" version = "0.20.11" @@ -3146,7 +3194,7 @@ dependencies = [ "libc", "option-ext", "redox_users 0.5.2", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3286,6 +3334,20 @@ dependencies = [ "cipher", ] +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + [[package]] name = "ecow" version = "0.2.6" @@ -3295,6 +3357,30 @@ dependencies = [ "serde", ] +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" +dependencies = [ + "curve25519-dalek", + "ed25519", + "serde", + "sha2", + "subtle", + "zeroize", +] + [[package]] name = "either" version = "1.15.0" @@ -3304,6 +3390,27 @@ dependencies = [ "serde", ] +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "hkdf", + "pem-rfc7468", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "email_address" version = "0.2.9" @@ -3396,7 +3503,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -3543,6 +3650,22 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + [[package]] name = "filetime" version = "0.2.27" @@ -3598,7 +3721,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719a903cc23e4a89e87962c2a80fdb45cdaad0983a89bd150bb57b4c8571a7d5" dependencies = [ - "cudarc 0.19.3", + "cudarc 0.19.4", "half", "num-traits", "rand 0.9.2", @@ -4144,6 +4267,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -4290,6 +4414,7 @@ dependencies = [ "nanoid", "oauth2", "once_cell", + "openssl", "opentelemetry", "opentelemetry-appender-tracing", "opentelemetry-otlp", @@ -4448,7 +4573,7 @@ dependencies = [ "urlencoding", "webbrowser", "winapi", - "zip 8.2.0", + "zip 8.4.0", ] [[package]] @@ -4499,6 +4624,7 @@ dependencies = [ "goose-mcp", "hex", "http 1.4.0", + "openssl", "rand 0.9.2", "rcgen", "reqwest 0.13.2", @@ -4546,6 +4672,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "gzip-header" version = "1.0.0" @@ -4882,6 +5019,22 @@ dependencies = [ "tower-service", ] +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper 1.8.1", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + [[package]] name = "hyper-util" version = "0.1.20" @@ -5266,9 +5419,9 @@ checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" [[package]] name = "iri-string" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" +checksum = "d8e7418f59cc01c88316161279a7f665217ae316b388e58a0d10e29f54f1e5eb" dependencies = [ "memchr", "serde", @@ -5313,9 +5466,9 @@ checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itertools" -version = "0.10.5" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] @@ -5331,9 +5484,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "ixdtf" @@ -5353,7 +5506,7 @@ dependencies = [ "portable-atomic", "portable-atomic-util", "serde_core", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -5391,7 +5544,7 @@ dependencies = [ "cesu8", "cfg-if", "combine", - "jni-sys 0.3.0", + "jni-sys 0.3.1", "log", "thiserror 1.0.69", "walkdir", @@ -5430,9 +5583,12 @@ dependencies = [ [[package]] name = "jni-sys" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] [[package]] name = "jni-sys" @@ -5547,11 +5703,18 @@ checksum = "0529410abe238729a60b108898784df8984c87f6054c9c4fcacc47e4803c1ce1" dependencies = [ "aws-lc-rs", "base64 0.22.1", + "ed25519-dalek", "getrandom 0.2.17", + "hmac", "js-sys", + "p256", + "p384", "pem", + "rand 0.8.5", + "rsa", "serde", "serde_json", + "sha2", "signature", "simple_asn1", ] @@ -5684,9 +5847,9 @@ dependencies = [ [[package]] name = "linux-keyutils" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "761e49ec5fd8a5a463f9b84e877c373d888935b71c6be78f3767fe2ae6bed18e" +checksum = "83270a18e9f90d0707c41e9f35efada77b64c0e6f3f1810e71c8368a864d5590" dependencies = [ "bitflags 2.11.0", "libc", @@ -5718,9 +5881,9 @@ checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" [[package]] name = "llama-cpp-2" -version = "0.1.139" +version = "0.1.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1b92f824729095247507a51f5ef7100adc70bbb4f86f1c4fdccbe4afd356bb9" +checksum = "e5604c13b9c847157470479a64d1d7c94f3089709309f82f2fdcbcd43510f2f2" dependencies = [ "encoding_rs", "enumflags2", @@ -5732,9 +5895,9 @@ dependencies = [ [[package]] name = "llama-cpp-sys-2" -version = "0.1.139" +version = "0.1.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e762baca42996077c9b3e5af393d585ca5299977faacf8ac4391f2dbd013a5d5" +checksum = "cbdd3e2c06f3a9a47466a631735946e9ad47fef565b88bc8766a3794474a66f3" dependencies = [ "bindgen", "cc", @@ -6032,6 +6195,23 @@ dependencies = [ "rand 0.8.5", ] +[[package]] +name = "native-tls" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework 3.7.0", + "security-framework-sys", + "tempfile", +] + [[package]] name = "ndk-context" version = "0.1.1" @@ -6144,7 +6324,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -6592,6 +6772,30 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e" +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "p384" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + [[package]] name = "par-core" version = "2.0.0" @@ -7148,6 +7352,15 @@ dependencies = [ "num-integer", ] +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -7255,9 +7468,9 @@ dependencies = [ [[package]] name = "pulldown-cmark" -version = "0.13.1" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83c41efbf8f90ac44de7f3a868f0867851d261b56291732d0cbf7cceaaeb55a6" +checksum = "7c3a14896dfa883796f1cb410461aef38810ea05f2b2c33c5aded3649095fdad" dependencies = [ "bitflags 2.11.0", "getopts", @@ -7727,9 +7940,11 @@ dependencies = [ "http-body-util", "hyper 1.8.1", "hyper-rustls", + "hyper-tls", "hyper-util", "js-sys", "log", + "native-tls", "percent-encoding", "pin-project-lite", "quinn", @@ -7740,6 +7955,7 @@ dependencies = [ "serde_urlencoded", "sync_wrapper", "tokio", + "tokio-native-tls", "tokio-rustls", "tower", "tower-http", @@ -7771,11 +7987,13 @@ dependencies = [ "http-body-util", "hyper 1.8.1", "hyper-rustls", + "hyper-tls", "hyper-util", "js-sys", "log", "mime", "mime_guess", + "native-tls", "percent-encoding", "pin-project-lite", "quinn", @@ -7787,6 +8005,7 @@ dependencies = [ "serde_urlencoded", "sync_wrapper", "tokio", + "tokio-native-tls", "tokio-rustls", "tokio-util", "tower", @@ -7809,6 +8028,16 @@ dependencies = [ "serde_core", ] +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + [[package]] name = "rgb" version = "0.8.53" @@ -8006,7 +8235,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.12.1", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -8065,7 +8294,7 @@ dependencies = [ "security-framework 3.7.0", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -8277,6 +8506,20 @@ version = "3.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "490dcfcbfef26be6800d11870ff2df8774fa6e86d047e3e8c8a76b25655e41ca" +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + [[package]] name = "security-framework" version = "2.11.1" @@ -8435,9 +8678,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776" +checksum = "876ac351060d4f882bb1032b6369eb0aef79ad9df1ea8bc404874d8cc3d0cd98" dependencies = [ "serde_core", ] @@ -8856,7 +9099,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -8949,6 +9192,7 @@ dependencies = [ "indexmap 2.13.0", "log", "memchr", + "native-tls", "once_cell", "percent-encoding", "rustls", @@ -9994,7 +10238,7 @@ dependencies = [ "getrandom 0.4.2", "once_cell", "rustix 1.1.4", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -10401,6 +10645,27 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-openssl" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59df6849caa43bb7567f9a36f863c447d95a11d5903c9cc334ba32576a27eadd" +dependencies = [ + "openssl", + "openssl-sys", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.26.4" @@ -10430,10 +10695,12 @@ checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857" dependencies = [ "futures-util", "log", + "native-tls", "rustls", "rustls-native-certs", "rustls-pki-types", "tokio", + "tokio-native-tls", "tokio-rustls", "tungstenite", ] @@ -10470,13 +10737,13 @@ dependencies = [ [[package]] name = "toml" -version = "1.0.7+spec-1.1.0" +version = "1.1.0+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd28d57d8a6f6e458bc0b8784f8fdcc4b99a437936056fa122cb234f18656a96" +checksum = "f8195ca05e4eb728f4ba94f3e3291661320af739c4e43779cbdfae82ab239fcc" dependencies = [ "serde_core", "serde_spanned", - "toml_datetime 1.0.1+spec-1.1.0", + "toml_datetime 1.1.0+spec-1.1.0", "toml_parser", "winnow 1.0.0", ] @@ -10492,27 +10759,27 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "1.0.1+spec-1.1.0" +version = "1.1.0+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b320e741db58cac564e26c607d3cc1fdc4a88fd36c879568c07856ed83ff3e9" +checksum = "97251a7c317e03ad83774a8752a7e81fb6067740609f75ea2b585b569a59198f" dependencies = [ "serde_core", ] [[package]] name = "toml_parser" -version = "1.0.10+spec-1.1.0" +version = "1.1.0+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7df25b4befd31c4816df190124375d5a20c6b6921e2cad937316de3fccd63420" +checksum = "2334f11ee363607eb04df9b8fc8a13ca1715a72ba8662a26ac285c98aabb4011" dependencies = [ "winnow 1.0.0", ] [[package]] name = "toml_writer" -version = "1.0.7+spec-1.1.0" +version = "1.1.0+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17aaa1c6e3dc22b1da4b6bba97d066e354c7945cac2f7852d4e4e7ca7a6b56d" +checksum = "d282ade6016312faf3e41e57ebbba0c073e4056dab1232ab1cb624199648f8ed" [[package]] name = "tonic" @@ -10827,9 +11094,9 @@ dependencies = [ [[package]] name = "tree-sitter-rust" -version = "0.24.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b9b18034c684a2420722be8b2a91c9c44f2546b631c039edf575ccba8c61be1" +checksum = "f715f73a0687261ddb686f0d64a1e5af57bd199c4d12be5fdda6676ce1885bf9" dependencies = [ "cc", "tree-sitter-language", @@ -10882,6 +11149,7 @@ dependencies = [ "http 1.4.0", "httparse", "log", + "native-tls", "rand 0.9.2", "rustls", "rustls-pki-types", @@ -11559,7 +11827,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] @@ -12324,18 +12592,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.42" +version = "0.8.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2578b716f8a7a858b7f02d5bd870c14bf4ddbbcf3a4c05414ba6503640505e3" +checksum = "efbb2a062be311f2ba113ce66f697a4dc589f85e78a4aea276200804cea0ed87" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.42" +version = "0.8.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e6cc098ea4d3bd6246687de65af3f920c430e236bee1e3bf2e441463f08a02f" +checksum = "0e8bc7269b54418e7aeeef514aa68f8690b8c0489a06b0136e5f57c4c5ccab89" dependencies = [ "proc-macro2", "quote", @@ -12468,9 +12736,9 @@ dependencies = [ [[package]] name = "zip" -version = "8.2.0" +version = "8.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b680f2a0cd479b4cff6e1233c483fdead418106eae419dc60200ae9850f6d004" +checksum = "7756d0206d058333667493c4014f545f4b9603c4330ccd6d9b3f86dcab59f7d9" dependencies = [ "crc32fast", "flate2", @@ -12581,9 +12849,9 @@ dependencies = [ [[package]] name = "zune-jpeg" -version = "0.5.13" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec5f41c76397b7da451efd19915684f727d7e1d516384ca6bd0ec43ec94de23c" +checksum = "0b7a1c0af6e5d8d1363f4994b7a091ccf963d8b694f7da5b0b9cceb82da2c0a6" dependencies = [ "zune-core", ] diff --git a/Justfile b/Justfile index 0b201525eb49..5285b74a2724 100644 --- a/Justfile +++ b/Justfile @@ -11,8 +11,6 @@ check-everything: cargo fmt --all @echo " → Running clippy linting..." cargo clippy --all-targets -- -D warnings - @echo " → Checking for banned TLS crates..." - ./scripts/check-no-native-tls.sh @echo " → Checking UI code formatting..." cd ui/desktop && pnpm run lint:check @echo " → Validating OpenAPI schema..." diff --git a/crates/goose-acp/Cargo.toml b/crates/goose-acp/Cargo.toml index bb5e0983befb..32f2148c323d 100644 --- a/crates/goose-acp/Cargo.toml +++ b/crates/goose-acp/Cargo.toml @@ -16,15 +16,17 @@ name = "generate-acp-schema" path = "src/bin/generate_acp_schema.rs" [features] -default = ["code-mode"] +default = ["code-mode", "rustls-tls"] code-mode = ["goose/code-mode"] +rustls-tls = ["goose/rustls-tls", "goose-mcp/rustls-tls"] +native-tls = ["goose/native-tls", "goose-mcp/native-tls"] [lints] workspace = true [dependencies] goose = { path = "../goose", default-features = false } -goose-mcp = { path = "../goose-mcp" } +goose-mcp = { path = "../goose-mcp", default-features = false } rmcp = { workspace = true } sacp = { workspace = true, features = ["unstable"] } agent-client-protocol-schema = { workspace = true } diff --git a/crates/goose-cli/Cargo.toml b/crates/goose-cli/Cargo.toml index 38da39bbd4ac..3e62ec95baa6 100644 --- a/crates/goose-cli/Cargo.toml +++ b/crates/goose-cli/Cargo.toml @@ -49,7 +49,7 @@ async-trait = { workspace = true } base64 = { workspace = true } regex = { workspace = true } tar = "0.4" -reqwest = { workspace = true, features = ["blocking", "rustls"], default-features = false } +reqwest = { workspace = true, features = ["blocking"], default-features = false } zip = { version = "^8.0", default-features = false, features = ["deflate"] } bzip2 = "0.5" webbrowser = { workspace = true } @@ -62,18 +62,30 @@ urlencoding = { workspace = true } clap_complete = "4.5.62" comfy-table = "7.2.2" sha2 = "0.10" -sigstore-verify = { version = "0.6", default-features = false, features = ["rustls"] } +sigstore-verify = { version = "0.6", default-features = false } [target.'cfg(target_os = "windows")'.dependencies] winapi = { version = "0.3", features = ["wincred"] } [features] -default = ["code-mode", "local-inference"] +default = ["code-mode", "local-inference", "rustls-tls"] code-mode = ["goose/code-mode", "goose-acp/code-mode"] local-inference = ["goose/local-inference"] cuda = ["goose/cuda", "local-inference"] # disables the update command disable-update = [] +rustls-tls = [ + "reqwest/rustls", + "sigstore-verify/rustls", + "goose/rustls-tls", + "goose-mcp/rustls-tls", +] +native-tls = [ + "reqwest/native-tls", + "sigstore-verify/native-tls", + "goose/native-tls", + "goose-mcp/native-tls", +] [dev-dependencies] tempfile = { workspace = true } diff --git a/crates/goose-cli/src/lib.rs b/crates/goose-cli/src/lib.rs index b5006389cbb9..be821a2a2920 100644 --- a/crates/goose-cli/src/lib.rs +++ b/crates/goose-cli/src/lib.rs @@ -1,3 +1,9 @@ +#[cfg(not(any(feature = "rustls-tls", feature = "native-tls")))] +compile_error!("At least one of `rustls-tls` or `native-tls` features must be enabled"); + +#[cfg(all(feature = "rustls-tls", feature = "native-tls"))] +compile_error!("Features `rustls-tls` and `native-tls` are mutually exclusive"); + pub mod cli; pub mod commands; pub mod logging; diff --git a/crates/goose-mcp/Cargo.toml b/crates/goose-mcp/Cargo.toml index 56cad42e1420..46e4f3ee53d5 100644 --- a/crates/goose-mcp/Cargo.toml +++ b/crates/goose-mcp/Cargo.toml @@ -10,6 +10,10 @@ description.workspace = true [lints] workspace = true +[features] +rustls-tls = ["reqwest/rustls"] +native-tls = ["reqwest/native-tls"] + [dependencies] rmcp = { workspace = true, features = ["server", "client", "transport-io", "macros"] } anyhow = { workspace = true } @@ -23,7 +27,7 @@ serde = { workspace = true } serde_json = { workspace = true } schemars = { workspace = true } indoc = { workspace = true } -reqwest = { workspace = true, features = ["json", "rustls", "system-proxy"], default-features = false } +reqwest = { workspace = true, features = ["json", "system-proxy"], default-features = false } chrono = { workspace = true } etcetera = { workspace = true } tempfile = { workspace = true } diff --git a/crates/goose-server/Cargo.toml b/crates/goose-server/Cargo.toml index f8774920ac9d..13d04f1da43a 100644 --- a/crates/goose-server/Cargo.toml +++ b/crates/goose-server/Cargo.toml @@ -11,10 +11,27 @@ description.workspace = true workspace = true [features] -default = ["code-mode", "local-inference"] +default = ["code-mode", "local-inference", "rustls-tls"] code-mode = ["goose/code-mode"] local-inference = ["goose/local-inference"] cuda = ["goose/cuda", "local-inference"] +rustls-tls = [ + "reqwest/rustls", + "tokio-tungstenite/rustls-tls-native-roots", + "axum-server/tls-rustls", + "dep:rustls", + "dep:aws-lc-rs", + "goose/rustls-tls", + "goose-mcp/rustls-tls", +] +native-tls = [ + "reqwest/native-tls", + "tokio-tungstenite/native-tls", + "axum-server/tls-openssl", + "dep:openssl", + "goose/native-tls", + "goose-mcp/native-tls", +] [dependencies] goose = { path = "../goose", default-features = false } @@ -40,21 +57,22 @@ thiserror = { workspace = true } clap = { workspace = true } serde_yaml = { workspace = true } utoipa = { workspace = true, features = ["axum_extras", "chrono"] } -reqwest = { workspace = true, features = ["json", "rustls", "blocking", "multipart", "system-proxy"], default-features = false } +reqwest = { workspace = true, features = ["json", "blocking", "multipart", "system-proxy"], default-features = false } tokio-util = { workspace = true } serde_path_to_error = "0.1.20" -tokio-tungstenite = { version = "0.28.0", features = ["rustls-tls-native-roots"] } +tokio-tungstenite = { version = "0.28.0" } url = { workspace = true } rand = "0.9.2" hex = "0.4.3" subtle = "2.6" socket2 = "0.6.1" fs2 = { workspace = true } -rustls = { version = "0.23", features = ["aws_lc_rs"] } +rustls = { version = "0.23", features = ["aws_lc_rs"], optional = true } uuid = { workspace = true } rcgen = "0.13" -axum-server = { version = "0.8.0", features = ["tls-rustls"] } -aws-lc-rs = "1.16.0" +axum-server = { version = "0.8.0" } +aws-lc-rs = { version = "1.16.0", optional = true } +openssl = { version = "0.10", optional = true } [target.'cfg(windows)'.dependencies] winreg = { version = "0.55.0" } diff --git a/crates/goose-server/src/commands/agent.rs b/crates/goose-server/src/commands/agent.rs index c5799e243cfd..e1e642fac55b 100644 --- a/crates/goose-server/src/commands/agent.rs +++ b/crates/goose-server/src/commands/agent.rs @@ -4,6 +4,7 @@ use anyhow::Result; use axum::middleware; use axum_server::Handle; use goose_server::auth::check_token; +#[cfg(any(feature = "rustls-tls", feature = "native-tls"))] use goose_server::tls::self_signed_config; use tower_http::cors::{Any, CorsLayer}; use tracing::info; @@ -31,6 +32,7 @@ pub async fn run() -> Result<()> { // gateways, etc.) try to open TLS connections. Both `ring` and `aws-lc-rs` // features are enabled on rustls (via different transitive deps), so rustls // cannot auto-detect a provider — we must pick one explicitly. + #[cfg(feature = "rustls-tls")] let _ = rustls::crypto::ring::default_provider().install_default(); crate::logging::setup_logging(Some("goosed"))?; @@ -74,21 +76,39 @@ pub async fn run() -> Result<()> { }); if settings.tls { - let tls_setup = self_signed_config().await?; - - let handle = Handle::new(); - let shutdown_handle = handle.clone(); - tokio::spawn(async move { - shutdown_signal().await; - shutdown_handle.graceful_shutdown(None); - }); - - info!("listening on https://{}", addr); - - axum_server::bind_rustls(addr, tls_setup.config) - .handle(handle) - .serve(app.into_make_service()) - .await?; + #[cfg(any(feature = "rustls-tls", feature = "native-tls"))] + { + let tls_setup = self_signed_config().await?; + + let handle = Handle::new(); + let shutdown_handle = handle.clone(); + tokio::spawn(async move { + shutdown_signal().await; + shutdown_handle.graceful_shutdown(None); + }); + + info!("listening on https://{}", addr); + + #[cfg(feature = "rustls-tls")] + axum_server::bind_rustls(addr, tls_setup.config) + .handle(handle) + .serve(app.into_make_service()) + .await?; + + #[cfg(feature = "native-tls")] + axum_server::bind_openssl(addr, tls_setup.config) + .handle(handle) + .serve(app.into_make_service()) + .await?; + } + + #[cfg(not(any(feature = "rustls-tls", feature = "native-tls")))] + { + anyhow::bail!( + "TLS was requested but no TLS backend is enabled. \ + Enable the `rustls-tls` or `native-tls` feature." + ); + } } else { let listener = tokio::net::TcpListener::bind(addr).await?; diff --git a/crates/goose-server/src/lib.rs b/crates/goose-server/src/lib.rs index ab35c400c284..2323f2877490 100644 --- a/crates/goose-server/src/lib.rs +++ b/crates/goose-server/src/lib.rs @@ -1,3 +1,9 @@ +#[cfg(not(any(feature = "rustls-tls", feature = "native-tls")))] +compile_error!("At least one of `rustls-tls` or `native-tls` features must be enabled"); + +#[cfg(all(feature = "rustls-tls", feature = "native-tls"))] +compile_error!("Features `rustls-tls` and `native-tls` are mutually exclusive"); + pub mod auth; pub mod configuration; pub mod error; @@ -5,6 +11,7 @@ pub mod openapi; pub mod routes; pub mod session_event_bus; pub mod state; +#[cfg(any(feature = "rustls-tls", feature = "native-tls"))] pub mod tls; pub mod tunnel; diff --git a/crates/goose-server/src/tls.rs b/crates/goose-server/src/tls.rs index 8a5cf86daf5a..5eb7e3f49060 100644 --- a/crates/goose-server/src/tls.rs +++ b/crates/goose-server/src/tls.rs @@ -1,22 +1,31 @@ +//! TLS configuration for the goose server. +//! +//! Two TLS backends are supported for the HTTPS listener via `axum-server`: +//! +//! - **`rustls-tls`** (enabled by default) – uses `axum-server/tls-rustls` with +//! the `aws-lc-rs` crypto provider. +//! - **`native-tls`** – uses `axum-server/tls-openssl`, which links against the +//! platform's OpenSSL (or a compatible fork such as LibreSSL / BoringSSL). +//! On Linux this *is* the platform-native TLS stack; on macOS/Windows the +//! `native-tls` crate used by the HTTP *client* delegates to Security.framework +//! / SChannel respectively, but `axum-server` does not offer those backends so +//! the server listener always uses OpenSSL when this feature is active. + use anyhow::Result; -use aws_lc_rs::digest; -use axum_server::tls_rustls::RustlsConfig; use rcgen::{CertificateParams, DnType, KeyPair, SanType}; +#[cfg(feature = "rustls-tls")] +pub type TlsConfig = axum_server::tls_rustls::RustlsConfig; + +#[cfg(feature = "native-tls")] +pub type TlsConfig = axum_server::tls_openssl::OpenSSLConfig; + pub struct TlsSetup { - pub config: RustlsConfig, + pub config: TlsConfig, pub fingerprint: String, } -/// Generate a self-signed TLS certificate for localhost (127.0.0.1) and -/// return a [`TlsSetup`] containing the rustls config and the SHA-256 -/// fingerprint of the generated certificate (colon-separated hex). -/// -/// The fingerprint is printed to stdout so the parent process (e.g. Electron) -/// can pin it and reject connections from any other certificate. -pub async fn self_signed_config() -> Result { - let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); - +fn generate_self_signed_cert() -> Result<(rcgen::Certificate, KeyPair)> { let mut params = CertificateParams::default(); params .distinguished_name @@ -28,22 +37,62 @@ pub async fn self_signed_config() -> Result { let key_pair = KeyPair::generate()?; let cert = params.self_signed(&key_pair)?; + Ok((cert, key_pair)) +} - let cert_der = cert.der(); - let sha256 = digest::digest(&digest::SHA256, cert_der); - let fingerprint = sha256 - .as_ref() - .iter() - .map(|b| format!("{b:02X}")) - .collect::>() - .join(":"); +fn sha256_fingerprint(der: &[u8]) -> String { + #[cfg(feature = "rustls-tls")] + { + let sha256 = aws_lc_rs::digest::digest(&aws_lc_rs::digest::SHA256, der); + sha256 + .as_ref() + .iter() + .map(|b| format!("{b:02X}")) + .collect::>() + .join(":") + } + #[cfg(feature = "native-tls")] + { + use openssl::hash::MessageDigest; + let digest = + openssl::hash::hash(MessageDigest::sha256(), der).expect("SHA-256 hash failed"); + digest + .iter() + .map(|b| format!("{b:02X}")) + .collect::>() + .join(":") + } +} + +/// Generate a self-signed TLS certificate for localhost (127.0.0.1) and +/// return a [`TlsSetup`] containing the server config and the SHA-256 +/// fingerprint of the generated certificate (colon-separated hex). +/// +/// The fingerprint is printed to stdout so the parent process (e.g. Electron) +/// can pin it and reject connections from any other certificate. +pub async fn self_signed_config() -> Result { + #[cfg(feature = "rustls-tls")] + let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); + + let (cert, key_pair) = generate_self_signed_cert()?; + + let fingerprint = sha256_fingerprint(cert.der()); println!("GOOSED_CERT_FINGERPRINT={fingerprint}"); let cert_pem = cert.pem(); let key_pem = key_pair.serialize_pem(); - let config = RustlsConfig::from_pem(cert_pem.into_bytes(), key_pem.into_bytes()).await?; + #[cfg(feature = "rustls-tls")] + let config = axum_server::tls_rustls::RustlsConfig::from_pem( + cert_pem.into_bytes(), + key_pem.into_bytes(), + ) + .await?; + + #[cfg(feature = "native-tls")] + let config = + axum_server::tls_openssl::OpenSSLConfig::from_pem(cert_pem.as_bytes(), key_pem.as_bytes())?; Ok(TlsSetup { config, diff --git a/crates/goose-server/src/tunnel/lapstone.rs b/crates/goose-server/src/tunnel/lapstone.rs index 94c6d5d8adf0..9b55afbf306b 100644 --- a/crates/goose-server/src/tunnel/lapstone.rs +++ b/crates/goose-server/src/tunnel/lapstone.rs @@ -485,6 +485,7 @@ async fn run_single_connection( scheme: String, restart_tx: mpsc::Sender<()>, ) { + #[cfg(feature = "rustls-tls")] let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); let worker_url = get_worker_url(); diff --git a/crates/goose-server/tests/tls_test.rs b/crates/goose-server/tests/tls_test.rs new file mode 100644 index 000000000000..a955ebd0f882 --- /dev/null +++ b/crates/goose-server/tests/tls_test.rs @@ -0,0 +1,109 @@ +use goose_server::tls::{self_signed_config, TlsConfig}; + +#[cfg(not(feature = "native-tls"))] +#[test] +fn default_tls_config_is_rustls() { + fn assert_type(_: &T) {} + let rt = tokio::runtime::Runtime::new().unwrap(); + let setup = rt.block_on(self_signed_config()).unwrap(); + // Proves TlsConfig resolves to RustlsConfig when native-tls is disabled. + let _: &axum_server::tls_rustls::RustlsConfig = &setup.config; + assert_type::(&setup.config); +} + +#[cfg(feature = "native-tls")] +#[test] +fn native_tls_config_is_openssl() { + fn assert_type(_: &T) {} + let rt = tokio::runtime::Runtime::new().unwrap(); + let setup = rt.block_on(self_signed_config()).unwrap(); + // Proves TlsConfig resolves to OpenSSLConfig when native-tls is enabled. + let _: &axum_server::tls_openssl::OpenSSLConfig = &setup.config; + assert_type::(&setup.config); +} + +#[tokio::test] +async fn self_signed_config_produces_valid_fingerprint() { + let setup = self_signed_config().await.unwrap(); + + assert!( + !setup.fingerprint.is_empty(), + "fingerprint must not be empty" + ); + + let parts: Vec<&str> = setup.fingerprint.split(':').collect(); + assert_eq!( + parts.len(), + 32, + "SHA-256 fingerprint must have 32 hex pairs" + ); + + for part in &parts { + assert_eq!( + part.len(), + 2, + "each fingerprint segment must be 2 hex chars" + ); + assert!( + part.chars().all(|c| c.is_ascii_hexdigit()), + "fingerprint segment '{}' must be valid hex", + part + ); + } +} + +#[tokio::test] +async fn self_signed_config_returns_usable_tls_config() { + use axum::routing::get; + use std::net::SocketAddr; + + let setup = self_signed_config().await.unwrap(); + + let app = axum::Router::new().route("/health", get(|| async { "ok" })); + let addr = SocketAddr::from(([127, 0, 0, 1], 0)); + + #[cfg(not(feature = "native-tls"))] + let server = axum_server::bind_rustls(addr, setup.config); + + #[cfg(feature = "native-tls")] + let server = axum_server::bind_openssl(addr, setup.config); + + let handle = axum_server::Handle::new(); + let shutdown_handle = handle.clone(); + + let server_handle = tokio::spawn({ + let handle = handle.clone(); + async move { + server + .handle(handle) + .serve(app.into_make_service()) + .await + .unwrap(); + } + }); + + // Wait for the server to start listening. + let listening_addr = loop { + if let Some(addr) = handle.listening().await { + break addr; + } + tokio::time::sleep(std::time::Duration::from_millis(10)).await; + }; + + let client = reqwest::Client::builder() + .danger_accept_invalid_certs(true) + .build() + .unwrap(); + + let resp = client + .get(format!("https://{}/health", listening_addr)) + .send() + .await + .unwrap(); + + assert_eq!(resp.status(), 200); + assert_eq!(resp.text().await.unwrap(), "ok"); + + shutdown_handle.graceful_shutdown(None); + let _ = server_handle.await; +} diff --git a/crates/goose/Cargo.toml b/crates/goose/Cargo.toml index 06cc107b4816..c790c90e0216 100644 --- a/crates/goose/Cargo.toml +++ b/crates/goose/Cargo.toml @@ -8,7 +8,7 @@ repository.workspace = true description.workspace = true [features] -default = ["code-mode", "local-inference"] +default = ["code-mode", "local-inference", "rustls-tls"] code-mode = ["dep:pctx_code_mode"] local-inference = [ "dep:candle-core", @@ -21,6 +21,23 @@ local-inference = [ "dep:byteorder", ] cuda = ["local-inference", "candle-core/cuda", "candle-nn/cuda", "llama-cpp-2/cuda"] +rustls-tls = [ + "reqwest/rustls", + "rmcp/reqwest", + "sqlx/runtime-tokio-rustls", + "jsonwebtoken/aws_lc_rs", + "oauth2/reqwest", + "oauth2/rustls-tls", +] +native-tls = [ + "dep:openssl", + "reqwest/native-tls", + "rmcp/reqwest-native-tls", + "sqlx/runtime-tokio-native-tls", + "jsonwebtoken/rust_crypto", + "oauth2/reqwest", + "oauth2/native-tls", +] [lints] workspace = true @@ -29,17 +46,16 @@ workspace = true lru = { workspace = true } rmcp = { workspace = true, features = [ "client", - "reqwest", "transport-child-process", "transport-streamable-http-client", "transport-streamable-http-client-reqwest", ] } -oauth2 = "5.0" +oauth2 = { version = "5.0", default-features = false } anyhow = { workspace = true } thiserror = { workspace = true } futures = { workspace = true } dirs = { workspace = true } -reqwest = { workspace = true, features = ["rustls", "json", "cookies", "gzip", "brotli", "deflate", "zstd", "charset", "http2", "stream", "blocking", "multipart", "system-proxy"], default-features = false } +reqwest = { workspace = true, features = ["json", "cookies", "gzip", "brotli", "deflate", "zstd", "charset", "http2", "stream", "blocking", "multipart", "system-proxy"], default-features = false } tokio = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } @@ -88,7 +104,6 @@ tokio-cron-scheduler = "0.14.0" urlencoding = { workspace = true } v_htmlescape = "0.15" sqlx = { version = "0.8", default-features = false, features = [ - "runtime-tokio-rustls", "sqlite", "chrono", "json", @@ -105,7 +120,7 @@ aws-sdk-bedrockruntime = { version = "=1.120.0", default-features = false, featu aws-sdk-sagemakerruntime = { version = "1.62.0", default-features = false, features = ["default-https-client", "rt-tokio"] } # For GCP Vertex AI provider auth -jsonwebtoken = { version = "10.3.0", features = ["aws_lc_rs"] } +jsonwebtoken = { version = "10.3.0", default-features = false, features = ["use_pem"] } blake3 = "1.5" fs2 = { workspace = true } @@ -154,6 +169,7 @@ llama-cpp-2 = { version = "0.1.137", features = ["sampler"], optional = true } encoding_rs = "0.8.35" pastey = "0.2.1" shell-words = "1.1.1" +openssl = { version = "0.10", optional = true } [target.'cfg(target_os = "windows")'.dependencies] winapi = { version = "0.3", features = ["wincred"] } diff --git a/crates/goose/src/lib.rs b/crates/goose/src/lib.rs index f73313e3bb7b..1e7d7a92f051 100644 --- a/crates/goose/src/lib.rs +++ b/crates/goose/src/lib.rs @@ -1,3 +1,9 @@ +#[cfg(not(any(feature = "rustls-tls", feature = "native-tls")))] +compile_error!("At least one of `rustls-tls` or `native-tls` features must be enabled"); + +#[cfg(all(feature = "rustls-tls", feature = "native-tls"))] +compile_error!("Features `rustls-tls` and `native-tls` are mutually exclusive"); + pub mod acp; pub mod action_required_manager; pub mod agents; diff --git a/crates/goose/src/providers/api_client.rs b/crates/goose/src/providers/api_client.rs index 9f4feefe8ef5..d87560e048ac 100644 --- a/crates/goose/src/providers/api_client.rs +++ b/crates/goose/src/providers/api_client.rs @@ -119,12 +119,26 @@ impl TlsConfig { let key_pem = read_to_string(&cert_key_pair.key_path) .map_err(|e| anyhow::anyhow!("Failed to read client private key: {}", e))?; - // Create a combined PEM file with certificate and private key - let combined_pem = format!("{}\n{}", cert_pem, key_pem); - - let identity = Identity::from_pem(combined_pem.as_bytes()).map_err(|e| { - anyhow::anyhow!("Failed to create identity from cert and key: {}", e) - })?; + #[cfg(not(feature = "native-tls"))] + let identity = { + let combined_pem = format!("{}\n{}", cert_pem, key_pem); + Identity::from_pem(combined_pem.as_bytes()).map_err(|e| { + anyhow::anyhow!("Failed to create identity from cert and key: {}", e) + })? + }; + + #[cfg(feature = "native-tls")] + let identity = { + // Convert any PEM key format (PKCS#1, SEC1, PKCS#8) to PKCS#8 for native-tls + let pkey = openssl::pkey::PKey::private_key_from_pem(key_pem.as_bytes()) + .map_err(|e| anyhow::anyhow!("Failed to parse private key: {}", e))?; + let pkcs8_pem = pkey + .private_key_to_pem_pkcs8() + .map_err(|e| anyhow::anyhow!("Failed to convert key to PKCS#8: {}", e))?; + Identity::from_pkcs8_pem(cert_pem.as_bytes(), &pkcs8_pem).map_err(|e| { + anyhow::anyhow!("Failed to create identity from cert and key: {}", e) + })? + }; Ok(Some(identity)) } else { diff --git a/scripts/check-no-native-tls.sh b/scripts/check-no-native-tls.sh deleted file mode 100755 index c0a337fbd27a..000000000000 --- a/scripts/check-no-native-tls.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash -# Prevent native-tls/OpenSSL from being added to the dependency tree. -# These cause Linux compatibility issues with OpenSSL version mismatches. -# See: https://github.com/block/goose/issues/6034 - -set -e - -BANNED_CRATES=("native-tls" "openssl-sys" "openssl") -FOUND_BANNED=0 - -for crate in "${BANNED_CRATES[@]}"; do - if cargo tree -i "$crate" 2>/dev/null | grep -q "$crate"; then - echo "ERROR: Found banned crate '$crate' in dependency tree" - echo "This causes Linux compatibility issues with OpenSSL versions." - echo "Use rustls-based alternatives instead (e.g., rustls-tls-native-roots)." - echo "" - echo "Dependency chain:" - cargo tree -i "$crate" - echo "" - FOUND_BANNED=1 - fi -done - -if [ $FOUND_BANNED -eq 1 ]; then - exit 1 -fi - -echo "✓ No banned TLS crates found (native-tls, openssl, openssl-sys)"