22 private static $phpUnsecureFunctions = [];
29 private static $jsUnsecureFunctions = [];
36 private $fileExtensions =
'/\.(php|phtml|js)$/';
45 self::loadData(self::$phpUnsecureFunctions,
'unsecure_php_functions*.php');
46 self::loadData(self::$jsUnsecureFunctions,
'unsecure_js_functions*.php');
56 private static function loadData(array &
$data, $filePattern)
58 foreach (glob(
__DIR__ .
'/_files/security/' . $filePattern) as $file) {
59 $data = array_merge_recursive(
$data, self::readList($file));
63 $excludes =
$value[
'exclude'];
65 foreach ($excludes as $exclude) {
66 if (
'setup' == $exclude[
'type']) {
67 $excludePaths[] =
BP .
'/setup/' . $exclude[
'path'];
70 .
'/' . $exclude[
'path'];
73 $data[$key][
'exclude'] = $excludePaths;
83 private static function readList($file)
95 $invoker = new \Magento\Framework\App\Utility\AggregateInvoker($this);
98 function ($fileFullPath) use ($functionDetector) {
99 $functions = $this->getFunctions($fileFullPath);
100 $lines = $functionDetector->detect($fileFullPath, array_keys($functions));
103 if (!empty($lines)) {
104 $message = $this->composeMessage($fileFullPath, $lines, $functions);
111 $this->getFilesToVerify()
123 private function composeMessage($fileFullPath, $lines, $functionRules)
126 foreach ($lines as $lineNumber => $detectedFunctions) {
127 $detectedFunctionRules = array_intersect_key($functionRules, array_flip($detectedFunctions));
128 $replacementString =
'';
129 foreach ($detectedFunctionRules as $function => $functionRule) {
134 "[\n\t\t\t" . implode(
"\n\t\t\t",
$replacement) .
"\n\t\t]" :
138 $replacementString .=
"\t\t'$function' => '$replacement'\n";
141 "Functions '%s' are not secure in %s. \n\tSuggested replacement:\n%s",
142 implode(
', ', $detectedFunctions),
143 $fileFullPath .
':' . $lineNumber,
155 private function getFilesToVerify()
157 $fileExtensions = $this->fileExtensions;
158 $directoriesToScan =
Files::init()->readLists(
__DIR__ .
'/_files/security/whitelist.txt');
161 foreach (glob(
__DIR__ .
'/../_files/changed_files*') as $listFile) {
162 $filesToVerify = array_merge(
164 file($listFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES)
170 $file = [
BP .
'/' . $file];
173 $filesToVerify = array_filter(
175 function (
$path) use ($directoriesToScan, $fileExtensions) {
176 if (!file_exists(
$path[0])) {
180 foreach ($directoriesToScan as $directory) {
181 $directory = realpath($directory);
182 if (strpos(
$path, $directory) === 0) {
183 if (preg_match($fileExtensions,
$path)) {
185 if (preg_match(
'#' . preg_quote(
'Test/Unit',
'#') .
'#',
$path)) {
195 return $filesToVerify;
204 private function getFunctions($fileFullPath)
206 $fileExtension = pathinfo($fileFullPath, PATHINFO_EXTENSION);
208 if ($fileExtension ==
'php') {
209 $functions = self::$phpUnsecureFunctions;
210 }
elseif ($fileExtension ==
'js') {
211 $functions = self::$jsUnsecureFunctions;
212 }
elseif ($fileExtension ==
'phtml') {
213 $functions = array_merge_recursive(self::$phpUnsecureFunctions, self::$jsUnsecureFunctions);
215 foreach ($functions as $function => $functionRules) {
216 if (in_array($fileFullPath, $functionRules[
'exclude'])) {
217 unset($functions[$function]);
elseif(isset( $params[ 'redirect_parent']))
defined('TESTS_BP')||define('TESTS_BP' __DIR__
static setUpBeforeClass()
testUnsecureFunctionsUsage()