diff --git a/src/lib-sieve/sieve-script-private.h b/src/lib-sieve/sieve-script-private.h
index c0b7433e3f6cf4460568f201e8ec7ea8b8c7d714..d23ce0f79216d5fc2379ce2ef1195bc559908bf9 100644
--- a/src/lib-sieve/sieve-script-private.h
+++ b/src/lib-sieve/sieve-script-private.h
@@ -74,6 +74,20 @@ void sieve_script_init(struct sieve_script *script,
 		       const struct sieve_script *script_class,
 		       const char *location, const char *name);
 
+/*
+ * Binary
+ */
+
+int sieve_script_binary_load_default(struct sieve_script *script,
+				     const char *path,
+				     struct sieve_binary **sbin_r,
+				     enum sieve_error *error_code_r);
+int sieve_script_binary_save_default(struct sieve_script *script,
+				     struct sieve_binary *sbin,
+				     const char *path, bool update,
+				     mode_t save_mode,
+				     enum sieve_error *error_code_r);
+
 /*
  * Built-in script drivers
  */
diff --git a/src/lib-sieve/sieve-script.c b/src/lib-sieve/sieve-script.c
index b15c197accda730757d2ae5254981f35bb72c10b..aa34673a5269f115c9a88d41c77a2c1051ee8e28 100644
--- a/src/lib-sieve/sieve-script.c
+++ b/src/lib-sieve/sieve-script.c
@@ -9,6 +9,7 @@
 #include "hash.h"
 #include "array.h"
 #include "eacces-error.h"
+#include "mkdir-parents.h"
 #include "istream.h"
 
 #include "sieve-common.h"
@@ -503,6 +504,31 @@ bool sieve_script_binary_dump_metadata(struct sieve_script *script,
 	return result;
 }
 
+int sieve_script_binary_load_default(struct sieve_script *script,
+				     const char *path,
+				     struct sieve_binary **sbin_r,
+				     enum sieve_error *error_code_r)
+{
+	struct sieve_instance *svinst = script->storage->svinst;
+	enum sieve_error error_code;
+
+	if (path == NULL) {
+		sieve_script_set_error(
+			script, SIEVE_ERROR_NOT_POSSIBLE,
+			"Cannot load script binary for this storage");
+		*error_code_r = script->storage->error_code;
+		return -1;
+	}
+
+	if (sieve_binary_open(svinst, path, script, sbin_r, &error_code) < 0) {
+		sieve_script_set_error(script, error_code,
+				       "Failed to load script binary");
+		*error_code_r = script->storage->error_code;
+		return -1;
+	}
+	return 0;
+}
+
 int sieve_script_binary_load(struct sieve_script *script,
 			     struct sieve_binary **sbin_r,
 			     enum sieve_error *error_code_r)
@@ -525,6 +551,42 @@ int sieve_script_binary_load(struct sieve_script *script,
 	return ret;
 }
 
+int sieve_script_binary_save_default(struct sieve_script *script ATTR_UNUSED,
+				     struct sieve_binary *sbin,
+				     const char *path, bool update,
+				     mode_t save_mode,
+				     enum sieve_error *error_code_r)
+{
+	struct sieve_storage *storage = script->storage;
+	enum sieve_error error_code;
+	int ret;
+
+	if (path == NULL) {
+		sieve_script_set_error(
+			script, SIEVE_ERROR_NOT_POSSIBLE,
+			"Cannot save script binary for this storage");
+		*error_code_r = script->storage->error_code;
+		return -1;
+	}
+
+	if (storage->bin_path != NULL &&
+	    str_begins_with(path, storage->bin_path) &&
+	    sieve_storage_setup_bin_path(
+		script->storage, mkdir_get_executable_mode(save_mode)) < 0) {
+		*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
+		return -1;
+	}
+
+	ret = sieve_binary_save(sbin, path, update, save_mode, &error_code);
+	if (ret < 0) {
+		sieve_script_set_error(script, error_code,
+				       "Failed to save script binary");
+		*error_code_r = script->storage->error_code;
+		return -1;
+	}
+	return 0;
+}
+
 int sieve_script_binary_save(struct sieve_script *script,
 			     struct sieve_binary *sbin, bool update,
 			     enum sieve_error *error_code_r)
diff --git a/src/lib-sieve/storage/dict/sieve-dict-script.c b/src/lib-sieve/storage/dict/sieve-dict-script.c
index b03fbc31c98f33cf988184623d9339e3a656fb59..dcd062487fab3a1747ffcc95aa13682331e41dd6 100644
--- a/src/lib-sieve/storage/dict/sieve-dict-script.c
+++ b/src/lib-sieve/storage/dict/sieve-dict-script.c
@@ -232,11 +232,9 @@ sieve_dict_script_binary_load(struct sieve_script *script,
 	struct sieve_dict_script *dscript =
 		container_of(script, struct sieve_dict_script, script);
 
-	if (sieve_dict_script_get_bin_path(dscript) == NULL)
-		return -1;
-
-	return sieve_binary_open(script->storage->svinst, dscript->bin_path,
-				 script, sbin_r, error_code_r);
+	return sieve_script_binary_load_default(
+		script, sieve_dict_script_get_bin_path(dscript),
+		sbin_r, error_code_r);
 }
 
 static int
@@ -247,13 +245,9 @@ sieve_dict_script_binary_save(struct sieve_script *script,
 	struct sieve_dict_script *dscript =
 		container_of(script, struct sieve_dict_script, script);
 
-	if (sieve_dict_script_get_bin_path(dscript) == NULL)
-		return 0;
-	if (sieve_storage_setup_bin_path(script->storage, 0700) < 0)
-		return -1;
-
-	return sieve_binary_save(sbin, dscript->bin_path, update, 0600,
-				 error_code_r);
+	return sieve_script_binary_save_default(
+		script, sbin, sieve_dict_script_get_bin_path(dscript),
+		update, 0600, error_code_r);
 }
 
 static int
diff --git a/src/lib-sieve/storage/file/sieve-file-script.c b/src/lib-sieve/storage/file/sieve-file-script.c
index 959ba631198a832aef9a3a357472f5b0d96d3695..a416fbe79b5773759f96f2774b5890bf68197cf8 100644
--- a/src/lib-sieve/storage/file/sieve-file-script.c
+++ b/src/lib-sieve/storage/file/sieve-file-script.c
@@ -537,10 +537,9 @@ sieve_file_script_binary_load(struct sieve_script *script,
 {
 	struct sieve_file_script *fscript =
 		container_of(script, struct sieve_file_script, script);
-	struct sieve_instance *svinst = script->storage->svinst;
 
-	return sieve_binary_open(svinst, fscript->bin_path, script,
-				 sbin_r, error_code_r);
+	return sieve_script_binary_load_default(script, fscript->bin_path,
+						sbin_r, error_code_r);
 }
 
 static int
@@ -548,16 +547,12 @@ sieve_file_script_binary_save(struct sieve_script *script,
 			      struct sieve_binary *sbin, bool update,
 			      enum sieve_error *error_code_r)
 {
-	struct sieve_storage *storage = script->storage;
 	struct sieve_file_script *fscript =
 		container_of(script, struct sieve_file_script, script);
 
-	if (storage->bin_path != NULL &&
-	    sieve_storage_setup_bin_path(storage, 0700) < 0)
-		return -1;
-
-	return sieve_binary_save(sbin, fscript->bin_path, update,
-				 (fscript->st.st_mode & 0777), error_code_r);
+	return sieve_script_binary_save_default(
+		script, sbin, fscript->bin_path, update,
+		(fscript->st.st_mode & 0777), error_code_r);
 }
 
 static const char *
diff --git a/src/lib-sieve/storage/ldap/sieve-ldap-script.c b/src/lib-sieve/storage/ldap/sieve-ldap-script.c
index 102028849475998b0269083478980c25498175de..3f416daa5afb1b594c3f7cf07576d77f5218c028 100644
--- a/src/lib-sieve/storage/ldap/sieve-ldap-script.c
+++ b/src/lib-sieve/storage/ldap/sieve-ldap-script.c
@@ -251,15 +251,12 @@ sieve_ldap_script_binary_load(struct sieve_script *script,
 			      struct sieve_binary **sbin_r,
 			      enum sieve_error *error_code_r)
 {
-	struct sieve_storage *storage = script->storage;
 	struct sieve_ldap_script *lscript =
 		container_of(script, struct sieve_ldap_script, script);
 
-	if (sieve_ldap_script_get_bin_path(lscript) == NULL)
-		return -1;
-
-	return sieve_binary_open(storage->svinst, lscript->bin_path, script,
-				 sbin_r, error_code_r);
+	return sieve_script_binary_load_default(
+		script, sieve_ldap_script_get_bin_path(lscript),
+		sbin_r, error_code_r);
 }
 
 static int
@@ -270,13 +267,9 @@ sieve_ldap_script_binary_save(struct sieve_script *script,
 	struct sieve_ldap_script *lscript =
 		container_of(script, struct sieve_ldap_script, script);
 
-	if (sieve_ldap_script_get_bin_path(lscript) == NULL)
-		return 0;
-	if (sieve_storage_setup_bin_path(script->storage, 0700) < 0)
-		return -1;
-
-	return sieve_binary_save(sbin, lscript->bin_path, update, 0600,
-				 error_code_r);
+	return sieve_script_binary_save_default(
+		script, sbin, sieve_ldap_script_get_bin_path(lscript),
+		update, 0600, error_code_r);
 }
 
 static int