3 namespace Drupal\security_review\Checks;
7 use Drupal\security_review\Check;
8 use Drupal\security_review\CheckResult;
11 * Checks for vulnerabilities related to input formats.
13 * Checks for formats that either do not have HTML filter that can be used by
14 * untrusted users, or if they do check if unsafe tags are allowed.
16 class InputFormats extends Check {
21 public function getNamespace() {
22 return 'Security Review';
28 public function getTitle() {
29 return 'Text formats';
35 public function getMachineTitle() {
36 return 'input_formats';
42 public function run() {
43 // If filter is not enabled return with INFO.
44 if (!$this->moduleHandler()->moduleExists('filter')) {
45 return $this->createResult(CheckResult::INFO);
48 $result = CheckResult::SUCCESS;
51 $formats = filter_formats();
52 $untrusted_roles = $this->security()->untrustedRoles();
53 $unsafe_tags = $this->security()->unsafeTags();
55 foreach ($formats as $format) {
56 $format_roles = array_keys(filter_get_roles_by_format($format));
57 $intersect = array_intersect($format_roles, $untrusted_roles);
59 if (!empty($intersect)) {
60 // Untrusted users can use this format.
61 // Check format for enabled HTML filter.
62 $filter_html_enabled = FALSE;
63 if ($format->filters()->has('filter_html')) {
64 $filter_html_enabled = $format->filters('filter_html')
65 ->getConfiguration()['status'];
67 $filter_html_escape_enabled = FALSE;
68 if ($format->filters()->has('filter_html_escape')) {
69 $filter_html_escape_enabled = $format->filters('filter_html_escape')
70 ->getConfiguration()['status'];
73 if ($filter_html_enabled) {
74 $filter = $format->filters('filter_html');
76 // Check for unsafe tags in allowed tags.
77 $allowed_tags = array_keys($filter->getHTMLRestrictions()['allowed']);
78 foreach (array_intersect($allowed_tags, $unsafe_tags) as $tag) {
79 // Found an unsafe tag.
80 $findings['tags'][$format->id()] = $tag;
83 elseif (!$filter_html_escape_enabled) {
84 // Format is usable by untrusted users but does not contain the HTML
85 // Filter or the HTML escape.
86 $findings['formats'][$format->id()] = $format->label();
91 if (!empty($findings)) {
92 $result = CheckResult::FAIL;
94 return $this->createResult($result, $findings);
100 public function help() {
102 $paragraphs[] = $this->t("Certain HTML tags can allow an attacker to take control of your site. Drupal's input format system makes use of a set filters to run on incoming text. The 'HTML Filter' strips out harmful tags and Javascript events and should be used on all formats accessible by untrusted users.");
103 $paragraphs[] = new Link(
104 $this->t("Read more about Drupal's input formats in the handbooks."),
105 Url::fromUri('http://drupal.org/node/224921')
109 '#theme' => 'check_help',
110 '#title' => $this->t('Allowed HTML tags in text formats'),
111 '#paragraphs' => $paragraphs,
118 public function evaluate(CheckResult $result) {
121 if (!empty($result->findings()['tags'])) {
123 $paragraphs[] = Link::createFromRoute(
124 $this->t('Review your text formats.'),
125 'filter.admin_overview'
127 $paragraphs[] = $this->t('It is recommended you remove the following tags from roles accessible by untrusted users.');
129 '#theme' => 'check_evaluation',
130 '#paragraphs' => $paragraphs,
131 '#items' => $result->findings()['tags'],
135 if (!empty($result->findings()['formats'])) {
137 $paragraphs[] = $this->t('The following formats are usable by untrusted roles and do not filter or escape allowed HTML tags.');
139 '#theme' => 'check_evaluation',
140 '#paragraphs' => $paragraphs,
141 '#items' => $result->findings()['formats'],
151 public function evaluatePlain(CheckResult $result) {
154 if (!empty($result->findings()['tags'])) {
155 $output .= $this->t('Tags') . "\n";
156 foreach ($result->findings()['tags'] as $tag) {
157 $output .= "\t$tag\n";
161 if (!empty($result->findings()['formats'])) {
162 $output .= $this->t('Formats') . "\n";
163 foreach ($result->findings()['formats'] as $format) {
164 $output .= "\t$format\n";
174 public function getMessage($result_const) {
175 switch ($result_const) {
176 case CheckResult::SUCCESS:
177 return $this->t('Untrusted users are not allowed to input dangerous HTML tags.');
179 case CheckResult::FAIL:
180 return $this->t('Untrusted users are allowed to input dangerous HTML tags.');
182 case CheckResult::INFO:
183 return $this->t('Module filter is not enabled.');
186 return $this->t('Unexpected result.');