More updates to stop using dev or alpha or beta versions.
[yaffs-website] / web / modules / contrib / security_review / src / Checks / Field.php
1 <?php
2
3 namespace Drupal\security_review\Checks;
4
5 use Drupal\Core\Entity\FieldableEntityInterface;
6 use Drupal\Core\TypedData\TypedDataInterface;
7 use Drupal\security_review\Check;
8 use Drupal\security_review\CheckResult;
9 use Drupal\text\Plugin\Field\FieldType\TextItemBase;
10
11 /**
12  * Checks for Javascript and PHP in submitted content.
13  */
14 class Field extends Check {
15
16   /**
17    * {@inheritdoc}
18    */
19   public function getNamespace() {
20     return 'Security Review';
21   }
22
23   /**
24    * {@inheritdoc}
25    */
26   public function getTitle() {
27     return 'Content';
28   }
29
30   /**
31    * {@inheritdoc}
32    */
33   public function getMachineTitle() {
34     return 'field';
35   }
36
37   /**
38    * {@inheritdoc}
39    */
40   public function run() {
41     $result = CheckResult::SUCCESS;
42     $findings = [];
43
44     $tags = [
45       'Javascript' => 'script',
46       'PHP' => '?php',
47     ];
48
49     // Load all of the entities.
50     $entities = [];
51     $bundle_info = $this->entityManager()->getAllBundleInfo();
52     foreach ($bundle_info as $entity_type_id => $bundles) {
53       $current = $this->entityManager()
54         ->getStorage($entity_type_id)
55         ->loadMultiple();
56       $entities = array_merge($entities, $current);
57     }
58
59     // Search for text fields.
60     $text_items = [];
61     foreach ($entities as $entity) {
62       if ($entity instanceof FieldableEntityInterface) {
63         /** @var FieldableEntityInterface $entity */
64         foreach ($entity->getFields() as $field_list) {
65           foreach ($field_list as $field_item) {
66             if ($field_item instanceof TextItemBase) {
67               /** @var TextItemBase $item */
68               // Text field found.
69               $text_items[] = $field_item;
70             }
71           }
72         }
73       }
74     }
75
76     // Scan the text items for vulnerabilities.
77     foreach ($text_items as $item) {
78       $entity = $item->getEntity();
79       foreach ($item->getProperties() as $property) {
80         /** @var TypedDataInterface $property */
81         $value = $property->getValue();
82         if (is_string($value)) {
83           $field_name = $item->getFieldDefinition()->getLabel();
84           foreach ($tags as $vulnerability => $tag) {
85             if (strpos($value, '<' . $tag) !== FALSE) {
86               // Vulnerability found.
87               $findings[$entity->getEntityTypeId()][$entity->id()][$field_name][] = $vulnerability;
88             }
89           }
90         }
91       }
92     }
93
94     if (!empty($findings)) {
95       $result = CheckResult::FAIL;
96     }
97
98     return $this->createResult($result, $findings);
99   }
100
101   /**
102    * {@inheritdoc}
103    */
104   public function help() {
105     $paragraphs = [];
106     $paragraphs[] = $this->t('Script and PHP code in content does not align with Drupal best practices and may be a vulnerability if an untrusted user is allowed to edit such content. It is recommended you remove such contents.');
107
108     return [
109       '#theme' => 'check_help',
110       '#title' => $this->t('Dangerous tags in content'),
111       '#paragraphs' => $paragraphs,
112     ];
113   }
114
115   /**
116    * {@inheritdoc}
117    */
118   public function evaluate(CheckResult $result) {
119     $findings = $result->findings();
120     if (empty($findings)) {
121       return [];
122     }
123
124     $paragraphs = [];
125     $paragraphs[] = $this->t('The following items potentially have dangerous tags.');
126
127     $items = [];
128     foreach ($findings as $entity_type_id => $entities) {
129       foreach ($entities as $entity_id => $fields) {
130         $entity = $this->entityManager()
131           ->getStorage($entity_type_id)
132           ->load($entity_id);
133
134         foreach ($fields as $field => $finding) {
135           $url = $entity->toUrl('edit-form');
136           if ($url === NULL) {
137             $url = $entity->toUrl();
138           }
139           $items[] = $this->t(
140             '@vulnerabilities found in <em>@field</em> field of <a href=":url">@label</a>',
141             [
142               '@vulnerabilities' => implode(' and ', $finding),
143               '@field' => $field,
144               '@label' => $entity->label(),
145               ':url' => $url->toString(),
146             ]
147           );
148         }
149       }
150     }
151
152     return [
153       '#theme' => 'check_evaluation',
154       '#paragraphs' => $paragraphs,
155       '#items' => $items,
156     ];
157   }
158
159   /**
160    * {@inheritdoc}
161    */
162   public function evaluatePlain(CheckResult $result) {
163     $findings = $result->findings();
164     if (empty($findings)) {
165       return '';
166     }
167
168     $output = '';
169     foreach ($findings as $entity_type_id => $entities) {
170       foreach ($entities as $entity_id => $fields) {
171         $entity = $this->entityManager()
172           ->getStorage($entity_type_id)
173           ->load($entity_id);
174
175         foreach ($fields as $field => $finding) {
176           $url = $entity->toUrl('edit-form');
177           if ($url === NULL) {
178             $url = $entity->toUrl();
179           }
180           $output .= "\t" . $this->t(
181               '@vulnerabilities in @field of :link',
182               [
183                 '@vulnerabilities' => implode(' and ', $finding),
184                 '@field' => $field,
185                 ':link' => $url->toString(),
186               ]
187             ) . "\n";
188         }
189       }
190     }
191
192     return $output;
193   }
194
195   /**
196    * {@inheritdoc}
197    */
198   public function getMessage($result_const) {
199     switch ($result_const) {
200       case CheckResult::SUCCESS:
201         return $this->t('Dangerous tags were not found in any submitted content (fields).');
202
203       case CheckResult::FAIL:
204         return $this->t('Dangerous tags were found in submitted content (fields).');
205
206       default:
207         return $this->t('Unexpected result.');
208     }
209   }
210
211 }