class Field in Security Review 8
Checks for Javascript and PHP in submitted content.
Hierarchy
- class \Drupal\security_review\Check uses DependencySerializationTrait, StringTranslationTrait
- class \Drupal\security_review\Checks\Field
Expanded class hierarchy of Field
1 file declares its use of Field
- security_review.module in ./
security_review.module - Site security review and reporting Drupal module.
File
- src/
Checks/ Field.php, line 14
Namespace
Drupal\security_review\ChecksView source
class Field extends Check {
/**
* {@inheritdoc}
*/
public function getNamespace() {
return 'Security Review';
}
/**
* {@inheritdoc}
*/
public function getTitle() {
return 'Content';
}
/**
* {@inheritdoc}
*/
public function getMachineTitle() {
return 'field';
}
/**
* {@inheritdoc}
*/
public function run() {
$result = CheckResult::SUCCESS;
$findings = [];
$field_types = [
'text_with_summary',
'text_long',
];
$tags = [
'Javascript' => 'script',
'PHP' => '?php',
];
/** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager */
$entity_type_manager = \Drupal::service('entity_type.manager');
/** @var \Drupal\Core\Entity\EntityFieldManagerInterface $field_manager */
$field_manager = \Drupal::service('entity_field.manager');
foreach ($field_manager
->getFieldMap() as $entity_type_id => $fields) {
$field_storage_definitions = $field_manager
->getFieldStorageDefinitions($entity_type_id);
foreach ($fields as $field_name => $field) {
if (!isset($field_storage_definitions[$field_name])) {
continue;
}
$field_storage_definition = $field_storage_definitions[$field_name];
if (in_array($field_storage_definition
->getType(), $field_types)) {
if ($field_storage_definition instanceof FieldStorageConfig) {
$table = $entity_type_id . '__' . $field_name;
$separator = '_';
$id = 'entity_id';
}
else {
$entity = $entity_type_manager
->getStorage($entity_type_id)
->getEntityType();
$translatable = $entity
->isTranslatable();
$table = '';
if ($translatable) {
$table = $entity
->getDataTable() ?: $entity_type_id . '_field_data';
}
else {
$table = $entity
->getBaseTable() ?: $entity_type_id;
}
$separator = '__';
$id = $entity
->getKey('id');
}
$rows = \Drupal::database()
->select($table, 't')
->fields('t')
->execute()
->fetchAll();
foreach ($rows as $row) {
foreach (array_keys($field_storage_definition
->getSchema()['columns']) as $column) {
$column_name = $field_name . $separator . $column;
foreach ($tags as $vulnerability => $tag) {
if (strpos($row->{$column_name}, '<' . $tag) !== FALSE) {
// Vulnerability found.
$findings[$entity_type_id][$row->{$id}][$field_name][] = $vulnerability;
}
}
}
}
}
}
}
if (!empty($findings)) {
$result = CheckResult::FAIL;
}
return $this
->createResult($result, $findings);
}
/**
* {@inheritdoc}
*/
public function help() {
$paragraphs = [];
$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.');
return [
'#theme' => 'check_help',
'#title' => $this
->t('Dangerous tags in content'),
'#paragraphs' => $paragraphs,
];
}
/**
* {@inheritdoc}
*/
public function evaluate(CheckResult $result) {
$findings = $result
->findings();
if (empty($findings)) {
return [];
}
$paragraphs = [];
$paragraphs[] = $this
->t('The following items potentially have dangerous tags.');
$items = [];
foreach ($findings as $entity_type_id => $entities) {
foreach ($entities as $entity_id => $fields) {
$entity = $this
->entityTypeManager()
->getStorage($entity_type_id)
->load($entity_id);
foreach ($fields as $field => $finding) {
$items[] = $this
->t('@vulnerabilities found in <em>@field</em> field of <a href=":url">@label</a>', [
'@vulnerabilities' => implode(' and ', $finding),
'@field' => $field,
'@label' => $entity
->label(),
':url' => $this
->getEntityLink($entity),
]);
}
}
}
return [
'#theme' => 'check_evaluation',
'#paragraphs' => $paragraphs,
'#items' => $items,
];
}
/**
* Attempt to get a good link for the given entity.
*
* Falls back on a string with entity type id and id if no good link can
* be found.
*
* @param \Drupal\Core\Entity\EntityBase $entity
* The entity.
*
* @return string
*/
protected function getEntityLink(EntityInterface $entity) {
try {
$url = $entity
->toUrl('edit-form');
} catch (UndefinedLinkTemplateException $e) {
$url = NULL;
}
if ($url === NULL) {
try {
$url = $entity
->toUrl();
} catch (UndefinedLinkTemplateException $e) {
$url = NULL;
}
}
return $url !== NULL ? $url
->toString() : $entity
->getEntityTypeId() . ':' . $entity
->id();
}
/**
* {@inheritdoc}
*/
public function evaluatePlain(CheckResult $result) {
$findings = $result
->findings();
if (empty($findings)) {
return '';
}
$output = '';
foreach ($findings as $entity_type_id => $entities) {
foreach ($entities as $entity_id => $fields) {
$entity = $this
->entityTypeManager()
->getStorage($entity_type_id)
->load($entity_id);
foreach ($fields as $field => $finding) {
$output .= "\t" . $this
->t('@vulnerabilities in @field of :link', [
'@vulnerabilities' => implode(' and ', $finding),
'@field' => $field,
':link' => $this
->getEntityLink($entity),
]) . "\n";
}
}
}
return $output;
}
/**
* {@inheritdoc}
*/
public function getMessage($result_const) {
switch ($result_const) {
case CheckResult::SUCCESS:
return $this
->t('Dangerous tags were not found in any submitted content (fields).');
case CheckResult::FAIL:
return $this
->t('Dangerous tags were found in submitted content (fields).');
default:
return $this
->t('Unexpected result.');
}
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
Check:: |
protected | property | The configuration storage for this check. | |
Check:: |
protected | property | The service container. | |
Check:: |
protected | property | Settings handler for this check. | |
Check:: |
protected | property | The State system. | |
Check:: |
protected | property | The check's prefix in the State system. | |
Check:: |
protected | function | Returns the Security Review Checklist service. | |
Check:: |
protected | function | Returns the Config factory. | |
Check:: |
protected | function | Returns the service container. | |
Check:: |
public | function | Creates a new CheckResult for this Check. | |
Check:: |
protected | function | Returns the current Drupal user. | |
Check:: |
protected | function | Returns the database connection. | |
Check:: |
public | function | Enables the check. Has no effect if the check was not skipped. | |
Check:: |
protected | function | Returns the entity type manager. | |
Check:: |
public | function | Returns the namespace of the check. | |
Check:: |
final public | function | Returns the identifier constructed using the namespace and title values. | |
Check:: |
public | function | Returns whether the check is skipped. Checks are not skipped by default. | |
Check:: |
protected | function | Returns the Drupal Kernel. | |
Check:: |
public | function | Returns the last stored result of the check. | |
Check:: |
public | function | Returns the timestamp the check was last run. | |
Check:: |
protected | function | Returns the module handler. | |
Check:: |
public | function | Same as run(), but used in CLI context such as Drush. | 2 |
Check:: |
protected | function | Returns the Security Review Security service. | |
Check:: |
protected | function | Returns the Security Review service. | |
Check:: |
public | function | Returns the check-specific settings' handler. | |
Check:: |
public | function | Marks the check as skipped. | |
Check:: |
public | function | Returns the user the check was skipped by. | |
Check:: |
public | function | Returns the timestamp the check was last skipped on. | |
Check:: |
public | function | Stores a result in the state system. | |
Check:: |
public | function | Returns whether the findings should be stored or reproduced when needed. | 2 |
Check:: |
public | function | Initializes the configuration storage and the settings handler. | 2 |
DependencySerializationTrait:: |
protected | property | An array of entity type IDs keyed by the property name of their storages. | |
DependencySerializationTrait:: |
protected | property | An array of service IDs keyed by property name used for serialization. | |
DependencySerializationTrait:: |
public | function | 1 | |
DependencySerializationTrait:: |
public | function | 2 | |
Field:: |
public | function |
Returns the evaluation page of a result. Overrides Check:: |
|
Field:: |
public | function |
Evaluates a CheckResult and returns a plaintext output. Overrides Check:: |
|
Field:: |
protected | function | Attempt to get a good link for the given entity. | |
Field:: |
public | function |
Returns the machine name of the check. Overrides Check:: |
|
Field:: |
public | function |
Converts a result integer to a human-readable result message. Overrides Check:: |
|
Field:: |
public | function |
Returns the namespace of the check. Overrides Check:: |
|
Field:: |
public | function |
Returns the human-readable title of the check. Overrides Check:: |
|
Field:: |
public | function |
Returns the check-specific help page. Overrides Check:: |
|
Field:: |
public | function |
The actual procedure of carrying out the check. Overrides Check:: |
|
StringTranslationTrait:: |
protected | property | The string translation service. | 1 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. |