Skip to content

Filesystem

CodeScan

Scan files in a directory for matching criteria.

Class: Drutiny\Audit\Filesystem\CodeScan
Extends: Drutiny\Audit
Package: drutiny/drutiny

Policies

These are the policies that use this class:

Name Title
Drupal:ThemeSecurity Drupal Theme Security & Performance
Acquia:SiteFactoryDefaultThemePath Drupal Theme Path References

Parameters

Name Type Description Default
directory string Absolute filepath to directory to scan '%root'
exclude array Absolute filepaths to directories omit from scanning { }
filetypes array file extensions to include in the scan { }
patterns array patterns to run over each matching file. { }
whitelist array Whitelist patterns which the 'patterns' parameter may yield false positives from { }

Tokens

Name Type Description Default
directory string Absolute filepath to directory to scan '%root'
exclude array Absolute filepaths to directories omit from scanning { }
filetypes array file extensions to include in the scan { }
patterns array patterns to run over each matching file. { }
whitelist array Whitelist patterns which the 'patterns' parameter may yield false positives from { }
results array An array of results matching the scan criteria. Each match is an assoc array with the following keys: filepath, line, code, basename. { }
Source
  public function audit(Sandbox $sandbox) {
    $directory = $sandbox->getParameter('directory', '%root');
    $stat = $sandbox->drush(['format' => 'json'])->status();

    $directory =  strtr($directory, $stat['%paths']);

    $command = ['find', $directory, '-type f'];

    $types = $sandbox->getParameter('filetypes', []);

    if (!empty($types)) {
      $conditions = [];
      foreach ($types as $type) {
        $conditions[] = '-iname "*.' . $type . '"';
      }
      $command[] = '\( ' . implode(' -or ', $conditions) . ' \)';
    }

    foreach ($sandbox->getParameter('exclude', []) as $filepath) {
      $filepath = strtr($filepath, $stat['%paths']);
      $command[] = "! -path '$filepath'";
    }

    $command[] = '| (xargs grep -nE';
    $command[] = '"' . implode('|', $sandbox->getParameter('patterns', [])) . '" || exit 0)';

    $whitelist = $sandbox->getParameter('whitelist', []);
    if (!empty($whitelist)) {
      $command[] = "| (grep -vE '" . implode('|', $whitelist) . "' || exit 0)";
    }


    $command = implode(' ', $command);
    $sandbox->logger()->info('[' . __CLASS__ . '] ' . $command);
    $output = $sandbox->exec($command);

    if (empty($output)) {
      return TRUE;
    }

    $matches = array_filter(explode(PHP_EOL, $output));
    $matches = array_map(function ($line) {
      list($filepath, $line_number, $code) = explode(':', $line, 3);
      return [
        'file' => $filepath,
        'line' => $line_number,
        'code' => trim($code),
        'basename' => basename($filepath)
      ];
    }, $matches);

    $results = [
      'found' => count($matches),
      'findings' => $matches,
      'filepaths' => array_values(array_unique(array_map(function ($match) use ($stat) {
        return str_replace($stat['%paths']['%root'], '', $match['file']);
      }, $matches)))
    ];

    $sandbox->setParameter('results', $results);

    return empty($matches);
  }

FsSize

Large files

Class: Drutiny\Audit\Filesystem\FsSize
Extends: Drutiny\Audit
Package: drutiny/drutiny

Policies

These are the policies that use this class:

Name Title
fs:DrupalThemeDirectory Drupal Theme Directory Size
Acquia:SiteFactory:DrupalThemeDirectory ACSF Drupal Theme Directory Size

Parameters

Name Type Description Default
max_size integer The maximum size in MegaBytes a directory should be. 20
path string The path of the directory to check for size. null

Tokens

Name Type Description Default
max_size integer The maximum size in MegaBytes a directory should be. 20
path string The path of the directory to check for size. null
Source
  public function audit(Sandbox $sandbox) {
    $path = $sandbox->getParameter('path', '%files');
    $stat = $sandbox->drush(['format' => 'json'])->status();

    $path = strtr($path, $stat['%paths']);

    $size = trim($sandbox->exec("du -d 0 -m $path | awk '{print $1}'"));

    $max_size = (int) $sandbox->getParameter('max_size', 20);

    // Set the size in MB for rendering
    $sandbox->setParameter('size', $size);
    // Set the actual path.
    $sandbox->setParameter('path', $path);

    return $size < $max_size;
  }

LargeFiles

Large files

Class: Drutiny\Audit\Filesystem\LargeFiles
Extends: Drutiny\Audit
Package: drutiny/drutiny

Policies

These are the policies that use this class:

Name Title
fs:largeFiles Large public files

Parameters

Name Type Description Default
max_size integer Report files larger than this value measured in megabytes. 20

Tokens

Name Type Description Default
max_size integer Report files larger than this value measured in megabytes. 20
issues array A list of files that reach the max file size. null
plural string This variable will contain an 's' if there is more than one issue found. ''
Source
  public function audit(Sandbox $sandbox) {
    $stat = $sandbox->drush(['format' => 'json'])->status();

    $root = $stat['root'];
    $files = $stat['files'];

    $max_size = (int) $sandbox->getParameter('max_size', 20);

    $command = "find @location -type f -size +@sizeM -printf '@print-format'";
    $command .= " | sort -nr";
    $command = strtr($command, [
      '@location' => "{$root}/{$files}/",
      '@size' => $max_size,
      '@print-format' => '%k\t%p\n',
    ]);

    $output = $sandbox->exec($command);

    if (empty($output)) {
      return TRUE;
    }

    // Output from find is a giant string with newlines to seperate the files.
    $rows = array_map(function ($line) {
      $parts = array_map('trim', explode("\t", $line));
      $size = number_format((float) $parts[0] / 1024, 2);
      $filename = trim($parts[1]);
      return "{$filename} [{$size} MB]";
    },
    array_filter(explode("\n", $output)));

    $sandbox->setParameter('issues', $rows);
    $sandbox->setParameter('plural', count($rows) > 1 ? 's' : '');

    return Audit::WARNING;
  }

SensitivePublicFiles

Sensitive public files

Class: Drutiny\Audit\Filesystem\SensitivePublicFiles
Extends: Drutiny\Audit
Package: drutiny/drutiny

Policies

These are the policies that use this class:

Name Title
fs:SensitivePublicFiles Sensitive public files

Parameters

Name Type Description Default
extensions string The sensitive file extensions to look for. null

Tokens

Name Type Description Default
extensions string The sensitive file extensions to look for. null
issues array A list of files that reach the max file size. null
plural string This variable will contain an 's' if there is more than one issue found. ''
Source
  public function audit(Sandbox $sandbox) {
    $stat = $sandbox->drush(['format' => 'json'])->status();

    $root = $stat['root'];
    $files = $stat['files'];

    $extensions = $sandbox->getParameter('extensions');
    $extensions = array_map('trim', explode(',', $extensions));

    // Output is in the format:
    //
    // 7048 ./iStock_000017426795Large-2.jpg
    // 6370 ./portrait-small-1.png
    //
    // Note, the size is in KB in the response, we convert to MB later on in
    // this check.

    $command = "cd @location ; find . -type f \( @name-lookups \) -printf '@print-format'";
    $command .= " | grep -v -E '/js/js_|/css/css_|/php/twig/|/php/html_purifier_serializer/' | sort -nr";
    $command = strtr($command, [
      '@location' => "{$root}/{$files}/",
      '@name-lookups' => "-name '*." . implode("' -o -name '*.", $extensions) . "'",
      '@print-format' => '%k\t%p\n',
    ]);

    $output = $sandbox->exec($command);

    if (empty($output)) {
      return Audit::SUCCESS;
    }

    // Output from find is a giant string with newlines to separate the files.
    $rows = array_map(function ($line) {
      $parts = array_map('trim', explode("\t", $line));
      $size = number_format((float) $parts[0] / 1024, 2);
      $filename = trim($parts[1]);
      return "{$filename} [{$size} MB]";
    },
    array_filter(explode("\n", $output)));

    $sandbox->setParameter('issues', $rows);
    $sandbox->setParameter('plural', count($rows) > 1 ? 's' : '');

    return Audit::FAIL;
  }