Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ simd-json = "0.14.0"
slab = "0.4"
smallvec = "1.8"
socket2 = { version = "0.5.3", features = ["all"] }
sys_traits = "=0.1.17"
sys_traits = "=0.1.19"
tar = "=0.4.43"
tempfile = "3.4.0"
termcolor = "1.1.3"
Expand Down
18 changes: 18 additions & 0 deletions cli/args/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,7 @@ pub struct Flags {
pub eszip: bool,
pub node_conditions: Vec<String>,
pub preload: Vec<String>,
pub secret_env: Vec<String>,
pub tunnel: bool,
}

Expand Down Expand Up @@ -4181,6 +4182,7 @@ fn compile_args_without_check_args(app: Command) -> Command {
.arg(unsafely_ignore_certificate_errors_arg())
.arg(preload_arg())
.arg(min_dep_age_arg())
.arg(secret_env_arg())
}

fn permission_args(app: Command, requires: Option<&'static str>) -> Command {
Expand Down Expand Up @@ -4776,6 +4778,15 @@ fn min_dep_age_arg() -> Arg {
.help("(Unstable) The age in minutes, ISO-8601 duration or RFC3339 absolute timestamp (e.g. '120' for two hours, 'P2D' for two days, '2025-09-16' for cutoff date, '2025-09-16T12:00:00+00:00' for cutoff time, '0' to disable)")
}

fn secret_env_arg() -> Arg {
Arg::new("secret-env")
.long("secret-env")
.value_name("ENV_VAR_NAME")
.action(ArgAction::Append)
// TODO(THIS PR): this
.help("TODO")
}

fn ca_file_arg() -> Arg {
Arg::new("cert")
.long("cert")
Expand Down Expand Up @@ -6534,6 +6545,7 @@ fn compile_args_without_check_parse(
unsafely_ignore_certificate_errors_parse(flags, matches);
preload_arg_parse(flags, matches);
min_dep_age_arg_parse(flags, matches);
secret_env_arg_parse(flags, matches);
Ok(())
}

Expand Down Expand Up @@ -6816,6 +6828,12 @@ fn preload_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) {
}
}

fn secret_env_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) {
if let Some(value) = matches.remove_many::<String>("secret-env") {
flags.secret_env = value.collect();
}
}

fn min_dep_age_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) {
flags.minimum_dependency_age = matches.remove_one("minimum-dependency-age");
}
Expand Down
4 changes: 4 additions & 0 deletions cli/args/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,10 @@ impl CliOptions {
Ok(preload)
}

pub fn secret_env_var_names(&self) -> &[String] {
&self.flags.secret_env
}

fn resolve_main_module_with_resolver_if_bare(
&self,
raw_specifier: &str,
Expand Down
5 changes: 5 additions & 0 deletions cli/factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ use deno_resolver::loader::MemoryFiles;
use deno_resolver::npm::DenoInNpmPackageChecker;
use deno_resolver::workspace::WorkspaceResolver;
use deno_runtime::FeatureChecker;
use deno_runtime::deno_fetch::SecretsReplacer;
use deno_runtime::deno_fs;
use deno_runtime::deno_fs::RealFs;
use deno_runtime::deno_permissions::Permissions;
Expand Down Expand Up @@ -1077,6 +1078,10 @@ impl CliFactory {
create_npm_process_state_provider(npm_resolver),
pkg_json_resolver.clone(),
self.root_cert_store_provider().clone(),
Arc::new(SecretsReplacer::new(
&self.sys(),
cli_options.secret_env_var_names(),
)),
cli_options.resolve_storage_key_resolver(),
self.sys(),
self.create_lib_main_worker_options()?,
Expand Down
5 changes: 5 additions & 0 deletions cli/lib/worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use deno_runtime::deno_core::ModuleLoader;
use deno_runtime::deno_core::SharedArrayBufferStore;
use deno_runtime::deno_core::error::CoreError;
use deno_runtime::deno_core::v8;
use deno_runtime::deno_fetch::SecretsReplacer;
use deno_runtime::deno_fs;
use deno_runtime::deno_napi::DenoRtNativeAddonLoaderRc;
use deno_runtime::deno_node::NodeExtInitServices;
Expand Down Expand Up @@ -375,6 +376,7 @@ struct LibWorkerFactorySharedState<TSys: DenoLibSys> {
npm_process_state_provider: NpmProcessStateProviderRc,
pkg_json_resolver: Arc<node_resolver::PackageJsonResolver<TSys>>,
root_cert_store_provider: Arc<dyn RootCertStoreProvider>,
secrets_replacer: Arc<SecretsReplacer>,
shared_array_buffer_store: SharedArrayBufferStore,
storage_key_resolver: StorageKeyResolver,
sys: TSys,
Expand Down Expand Up @@ -546,6 +548,7 @@ impl<TSys: DenoLibSys> LibMainWorkerFactory<TSys> {
npm_process_state_provider: NpmProcessStateProviderRc,
pkg_json_resolver: Arc<node_resolver::PackageJsonResolver<TSys>>,
root_cert_store_provider: Arc<dyn RootCertStoreProvider>,
secrets_replacer: Arc<SecretsReplacer>,
storage_key_resolver: StorageKeyResolver,
sys: TSys,
options: LibMainWorkerOptions,
Expand All @@ -568,6 +571,7 @@ impl<TSys: DenoLibSys> LibMainWorkerFactory<TSys> {
npm_process_state_provider,
pkg_json_resolver,
root_cert_store_provider,
secrets_replacer,
shared_array_buffer_store: roots.shared_array_buffer_store,
storage_key_resolver,
sys,
Expand Down Expand Up @@ -652,6 +656,7 @@ impl<TSys: DenoLibSys> LibMainWorkerFactory<TSys> {
blob_store: shared.blob_store.clone(),
broadcast_channel: shared.broadcast_channel.clone(),
fetch_dns_resolver: Default::default(),
secrets_replacer: shared.secrets_replacer.clone(),
shared_array_buffer_store: Some(shared.shared_array_buffer_store.clone()),
compiled_wasm_module_store: Some(
shared.compiled_wasm_module_store.clone(),
Expand Down
3 changes: 3 additions & 0 deletions cli/rt/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ use deno_runtime::FeatureChecker;
use deno_runtime::WorkerExecutionMode;
use deno_runtime::WorkerLogLevel;
use deno_runtime::code_cache::CodeCache;
use deno_runtime::deno_fetch::SecretsReplacer;
use deno_runtime::deno_fs::FileSystem;
use deno_runtime::deno_node::NodeRequireLoader;
use deno_runtime::deno_node::create_host_defined_options;
Expand Down Expand Up @@ -1045,6 +1046,8 @@ pub async fn run(
create_npm_process_state_provider(&npm_resolver),
pkg_json_resolver,
root_cert_store_provider,
// TODO(dsherret): support secrets in deno compile
Arc::new(SecretsReplacer::default()),
StorageKeyResolver::empty(),
sys.clone(),
lib_main_worker_options,
Expand Down
2 changes: 2 additions & 0 deletions ext/fetch/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ percent-encoding.workspace = true
rustls-webpki.workspace = true
serde.workspace = true
serde_json.workspace = true
sys_traits.workspace = true
thiserror.workspace = true
tokio.workspace = true
tokio-rustls.workspace = true
Expand All @@ -52,3 +53,4 @@ tokio-vsock.workspace = true
[dev-dependencies]
fast-socks5.workspace = true
rustls.workspace = true
sys_traits = { features = ["memory"], workspace = true }
11 changes: 9 additions & 2 deletions ext/fetch/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
pub mod dns;
mod fs_fetch_handler;
mod proxy;
mod secrets_replacer;
#[cfg(test)]
mod tests;

Expand Down Expand Up @@ -87,6 +88,7 @@ use hyper_util::rt::TokioExecutor;
use hyper_util::rt::TokioIo;
use hyper_util::rt::TokioTimer;
pub use proxy::basic_auth;
pub use secrets_replacer::SecretsReplacer;
use serde::Deserialize;
use serde::Serialize;
use tower::BoxError;
Expand All @@ -98,6 +100,7 @@ use tower_http::decompression::Decompression;
#[derive(Clone)]
pub struct Options {
pub user_agent: String,
pub secrets_replacer: Arc<SecretsReplacer>,
pub root_cert_store_provider: Option<Arc<dyn RootCertStoreProvider>>,
pub proxy: Option<Proxy>,
/// A callback to customize HTTP client configuration.
Expand Down Expand Up @@ -132,6 +135,7 @@ impl Default for Options {
fn default() -> Self {
Self {
user_agent: "".to_string(),
secrets_replacer: Default::default(),
root_cert_store_provider: None,
proxy: None,
client_builder_hook: None,
Expand Down Expand Up @@ -503,9 +507,13 @@ pub fn op_fetch(
request.headers_mut().insert(CONTENT_LENGTH, len.into());
}

let options = state.borrow::<Options>();
for (key, value) in headers {
let name = HeaderName::from_bytes(&key)?;
let v = HeaderValue::from_bytes(&value)?;
let v = match options.secrets_replacer.replace(&value) {
Some(replaced_value) => HeaderValue::from_bytes(&replaced_value)?,
None => HeaderValue::from_bytes(&value)?,
};

if (name != HOST || allow_host) && name != CONTENT_LENGTH {
request.headers_mut().append(name, v);
Expand All @@ -520,7 +528,6 @@ pub fn op_fetch(
.insert(ACCEPT_ENCODING, HeaderValue::from_static("identity"));
}

let options = state.borrow::<Options>();
if let Some(request_builder_hook) = options.request_builder_hook {
request_builder_hook(&mut request)
.map_err(FetchError::RequestBuilderHook)?;
Expand Down
Loading