diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/UnsecureFunctionsUsageTest.php b/dev/tests/static/testsuite/Magento/Test/Legacy/UnsecureFunctionsUsageTest.php new file mode 100644 index 0000000000000000000000000000000000000000..6b18eb2b71478463e39e815dec078478c4034a07 --- /dev/null +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/UnsecureFunctionsUsageTest.php @@ -0,0 +1,167 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Test\Legacy; + +use Magento\Framework\App\Utility\Files; + +/** + * Tests to detect unsecure functions usage + */ +class UnsecureFunctionsUsageTest extends \PHPUnit_Framework_TestCase +{ + /** + * File extensions pattern to search for + * + * @var string + */ + private $fileExtensions = '/\.(php|phtml|js)$/'; + + /** + * Php unsecure functions to detect + * + * @var array + */ + private $phpUnsecureFunctions = [ + 'unserialize', + 'serialize', + 'eval', + 'md5', + 'srand', + 'mt_srand' + ]; + + /** + * JS unsecure functions to detect + * + * @var array + */ + private $jsUnsecureFunctions = []; + + /** + * Detect unsecure functions usage for changed files in whitelist with the exception of blacklist + * + * @return void + */ + public function testUnsecureFunctionsUsage() + { + $invoker = new \Magento\Framework\App\Utility\AggregateInvoker($this); + $invoker( + function ($fileName) { + $result = ''; + $errorMessage = 'The following functions are non secure and should be avoided: ' + . implode(', ', $this->phpUnsecureFunctions) + . ' for PHP'; + if (!empty($this->jsUnsecureFunctions)) { + $errorMessage .= ', and ' + . implode(', ', $this->jsUnsecureFunctions) + . ' for JavaScript'; + } + $errorMessage .= ".\n"; + $regexp = $this->getRegexpByFileExtension(pathinfo($fileName, PATHINFO_EXTENSION)); + if ($regexp) { + $matches = preg_grep( + $regexp, + file($fileName, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) + ); + if (!empty($matches)) { + foreach (array_keys($matches) as $line) { + $result .= $fileName . ':' . ($line + 1) . "\n"; + } + } + $this->assertEmpty($result, $errorMessage . $result); + } + }, + $this->unsecureFunctionsUsageDataProvider() + ); + } + + /** + * Data provider for test + * + * @return array + */ + public function unsecureFunctionsUsageDataProvider() + { + $fileExtensions = $this->fileExtensions; + $directoriesToScan = Files::init()->readLists(__DIR__ . '/_files/security/whitelist.txt'); + $blackListFiles = include __DIR__ . '/_files/security/blacklist.php'; + + $filesToVerify = []; + foreach (glob(__DIR__ . '/../_files/changed_files*') as $listFile) { + $filesToVerify = array_merge( + $filesToVerify, + file($listFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) + ); + } + array_walk( + $filesToVerify, + function (&$file) { + $file = [BP . '/' . $file]; + } + ); + $filesToVerify = array_filter( + $filesToVerify, + function ($path) use ($directoriesToScan, $fileExtensions, $blackListFiles) { + if (!file_exists($path[0])) { + return false; + } + $path = realpath($path[0]); + foreach ($directoriesToScan as $directory) { + $directory = realpath($directory); + if (strpos($path, $directory) === 0) { + if (preg_match($fileExtensions, $path)) { + foreach ($blackListFiles as $blackListFile) { + if (preg_match($blackListFile, $path)) { + return false; + } + } + return true; + } + } + } + return false; + } + ); + return $filesToVerify; + } + + /** + * Get regular expression by file extension + * + * @param string $fileExtension + * @return string|bool + */ + private function getRegexpByFileExtension($fileExtension) + { + $regexp = false; + if ($fileExtension == 'php') { + $regexp = $this->prepareRegexp($this->phpUnsecureFunctions); + } elseif ($fileExtension == 'js') { + $regexp = $this->prepareRegexp($this->jsUnsecureFunctions); + } elseif ($fileExtension == 'phtml') { + $regexp = $this->prepareRegexp($this->phpUnsecureFunctions + $this->jsUnsecureFunctions); + } + return $regexp; + } + + /** + * Prepare regular expression for unsecure function names + * + * @param array $functions + * @return string + */ + private function prepareRegexp(array $functions) + { + if (empty($functions)) { + return ''; + } + $regexArray = []; + foreach ($functions as $function) { + $regexArray[] = '\b' . $function . '\b\('; + } + return '/' . implode('|', $regexArray) . '/i'; + } +} diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/security/blacklist.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/security/blacklist.php new file mode 100644 index 0000000000000000000000000000000000000000..f055f0a732c664dd8ed109d7ec52b178c537a4d0 --- /dev/null +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/security/blacklist.php @@ -0,0 +1,8 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +return [ + '/Test\/Unit/' +]; diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/security/whitelist.txt b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/security/whitelist.txt new file mode 100644 index 0000000000000000000000000000000000000000..2567475de6a035b2a369ac342c076ce1e5cad07d --- /dev/null +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/security/whitelist.txt @@ -0,0 +1,4 @@ +module * / +library * / +setup +pub \ No newline at end of file