SecurityCommand.php 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. <?php
  2. /**
  3. * @package Grav\Console\Cli
  4. *
  5. * @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
  6. * @license MIT License; see LICENSE file for details.
  7. */
  8. namespace Grav\Console\Cli;
  9. use Grav\Common\Grav;
  10. use Grav\Common\Security;
  11. use Grav\Console\ConsoleCommand;
  12. use Symfony\Component\Console\Helper\ProgressBar;
  13. use Symfony\Component\Console\Style\SymfonyStyle;
  14. class SecurityCommand extends ConsoleCommand
  15. {
  16. /** @var ProgressBar $progress */
  17. protected $progress;
  18. protected $source;
  19. protected function configure()
  20. {
  21. $this
  22. ->setName('security')
  23. ->setDescription('Capable of running various Security checks')
  24. ->setHelp('The <info>security</info> runs various security checks on your Grav site');
  25. $this->source = getcwd();
  26. }
  27. protected function serve()
  28. {
  29. /** @var Grav $grav */
  30. $grav = Grav::instance();
  31. $grav->setup();
  32. $grav['uri']->init();
  33. $grav['config']->init();
  34. $grav['debugger']->enabled(false);
  35. $grav['plugins']->init();
  36. $grav['themes']->init();
  37. $grav['twig']->init();
  38. $grav['pages']->init();
  39. $this->progress = new ProgressBar($this->output, \count($grav['pages']->routes()) - 1);
  40. $this->progress->setFormat('Scanning <cyan>%current%</cyan> pages [<green>%bar%</green>] <white>%percent:3s%%</white> %elapsed:6s%');
  41. $this->progress->setBarWidth(100);
  42. $io = new SymfonyStyle($this->input, $this->output);
  43. $io->title('Grav Security Check');
  44. $output = Security::detectXssFromPages($grav['pages'], false, [$this, 'outputProgress']);
  45. $io->newline(2);
  46. if (!empty($output)) {
  47. $counter = 1;
  48. foreach ($output as $route => $results) {
  49. $results_parts = array_map(function($value, $key) {
  50. return $key.': \''.$value . '\'';
  51. }, array_values($results), array_keys($results));
  52. $io->writeln($counter++ .' - <cyan>' . $route . '</cyan> → <red>' . implode(', ', $results_parts) . '</red>');
  53. }
  54. $io->error('Security Scan complete: ' . \count($output) . ' potential XSS issues found...');
  55. } else {
  56. $io->success('Security Scan complete: No issues found...');
  57. }
  58. $io->newline(1);
  59. }
  60. /**
  61. * @param array $args
  62. */
  63. public function outputProgress($args)
  64. {
  65. switch ($args['type']) {
  66. case 'count':
  67. $steps = $args['steps'];
  68. $freq = (int)($steps > 100 ? round($steps / 100) : $steps);
  69. $this->progress->setMaxSteps($steps);
  70. $this->progress->setRedrawFrequency($freq);
  71. break;
  72. case 'progress':
  73. if (isset($args['complete']) && $args['complete']) {
  74. $this->progress->finish();
  75. } else {
  76. $this->progress->advance();
  77. }
  78. break;
  79. }
  80. }
  81. }