Skip to content
Draft
Show file tree
Hide file tree
Changes from 6 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: 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_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_arg() -> Arg {
Arg::new("secret")
.long("secret")
.value_name("ENV_VAR")
.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_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_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) {
if let Some(secret) = matches.remove_many::<String>("secret") {
flags.secret = secret.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
}

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