mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-23 08:03:33 +00:00
[ee] fix: stop handlers, apps and agents resolving untrusted refs (#11893)
* fix: stop handler, app and agent jobs resolving untrusted references * perf: skip decoding untrusted args that hold no dollar or escape * test: drop the transaction the recovery handler no longer takes * fix: flag reserved names in object keys and tighten the jsonb parity test
This commit is contained in:
@@ -21,7 +21,7 @@ use windmill_common::{
|
||||
jobs::JobPayload,
|
||||
users::username_to_permissioned_as,
|
||||
utils::{not_found_if_none, StripPath},
|
||||
variables::arg_needs_interpolation,
|
||||
variables::untrusted_arg_interpolates,
|
||||
};
|
||||
use windmill_queue::{push, PushArgs, PushIsolationLevel};
|
||||
|
||||
@@ -136,11 +136,8 @@ pub(crate) async fn run_agent_as(
|
||||
};
|
||||
if let Some(obo) = on_behalf_of.as_ref() {
|
||||
// The worker would interpolate such an input with the job's token, which is the
|
||||
// identity's. Checked on the decoded value: the raw JSON can spell `$` as `\u0024`.
|
||||
if args.values().any(|v| {
|
||||
serde_json::from_str::<serde_json::Value>(v.get())
|
||||
.is_ok_and(|v| arg_needs_interpolation(&v.to_string()))
|
||||
}) {
|
||||
// identity's.
|
||||
if args.values().any(|v| untrusted_arg_interpolates(v.get())) {
|
||||
return Err(Error::BadRequest(format!(
|
||||
"Agent {path} runs on behalf of {}, so its inputs cannot reference variables or resources",
|
||||
obo.permissioned_as
|
||||
|
||||
@@ -76,7 +76,7 @@ use windmill_common::{
|
||||
check_proper_path, http_get_from_hub, not_found_if_none, paginate, paginate_optional,
|
||||
query_elems_from_hub, require_admin, strip_json_nul, Pagination, RunnableKind, StripPath,
|
||||
},
|
||||
variables::{build_crypt, build_crypt_with_key_suffix, encrypt},
|
||||
variables::{build_crypt, build_crypt_with_key_suffix, encrypt, omit_untrusted_interpolation},
|
||||
worker::{to_raw_value, CLOUD_HOSTED},
|
||||
workspaces::{
|
||||
check_deploy_rules, check_operator_can_build, check_user_against_rule,
|
||||
@@ -6553,6 +6553,7 @@ async fn build_args(
|
||||
}
|
||||
}
|
||||
|
||||
let mut untrusted = HashMap::new();
|
||||
for (k, v) in args {
|
||||
if safe_args.contains_key(&k) {
|
||||
continue;
|
||||
@@ -6566,31 +6567,16 @@ async fn build_args(
|
||||
k.to_string(),
|
||||
ctx_value(prop, policy, authed, w_id, db).await?,
|
||||
);
|
||||
} else if !arg_str.contains("\"$var:") && !arg_str.contains("\"$res:") {
|
||||
safe_args.insert(k.to_string(), v);
|
||||
} else {
|
||||
safe_args.insert(
|
||||
k.to_string(),
|
||||
RawValue::from_string(
|
||||
arg_str
|
||||
.replace(
|
||||
"$var:",
|
||||
"The following variable has been omitted for security reasons: ",
|
||||
)
|
||||
.replace(
|
||||
"$res:",
|
||||
"The following resource has been omitted for security reasons, to allow it, toggle: 'Allow resources from users' on that field input: ",
|
||||
),
|
||||
)
|
||||
.map_err(|e| {
|
||||
Error::internal_err(format!(
|
||||
"failed to remove sensitive variable(s)/resource(s) with error: {}",
|
||||
e
|
||||
))
|
||||
})?,
|
||||
);
|
||||
untrusted.insert(k, v);
|
||||
}
|
||||
}
|
||||
safe_args.extend(
|
||||
omit_untrusted_interpolation(
|
||||
untrusted,
|
||||
"The following resource has been omitted for security reasons, to allow it, toggle: 'Allow resources from users' on that field input: ",
|
||||
),
|
||||
);
|
||||
for k in sensitive_inputs {
|
||||
let Some(v) = safe_args.get(k) else { continue };
|
||||
let raw = v.get();
|
||||
|
||||
Reference in New Issue
Block a user