From 2708f44af49c9dafdf63c02eea46adc1a6285cac Mon Sep 17 00:00:00 2001 From: ThangToee Date: Fri, 15 May 2026 23:12:34 +0700 Subject: [PATCH] Harden public debug and Docker secret exposure --- .dockerignore | 7 +- .../unit/security/PublicDebugEndpointTest.php | 72 +++++++++++++++++++ info.php | 2 - 3 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 common/tests/unit/security/PublicDebugEndpointTest.php delete mode 100644 info.php diff --git a/.dockerignore b/.dockerignore index b227ce1ca..a95b07361 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,8 @@ vendor .idea -.circleci \ No newline at end of file +.circleci + +# Local secrets and debug endpoints must not be copied into images. +.env +.env.* +info.php diff --git a/common/tests/unit/security/PublicDebugEndpointTest.php b/common/tests/unit/security/PublicDebugEndpointTest.php new file mode 100644 index 000000000..ddc0ccfdd --- /dev/null +++ b/common/tests/unit/security/PublicDebugEndpointTest.php @@ -0,0 +1,72 @@ +collectPhpFiles($publicPaths) as $file) { + $source = file_get_contents($file); + + $this->assertDoesNotMatchRegularExpression( + '/\bphpinfo\s*\(/i', + $source, + $file . ' must not expose phpinfo output from a public document root.' + ); + } + } + + public function testDockerBuildContextExcludesLocalSecrets() + { + $root = dirname(__DIR__, 4); + $entries = array_map('trim', file($root . '/.dockerignore', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES)); + $entries = array_values(array_filter($entries, static function ($entry) { + return $entry !== '' && strpos($entry, '#') !== 0; + })); + + $this->assertContains('.env', $entries); + $this->assertContains('.env.*', $entries); + $this->assertContains('info.php', $entries); + } + + private function collectPhpFiles(array $paths): array + { + $files = []; + + foreach ($paths as $path) { + if (is_file($path)) { + $files[] = $path; + continue; + } + + if (!is_dir($path)) { + continue; + } + + $iterator = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($path, \FilesystemIterator::SKIP_DOTS) + ); + + foreach ($iterator as $file) { + if ($file->isFile() && strtolower($file->getExtension()) === 'php') { + $files[] = $file->getPathname(); + } + } + } + + return $files; + } +} diff --git a/info.php b/info.php deleted file mode 100644 index f6cefd0e7..000000000 --- a/info.php +++ /dev/null @@ -1,2 +0,0 @@ -