Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.phpunit.cache
/vendor
/vendor
.idea
65 changes: 33 additions & 32 deletions src/Services/Audits/DebugModeAuditService.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,18 @@ public function run(): bool

// Only check for development packages if we're actually running in production
if ($this->isActuallyProduction()) {
// Check for development packages in composer.json
$composerJson = $this->getComposerJson();
if ($composerJson) {
$installedPackages = array_merge(
array_keys($composerJson['require'] ?? []),
array_keys($composerJson['require-dev'] ?? [])
);

foreach ($this->devPackages as $devPackage) {
if (in_array($devPackage, $installedPackages)) {
$this->addFinding([
'package' => $devPackage,
'title' => 'Development package detected in production',
'severity' => 'high',
'cve' => null,
'affected_versions' => null
]);
}
// Check for development packages in vendor/composer/installed.json
$installedPackagesNames = $this->getInstalledPackagesNames();

foreach ($this->devPackages as $devPackage) {
if (in_array($devPackage, $installedPackagesNames)) {
$this->addFinding([
'package' => $devPackage,
'title' => 'Development package detected in production',
'severity' => 'high',
'cve' => null,
'affected_versions' => null
]);
}
}

Expand Down Expand Up @@ -90,24 +84,31 @@ public function run(): bool
return true;
}

/**
* @return array<string, mixed>|null
*/
private function getComposerJson(): ?array
private function getInstalledPackagesNames(): array
{
$installedPackages = $this->getInstalledPackages();

return isset($installedPackages['packages'])
? array_column($installedPackages['packages'], 'name')
: [];
}

private function getInstalledPackages(): array
{
$composerPath = base_path('composer.json');
if (!file_exists($composerPath)) {
return null;
$installedPath = base_path('vendor/composer/installed.json');

if (!file_exists($installedPath)) {
return [];
}

$composerJsonContent = file_get_contents($composerPath);
return json_decode($composerJsonContent, true);
$installedContents = file_get_contents($installedPath);
return json_decode($installedContents, true);
}

private function hasExposedTestingRoutes(): bool
{
$routeCollection = \Route::getRoutes();

// Check debugbar routes separately as they're allowed when APP_DEBUG is true
foreach ($routeCollection as $route) {
$uri = $route->uri();
Expand All @@ -119,14 +120,14 @@ private function hasExposedTestingRoutes(): bool

continue;
}

// Check other testing routes that should never be exposed in production
$testingRoutes = [
'telescope',
'horizon',
'_dusk',
];

foreach ($testingRoutes as $testingRoute) {
if (str_starts_with($uri, $testingRoute)) {
return true;
Expand All @@ -151,15 +152,15 @@ private function hasProtectiveMiddleware($route): bool
'role:',
'Barryvdh\Debugbar\Middleware\DebugbarEnabled'
];

foreach ($middleware as $m) {
foreach ($protectiveMiddleware as $protect) {
if (str_starts_with($m, $protect)) {
return true;
}
}
}

return false;
}

Expand Down