moduleHandler()->moduleExists('field')) {
return $this->createResult(CheckResult::INFO);
}
$result = CheckResult::SUCCESS;
$findings = [];
// Check field configuration entities.
foreach (FieldConfig::loadMultiple() as $entity) {
/** @var FieldConfig $entity */
$extensions = $entity->getSetting('file_extensions');
if ($extensions != NULL) {
$extensions = explode(' ', $extensions);
$intersect = array_intersect($extensions, $this->security()->unsafeExtensions());
// $intersect holds the unsafe extensions this entity allows.
foreach ($intersect as $unsafe_extension) {
$findings[$entity->id()][] = $unsafe_extension;
}
}
}
if (!empty($findings)) {
$result = CheckResult::FAIL;
}
return $this->createResult($result, $findings);
}
/**
* {@inheritdoc}
*/
public function help() {
$paragraphs = [];
$paragraphs[] = $this->t(
'File and image fields allow for uploaded files. Some extensions are considered dangerous because the files can be evaluated and then executed in the browser. A malicious user could use this opening to gain control of your site. Review all fields on your site.',
[':url' => Url::fromRoute('entity.field_storage_config.collection')->toString()]
);
return [
'#theme' => 'check_help',
'#title' => 'Allowed upload extensions',
'#paragraphs' => $paragraphs,
];
}
/**
* {@inheritdoc}
*/
public function evaluate(CheckResult $result) {
$findings = $result->findings();
if (empty($findings)) {
return [];
}
$paragraphs = [];
$paragraphs[] = $this->t('The following extensions are considered unsafe and should be removed or limited from use. Or, be sure you are not granting untrusted users the ability to upload files.');
$items = [];
foreach ($findings as $entity_id => $unsafe_extensions) {
$entity = FieldConfig::load($entity_id);
/** @var FieldConfig $entity */
foreach ($unsafe_extensions as $extension) {
$item = $this->t(
'Review @type in @field field on @bundle',
[
'@type' => $extension,
'@field' => $entity->label(),
'@bundle' => $entity->getTargetBundle(),
]
);
// Try to get an edit url.
try {
$url_params = ['field_config' => $entity->id()];
if ($entity->getTargetEntityTypeId() == 'node') {
$url_params['node_type'] = $entity->getTargetBundle();
}
$items[] = Link::createFromRoute(
$item,
sprintf('entity.field_config.%s_field_edit_form', $entity->getTargetEntityTypeId()),
$url_params
);
}
catch (RouteNotFoundException $e) {
$items[] = $item;
}
}
}
return [
'#theme' => 'check_evaluation',
'#paragraphs' => $paragraphs,
'#items' => $items,
];
}
/**
* {@inheritdoc}
*/
public function evaluatePlain(CheckResult $result) {
$findings = $result->findings();
if (empty($findings)) {
return '';
}
$output = '';
foreach ($findings as $entity_id => $unsafe_extensions) {
$entity = FieldConfig::load($entity_id);
/** @var FieldConfig $entity */
$output .= $this->t(
'@bundle: field @field',
[
'@bundle' => $entity->getTargetBundle(),
'@field' => $entity->label(),
]
);
$output .= "\n\t" . implode(', ', $unsafe_extensions) . "\n";
}
return $output;
}
/**
* {@inheritdoc}
*/
public function getMessage($result_const) {
switch ($result_const) {
case CheckResult::SUCCESS:
return $this->t('Only safe extensions are allowed for uploaded files and images.');
case CheckResult::FAIL:
return $this->t('Unsafe file extensions are allowed in uploads.');
case CheckResult::INFO:
return $this->t('Module field is not enabled.');
default:
return $this->t('Unexpected result.');
}
}
}