diff --git a/crates/engine/src/cmd/effect.rs b/crates/engine/src/cmd/effect.rs index f41ba3f9c..2d73a2801 100644 --- a/crates/engine/src/cmd/effect.rs +++ b/crates/engine/src/cmd/effect.rs @@ -35,6 +35,14 @@ fn plugins_list(s: &mut Session, _: &Value) -> Result { /// folder) through the host's loader ([`Session::plugin_loader`]). fn plugins_load(s: &mut Session, p: &Value) -> Result { let c = "effect.plugins.load"; + // A plug-in is code, and a file that fails to load comes back in the error: a script may + // load one only with the access it would need to read and write files anywhere. + if s.running_for_script() && !s.prefs.scripting.allow_scripts_write_files { + return Err(bad( + c, + "scripts can't load effect plug-ins unless Settings ▸ Scripting & Expressions ▸ Allow Scripts to Write Files and Access Network is on", + )); + } let loader = s.plugin_loader.ok_or_else(|| EngineError::Other("WebAssembly effect plug-ins are not available in this build".into()))?; let files: Vec = match (str_p(p, "path"), str_p(p, "folder")) { (Some(path), _) => vec![path.to_string()], diff --git a/crates/engine/src/tests/settings.rs b/crates/engine/src/tests/settings.rs index 5e38c90a3..0dac9e6ed 100644 --- a/crates/engine/src/tests/settings.rs +++ b/crates/engine/src/tests/settings.rs @@ -651,6 +651,18 @@ fn context_shortcuts_on_the_same_keys_conflict() { assert!(t.conflicts(b, "F9").iter().any(|c| c.key == "test.paint" && !c.overrides)); } +/// A script loads effect plug-ins only with Allow Scripts to Write Files on. +#[test] +fn scripts_load_effect_plugins_only_with_file_access() { + let mut s = Session::default(); + let p = json!({"path": "/etc/hostname"}); + let e = s.execute_for_script("effect.plugins.load", p.clone()).unwrap_err().to_string(); + assert!(e.contains("Allow Scripts to Write Files"), "{e}"); + s.prefs.scripting.allow_scripts_write_files = true; + let e = s.execute_for_script("effect.plugins.load", p).unwrap_err().to_string(); + assert!(!e.contains("Allow Scripts to Write Files"), "{e}"); +} + // ---------------------------------------------------------------- auto-save / recovery /// The names in `d`, sorted.