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(); } $url = Url::fromRoute( 'entity.field_config.' . $entity->getTargetEntityTypeId() . '_field_edit_form', $url_params ); $items[] = $this->l($item, $url); } 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.'); } } }