3 namespace Drupal\security_review\Checks;
7 use Drupal\field\Entity\FieldConfig;
8 use Drupal\security_review\Check;
9 use Drupal\security_review\CheckResult;
10 use Symfony\Component\Routing\Exception\RouteNotFoundException;
13 * Checks for unsafe extensions in the allowed extensions settings of fields.
15 class UploadExtensions extends Check {
20 public function getNamespace() {
21 return 'Security Review';
27 public function getTitle() {
28 return 'Allowed upload extensions';
34 public function getMachineTitle() {
35 return 'upload_extensions';
41 public function run() {
42 // If field is not enabled return with INFO.
43 if (!$this->moduleHandler()->moduleExists('field')) {
44 return $this->createResult(CheckResult::INFO);
47 $result = CheckResult::SUCCESS;
50 // Check field configuration entities.
51 foreach (FieldConfig::loadMultiple() as $entity) {
52 /** @var FieldConfig $entity */
53 $extensions = $entity->getSetting('file_extensions');
54 if ($extensions != NULL) {
55 $extensions = explode(' ', $extensions);
56 $intersect = array_intersect($extensions, $this->security()->unsafeExtensions());
57 // $intersect holds the unsafe extensions this entity allows.
58 foreach ($intersect as $unsafe_extension) {
59 $findings[$entity->id()][] = $unsafe_extension;
64 if (!empty($findings)) {
65 $result = CheckResult::FAIL;
68 return $this->createResult($result, $findings);
74 public function help() {
76 $paragraphs[] = $this->t(
77 '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 <a href=":url">all fields on your site</a>.',
78 [':url' => Url::fromRoute('entity.field_storage_config.collection')->toString()]
82 '#theme' => 'check_help',
83 '#title' => 'Allowed upload extensions',
84 '#paragraphs' => $paragraphs,
91 public function evaluate(CheckResult $result) {
92 $findings = $result->findings();
93 if (empty($findings)) {
98 $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.');
101 foreach ($findings as $entity_id => $unsafe_extensions) {
102 $entity = FieldConfig::load($entity_id);
103 /** @var FieldConfig $entity */
105 foreach ($unsafe_extensions as $extension) {
107 'Review @type in <em>@field</em> field on @bundle',
109 '@type' => $extension,
110 '@field' => $entity->label(),
111 '@bundle' => $entity->getTargetBundle(),
115 // Try to get an edit url.
117 $url_params = ['field_config' => $entity->id()];
118 if ($entity->getTargetEntityTypeId() == 'node') {
119 $url_params['node_type'] = $entity->getTargetBundle();
121 $items[] = Link::createFromRoute(
123 sprintf('entity.field_config.%s_field_edit_form', $entity->getTargetEntityTypeId()),
127 catch (RouteNotFoundException $e) {
134 '#theme' => 'check_evaluation',
135 '#paragraphs' => $paragraphs,
143 public function evaluatePlain(CheckResult $result) {
144 $findings = $result->findings();
145 if (empty($findings)) {
150 foreach ($findings as $entity_id => $unsafe_extensions) {
151 $entity = FieldConfig::load($entity_id);
152 /** @var FieldConfig $entity */
155 '@bundle: field @field',
157 '@bundle' => $entity->getTargetBundle(),
158 '@field' => $entity->label(),
161 $output .= "\n\t" . implode(', ', $unsafe_extensions) . "\n";
170 public function getMessage($result_const) {
171 switch ($result_const) {
172 case CheckResult::SUCCESS:
173 return $this->t('Only safe extensions are allowed for uploaded files and images.');
175 case CheckResult::FAIL:
176 return $this->t('Unsafe file extensions are allowed in uploads.');
178 case CheckResult::INFO:
179 return $this->t('Module field is not enabled.');
182 return $this->t('Unexpected result.');