diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index fc5b484c..f6ae2fba 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -3,7 +3,7 @@ FROM php:8.1.13-cli RUN apt-get update && apt-get install -y vim git sudo wget RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \ - && php -r "if (hash_file('sha384', 'composer-setup.php') === '55ce33d7678c5a611085589f1f3ddf8b3c52d662cd01d4ba75c0ee0459970c2200a51f492d557530c71c15d8dba01eae') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" \ + && php -r "if (hash_file('sha384', 'composer-setup.php') === 'dac665fdc30fdd8ec78b38b9800061b4150413ff2e3b6f88543c636f7cd84f6db9189d43a81e5503cda447da73c7e5b6') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" \ && php composer-setup.php \ && php -r "unlink('composer-setup.php');" \ && sudo mv composer.phar /usr/local/bin/composer \ diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..0d625a2f --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +# All files are checked into the repo with LF +* text=auto + +# These files are checked out using LF locally +*.* eol=lf \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6616943a..f1eb936c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -14,6 +14,7 @@ jobs: - "8.0" - "8.1" - "8.2" + - "8.3" steps: - name: "Checkout" uses: "actions/checkout@v2" diff --git a/build.sh b/build.sh index d3a15ed5..d4c84f61 100755 --- a/build.sh +++ b/build.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/bash # Check if phar-composer.phar is in the $PATH if ! [ -x "$(command -v phar-composer.phar)" ]; then diff --git a/package/src/progpilot/Analysis/SecurityAnalysis.php b/package/src/progpilot/Analysis/SecurityAnalysis.php index 3642995e..aee4a909 100644 --- a/package/src/progpilot/Analysis/SecurityAnalysis.php +++ b/package/src/progpilot/Analysis/SecurityAnalysis.php @@ -92,12 +92,12 @@ public static function taintedStateFlow($context, $mySink, $indexParameter, $tai $oneTainted["flow_name"] = $ret["source_name"]; $oneTainted["flow_line"] = $ret["source_line"]; $oneTainted["flow_column"] = $ret["source_column"]; - $oneTainted["flow_file"] =$ret["source_file"]; + $oneTainted["flow_file"] = $ret["source_file"]; $resultTaintedFlow[] = $oneTainted; $idFlow .= \progpilot\Utils::printDefinition($fromTaintedDef); - $idFlow .= "-".$fromTaintedDef->getSourceMyFile()->getName(); + $idFlow .= "-".$fromTaintedDef->getSourceMyFile()->fileName; $taintedDef = $fromTaintedDef; $taintedState = $fromTaintedState; break 2; diff --git a/package/src/progpilot/Analyzer.php b/package/src/progpilot/Analyzer.php index 6ce70fc0..bee1a955 100644 --- a/package/src/progpilot/Analyzer.php +++ b/package/src/progpilot/Analyzer.php @@ -347,7 +347,7 @@ public function run($context, $cmdFiles = null) $context->readConfiguration(); // try to resolve incorrect included/excluded file paths - $context->inputs->resolvePaths(); + $context->inputs->resolvePathsIncludedAndExcludedFiles(); // add all configurations inside frameworks folders except if overwritten $context->inputs->readFrameworks(); @@ -360,17 +360,15 @@ public function run($context, $cmdFiles = null) $context->inputs->readDefaultCustomRules(); if ($cmdFiles !== null) { + $cmdFiles = \progpilot\Inputs\MyInputsInternalApi::resolvePaths($cmdFiles); foreach ($cmdFiles as $cmdFile) { if (is_dir($cmdFile)) { $this->getFilesOfDir($context, $cmdFile, $cmdFile, $files); } else { - $realpath = realpath($cmdFile); - if($realpath) { - $cmdFileA = new FileAnalysis($realpath, dirname($realpath)); - if (!in_array($cmdFileA, $files, true) - && !$context->inputs->isExcludedFile($realpath)) { - $files[] = $cmdFileA; - } + $cmdFileA = new FileAnalysis($cmdFile, dirname($cmdFile)); + if (!in_array($cmdFileA, $files, true) + && !$context->inputs->isExcludedFile($cmdFile)) { + $files[] = $cmdFileA; } } } @@ -382,28 +380,24 @@ public function run($context, $cmdFiles = null) if (is_dir($includedFile)) { $this->getFilesOfDir($context, $includedFile, $includedFile, $files); } else { - $realpath = realpath($includedFile); - if($realpath) { - $cmdFileA = new FileAnalysis($realpath, dirname($realpath)); - if (!in_array($cmdFileA, $files, true) - && !$context->inputs->isExcludedFile($realpath)) { - $files[] = $cmdFileA; - } + $cmdFileA = new FileAnalysis($includedFile, dirname($includedFile)); + if (!in_array($cmdFileA, $files, true) + && !$context->inputs->isExcludedFile($includedFile)) { + $files[] = $cmdFileA; } } } if (!is_null($context->inputs->getFolder())) { - $this->getFilesOfDir($context, $context->inputs->getFolder(), $context->inputs->getFolder(), $files); + $folder = \progpilot\Inputs\MyInputsInternalApi::resolvePath($context->inputs->getFolder()); + $this->getFilesOfDir($context, $folder, $folder, $files); } else { if ($context->inputs->getFile() !== null) { - $realpath = realpath($context->inputs->getFile()); - if($realpath) { - $cmdFileA = new FileAnalysis($realpath, dirname($realpath)); - if (!in_array($cmdFileA, $files, true) - && !$context->inputs->isExcludedFile($realpath)) { - $files[] = $cmdFileA; - } + $file = \progpilot\Inputs\MyInputsInternalApi::resolvePath($context->inputs->getFile()); + $cmdFileA = new FileAnalysis($file, dirname($file)); + if (!in_array($cmdFileA, $files, true) + && !$context->inputs->isExcludedFile($file)) { + $files[] = $cmdFileA; } } } diff --git a/package/src/progpilot/Console/Application.php b/package/src/progpilot/Console/Application.php index d4574220..abc38c19 100644 --- a/package/src/progpilot/Console/Application.php +++ b/package/src/progpilot/Console/Application.php @@ -17,7 +17,7 @@ class Application extends BaseApplication { const NAME = 'progpilot'; - const VERSION = '1.0.2'; + const VERSION = '1.1.0'; public function __construct() { diff --git a/package/src/progpilot/Inputs/MyInputsInternalApi.php b/package/src/progpilot/Inputs/MyInputsInternalApi.php index 347688dd..31236c12 100644 --- a/package/src/progpilot/Inputs/MyInputsInternalApi.php +++ b/package/src/progpilot/Inputs/MyInputsInternalApi.php @@ -70,50 +70,50 @@ public function __construct() $this->falsePositives= null; } - public function resolvePaths() + public static function resolvePath($file) { - $tmpFiles = $this->excludesFilesAnalysis; - $this->excludesFilesAnalysis = []; + if (strpos($file, "/") !== false + || strpos($file, "\\") !== false) { + // there is a slash, the dev likely wants a path + if (str_starts_with("./", $file) === 0 + && str_starts_with(".\\", $file) === 0 + && str_starts_with("/", $file) === 0 + && preg_match("/^[a-bA-B]*:/", $file) === 0) { + // it's not a relative or absolute path + $file = ".".DIRECTORY_SEPARATOR.$file; + } - foreach ($tmpFiles as $excludedFile) { - if (strpos($excludedFile, "/") !== false - || strpos($excludedFile, "\\") !== false) { - // there is a slash, the dev likely wants a path - if (str_starts_with("./", $excludedFile) === 0 - && str_starts_with(".\\", $excludedFile) === 0 - && str_starts_with("/", $excludedFile) === 0 - && preg_match("/^[a-bA-B]*:/", $excludedFile) === 0) { - // it's not a relative or absolute path - $excludedFile = ".".DIRECTORY_SEPARATOR.$excludedFile; - } + $file = realpath($file); + } - $excludedFile = realpath($excludedFile); - } + return $file; + } + public static function resolvePaths($files) + { + $resolvePaths = []; + foreach ($files as $file) { + $resolvePaths[] = MyInputsInternalApi::resolvePath($file); + } + + return $resolvePaths; + } + + public function resolvePathsIncludedAndExcludedFiles() + { + $tmpFiles = MyInputsInternalApi::resolvePaths($this->excludesFilesAnalysis); + $this->excludesFilesAnalysis = []; + + foreach ($tmpFiles as $excludedFile) { if (!in_array($excludedFile, $this->excludesFilesAnalysis, true)) { $this->excludesFilesAnalysis[] = $excludedFile; } } - - $tmpFiles = $this->includesFilesAnalysis; + $tmpFiles = MyInputsInternalApi::resolvePaths($this->includesFilesAnalysis); $this->includesFilesAnalysis = []; foreach ($tmpFiles as $includedFile) { - if (strpos($includedFile, "/") !== false - || strpos($includedFile, "\\") !== false) { - // there is a slash, the dev likely wants a path - if (str_starts_with("./", $includedFile) === 0 - && str_starts_with(".\\", $includedFile) === 0 - && str_starts_with("/", $includedFile) === 0 - && preg_match("/^[a-bA-B]*:/", $includedFile) === 0) { - // it's not a relative or absolute path - $includedFile = ".".DIRECTORY_SEPARATOR.$includedFile; - } - - $includedFile = realpath($includedFile); - } - if (!in_array($includedFile, $this->includesFilesAnalysis, true)) { $this->includesFilesAnalysis[] = $includedFile; } diff --git a/projects/example/composer.json b/projects/example/composer.json index 88281f31..da9b7506 100644 --- a/projects/example/composer.json +++ b/projects/example/composer.json @@ -3,7 +3,7 @@ "description": "Example of use of Progpilot", "require": { "php": ">=7.4", - "designsecurity/progpilot": "^1.0.2", + "designsecurity/progpilot": "^1.1.0", "ircmaxell/php-cfg": "^0.7.0" } } diff --git a/projects/example_config/composer.json b/projects/example_config/composer.json index 542967f2..e04b5290 100644 --- a/projects/example_config/composer.json +++ b/projects/example_config/composer.json @@ -9,7 +9,7 @@ ], "require": { "php": ">=7.4", - "progpilot/package": "^1.0.2", + "progpilot/package": "^1.1.0", "ircmaxell/php-cfg": "^0.7.0" } } diff --git a/projects/tests/tests/real/composer/composer.json b/projects/tests/tests/real/composer/composer.json index a99b162c..536d2e1d 100644 --- a/projects/tests/tests/real/composer/composer.json +++ b/projects/tests/tests/real/composer/composer.json @@ -1,5 +1,5 @@ { - "name": "test vuln composer package", + "name": "test/vuln", "description": "test vuln composer package", "repositories": [ {