new: [security] added functionality to tighten bookmark creation rules
- site admins can now limit the baseurls of the provided bookmark URLs to a list of values via the server settingspull/187/head
parent
ab331dcfb9
commit
55cac2e2e6
|
@ -79,6 +79,10 @@ class UserSettingsController extends AppController
|
|||
if (empty($currentUser['role']['perm_community_admin'])) {
|
||||
$data['user_id'] = $currentUser->id;
|
||||
}
|
||||
$validationResult = $this->UserSettings->validateUserSetting($data, $currentUser);
|
||||
if (!$validationResult !== true) {
|
||||
throw new MethodNotAllowedException(__('You cannot create the given user setting. Reason: {0}', $validationResult));
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
]);
|
||||
|
@ -131,6 +135,10 @@ class UserSettingsController extends AppController
|
|||
if ($data['user_id'] != $entity->user_id) {
|
||||
throw new MethodNotAllowedException(__('You cannot assign the setting to a different user.'));
|
||||
}
|
||||
$validationResult = $this->UserSettings->validateUserSetting($data);
|
||||
if ($validationResult !== true) {
|
||||
throw new MethodNotAllowedException(__('Setting value: {0}', $validationResult));
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
]);
|
||||
|
|
|
@ -338,6 +338,17 @@ class CerebrateSettingsProvider extends BaseSettingsProvider
|
|||
],
|
||||
]
|
||||
],
|
||||
'Restrictions' => [
|
||||
'Allowed bookmark domains' => [
|
||||
'security.restrictions.allowed_bookmark_domains' => [
|
||||
'name' => __('Allowed bookmark domains'),
|
||||
'type' => 'string',
|
||||
'severity' => 'info',
|
||||
'description' => __('Comma separated list of allowed bookmark domains. Leave empty to allow all domains.'),
|
||||
'default' => '',
|
||||
],
|
||||
],
|
||||
],
|
||||
'Development' => [
|
||||
'Debugging' => [
|
||||
'debug' => [
|
||||
|
|
|
@ -5,6 +5,7 @@ namespace App\Model\Table;
|
|||
use App\Model\Table\AppTable;
|
||||
use Cake\ORM\Table;
|
||||
use Cake\Validation\Validator;
|
||||
use Cake\Core\Configure;
|
||||
|
||||
require_once(APP . 'Model' . DS . 'Table' . DS . 'SettingProviders' . DS . 'UserSettingsProvider.php');
|
||||
use App\Settings\SettingsProvider\UserSettingsProvider;
|
||||
|
@ -102,6 +103,14 @@ class UserSettingsTable extends AppTable
|
|||
'name' => $data['bookmark_name'],
|
||||
'url' => $data['bookmark_url'],
|
||||
];
|
||||
$restricted_domains = Configure::read('Security.restrictions.allowed_bookmark_domains');
|
||||
if (!empty($restricted_domains)) {
|
||||
$restricted_domains = explode(',', $restricted_domains);
|
||||
$parsed = parse_url($bookmarkData['url']);
|
||||
if (!in_array($parsed['host'], $restricted_domains)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (is_null($setting)) { // setting not found, create it
|
||||
$bookmarksData = json_encode([$bookmarkData]);
|
||||
$result = $this->createSetting($user, $this->BOOKMARK_SETTING_NAME, $bookmarksData);
|
||||
|
@ -153,4 +162,40 @@ class UserSettingsTable extends AppTable
|
|||
}
|
||||
return $isLocalPath || $isValidURL;
|
||||
}
|
||||
|
||||
public function validateUserSetting($data): bool|string
|
||||
{
|
||||
$errors = [];
|
||||
$json_fields = ['ui.bookmarks'];
|
||||
if (in_array($data['name'], $json_fields)) {
|
||||
$decoded = json_decode($data['value'], true);
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
return __('Invalid JSON data');
|
||||
}
|
||||
$value = $decoded;
|
||||
} else {
|
||||
$value = $data['value'];
|
||||
}
|
||||
if ($data['name'] === 'ui.bookmarks') {
|
||||
if (array_values($value) !== $value) {
|
||||
$value = [$value];
|
||||
}
|
||||
$restricted_domains = Configure::read('security.restrictions.allowed_bookmark_domains');
|
||||
if (!empty($restricted_domains)) {
|
||||
$restricted_domains = explode(',', $restricted_domains);
|
||||
foreach ($restricted_domains as &$rd) {
|
||||
$rd = trim($rd);
|
||||
}
|
||||
}
|
||||
foreach ($value as $bookmark) {
|
||||
if (!empty($restricted_domains)) {
|
||||
$parsed = parse_url($bookmark['url']);
|
||||
if (!in_array($parsed['host'], $restricted_domains)) {
|
||||
return __('Invalid domain for bookmark. The only domains allowed are: {0}', implode(', ', $restricted_domains));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue