From 6950203b8cf65802f8a9dfc05c5b556fe6d300ab Mon Sep 17 00:00:00 2001 From: Alec Fong Date: Mon, 18 May 2026 17:57:42 -0700 Subject: [PATCH] feat(sandbox): inject DENO_CERT into sandbox child environment Sandbox processes running on Deno couldn't TLS-verify connections to services signed by OpenShell's per-sandbox ephemeral CA because Deno doesn't consult `SSL_CERT_FILE` / `NODE_EXTRA_CA_CERTS`. Deno reads its own `DENO_CERT` env var (additive PEM bundle, same shape as `NODE_EXTRA_CA_CERTS`) for that. Add `DENO_CERT` to `child_env::tls_env_vars` pointing at the standalone OpenShell CA cert (not the combined system+sandbox bundle, since DENO_CERT is additive). The three callers in `process.rs` / `ssh.rs` iterate the array, so the size bump from 5 to 6 entries flows through without caller changes. Updates the security best-practices doc to enumerate `DENO_CERT` alongside the other trust-store env vars. Tracks: brevdev/dex-ui#5 Signed-off-by: Alec Fong --- crates/openshell-sandbox/src/child_env.rs | 6 ++++-- docs/security/best-practices.mdx | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/crates/openshell-sandbox/src/child_env.rs b/crates/openshell-sandbox/src/child_env.rs index e764afdfe..32eecbee3 100644 --- a/crates/openshell-sandbox/src/child_env.rs +++ b/crates/openshell-sandbox/src/child_env.rs @@ -24,11 +24,12 @@ pub fn proxy_env_vars(proxy_url: &str) -> [(&'static str, String); 9] { pub fn tls_env_vars( ca_cert_path: &Path, combined_bundle_path: &Path, -) -> [(&'static str, String); 5] { +) -> [(&'static str, String); 6] { let ca_cert_path = ca_cert_path.display().to_string(); let combined_bundle_path = combined_bundle_path.display().to_string(); [ - ("NODE_EXTRA_CA_CERTS", ca_cert_path), + ("NODE_EXTRA_CA_CERTS", ca_cert_path.clone()), + ("DENO_CERT", ca_cert_path), ("SSL_CERT_FILE", combined_bundle_path.clone()), ("REQUESTS_CA_BUNDLE", combined_bundle_path.clone()), ("CURL_CA_BUNDLE", combined_bundle_path.clone()), @@ -81,6 +82,7 @@ mod tests { let stdout = String::from_utf8(output.stdout).expect("utf8"); assert!(stdout.contains("NODE_EXTRA_CA_CERTS=/etc/openshell-tls/openshell-ca.pem")); + assert!(stdout.contains("DENO_CERT=/etc/openshell-tls/openshell-ca.pem")); assert!(stdout.contains("SSL_CERT_FILE=/etc/openshell-tls/ca-bundle.pem")); assert!(stdout.contains("REQUESTS_CA_BUNDLE=/etc/openshell-tls/ca-bundle.pem")); assert!(stdout.contains("CURL_CA_BUNDLE=/etc/openshell-tls/ca-bundle.pem")); diff --git a/docs/security/best-practices.mdx b/docs/security/best-practices.mdx index faf1b5991..12ad00520 100644 --- a/docs/security/best-practices.mdx +++ b/docs/security/best-practices.mdx @@ -120,7 +120,7 @@ This enables credential injection and L7 inspection without explicit configurati | Aspect | Detail | |---|---| -| Default | Auto-detect and terminate. OpenShell generates the sandbox CA at startup and injects it into the process trust stores (`NODE_EXTRA_CA_CERTS`, `SSL_CERT_FILE`, `REQUESTS_CA_BUNDLE`, `CURL_CA_BUNDLE`, `GIT_SSL_CAINFO`). | +| Default | Auto-detect and terminate. OpenShell generates the sandbox CA at startup and injects it into the process trust stores (`NODE_EXTRA_CA_CERTS`, `DENO_CERT`, `SSL_CERT_FILE`, `REQUESTS_CA_BUNDLE`, `CURL_CA_BUNDLE`, `GIT_SSL_CAINFO`). | | What you can change | Set `tls: skip` on an endpoint to disable TLS detection and termination for that endpoint. Use this for client-certificate mTLS to upstream or non-standard binary protocols. | | Risk if relaxed | `tls: skip` disables credential injection and L7 inspection for that endpoint. The proxy relays encrypted traffic without seeing the contents. | | Recommendation | Use auto-detect (the default) for most endpoints. Use `tls: skip` only when the upstream requires the client's own TLS certificate (mTLS) or uses a non-HTTP protocol. |