diff --git a/auth/shibboleth/README.txt b/auth/shibboleth/README.txt
index d1adb680aee..eaaddacb7c4 100644
--- a/auth/shibboleth/README.txt
+++ b/auth/shibboleth/README.txt
@@ -182,7 +182,8 @@ How to customize the way the Shibboleth user data is used in Moodle
Among the Shibboleth settings in Moodle there is a field that should contain a
path to a php file that can be used as data manipulation hook.
You can use this if you want to further process the way your Shibboleth
-attributes are used in Moodle.
+attributes are used in Moodle. Due to security reasons this file cannot be
+located within the current site data directory ($CFG->dataroot).
Example 1: Your Shibboleth federation uses an attribute that specifies the
user's preferred language, but the content of this attribute is not
diff --git a/auth/shibboleth/classes/admin_setting_special_convert_data_configfile.php b/auth/shibboleth/classes/admin_setting_special_convert_data_configfile.php
new file mode 100644
index 00000000000..a11ff42579f
--- /dev/null
+++ b/auth/shibboleth/classes/admin_setting_special_convert_data_configfile.php
@@ -0,0 +1,75 @@
+.
+
+/**
+ * Special setting for auth_shibboleth convert_data.
+ *
+ * @package auth_shibboleth
+ * @copyright 2020 Mihail Geshoski
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/**
+ * Admin settings class for the convert_data option.
+ *
+ * @package auth_shibboleth
+ * @copyright 2020 Mihail Geshoski
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class auth_shibboleth_admin_setting_convert_data extends admin_setting_configfile {
+
+ /**
+ * Constructor.
+ *
+ * @param string $name
+ * @param string $visiblename
+ * @param string $description
+ * @param mixed $defaultdirectory
+ */
+ public function __construct($name, $visiblename, $description, $defaultdirectory) {
+ parent::__construct($name, $visiblename, $description, $defaultdirectory);
+ }
+
+ /**
+ * Validate the file path (location).
+ *
+ * This method ensures that the file defined as a data modification API exists and is not located in the site
+ * data directory ($CFG->dataroot). We should prohibit using files from the site data directory as this introduces
+ * security vulnerabilities.
+ *
+ * @param string $filepath The path to the file.
+ * @return mixed bool true for success or string:error on failure.
+ */
+ public function validate($filepath) {
+ global $CFG;
+
+ if (empty($filepath)) {
+ return true;
+ }
+
+ // Fail if the file does not exist or it is not readable by the webserver process.
+ if (!is_readable($filepath)) {
+ return get_string('auth_shib_convert_data_warning', 'auth_shibboleth');
+ }
+
+ // Fail if the absolute file path matches the currently defined dataroot path.
+ if (preg_match('/' . preg_quote($CFG->dataroot, '/') . '/', realpath($filepath))) {
+ return get_string('auth_shib_convert_data_filepath_warning', 'auth_shibboleth');
+ }
+
+ return true;
+ }
+}
diff --git a/auth/shibboleth/lang/en/auth_shibboleth.php b/auth/shibboleth/lang/en/auth_shibboleth.php
index ca9b65b81ad..931d2f39151 100644
--- a/auth/shibboleth/lang/en/auth_shibboleth.php
+++ b/auth/shibboleth/lang/en/auth_shibboleth.php
@@ -38,6 +38,7 @@ $string['auth_shibboleth_select_organization'] = 'For authentication via Shibbol
$string['auth_shib_convert_data'] = 'Data modification API';
$string['auth_shib_convert_data_description'] = 'You can use this API to further modify the data provided by Shibboleth. Read the README for further instructions.';
$string['auth_shib_convert_data_warning'] = 'The file does not exist or is not readable by the webserver process!';
+$string['auth_shib_convert_data_filepath_warning'] = 'You cannot use a file that is located within the current site data directory ($CFG->dataroot) as the data modification API.';
$string['auth_shib_changepasswordurl'] = 'Password-change URL';
$string['auth_shib_idp_list'] = 'Identity providers';
$string['auth_shib_idp_list_description'] = 'Provide a list of Identity Provider entityIDs to let the user choose from on the login page.
On each line there must be a comma-separated tuple for entityID of the IdP (see the Shibboleth metadata file) and Name of IdP as it shall be displayed in the drop-down list.
As an optional third parameter you can add the location of a Shibboleth session initiator that shall be used in case your Moodle installation is part of a multi federation setup.';
diff --git a/auth/shibboleth/settings.php b/auth/shibboleth/settings.php
index 86dce35a927..7c2117ec824 100644
--- a/auth/shibboleth/settings.php
+++ b/auth/shibboleth/settings.php
@@ -28,6 +28,7 @@ if ($ADMIN->fulltree) {
// We use a couple of custom admin settings since we need to massage the data before it is inserted into the DB.
require_once($CFG->dirroot.'/auth/shibboleth/classes/admin_setting_special_wayf_select.php');
require_once($CFG->dirroot.'/auth/shibboleth/classes/admin_setting_special_idp_configtextarea.php');
+ require_once($CFG->dirroot.'/auth/shibboleth/classes/admin_setting_special_convert_data_configfile.php');
// Introductory explanation.
$readmeurl = (new moodle_url('/auth/shibboleth/README.txt'))->out();
@@ -38,8 +39,8 @@ if ($ADMIN->fulltree) {
$settings->add(new admin_setting_configtext('auth_shibboleth/user_attribute', get_string('username'),
get_string('auth_shib_username_description', 'auth_shibboleth'), '', PARAM_RAW));
- // COnvert Data configuration file.
- $settings->add(new admin_setting_configfile('auth_shibboleth/convert_data',
+ // Convert Data configuration file.
+ $settings->add(new auth_shibboleth_admin_setting_convert_data('auth_shibboleth/convert_data',
get_string('auth_shib_convert_data', 'auth_shibboleth'),
get_string('auth_shib_convert_data_description', 'auth_shibboleth', $readmeurl), ''));
diff --git a/auth/shibboleth/upgrade.txt b/auth/shibboleth/upgrade.txt
index 9083025cd42..0acea5de397 100644
--- a/auth/shibboleth/upgrade.txt
+++ b/auth/shibboleth/upgrade.txt
@@ -1,6 +1,11 @@
This files describes API changes in /auth/shibboleth/*,
information provided here is intended especially for developers.
+=== 3.11 ===
+
+* The 'Data modification API' (convert_data) setting can no longer be configured to use files located within the
+ current site data directory ($CFG->dataroot), as it exposes the site to security risks.
+
=== 3.5.2 ===
* Moved the public function unserializesession in auth/shibboleth/logout.php to auth/shibboleth/classes/helper.php and