Make cron CLI-only and deny non-entry PHP in DDEV nginx (#4348)

* Make cron CLI-only and deny non-entry PHP in DDEV nginx

* Assert terminating action in cron guard test
This commit is contained in:
Adam Daley authored and GitHub committed 2026-09-17 21:17:09 +01:00
1 parent 1751c29105
commit ac97cf2796
3 files changed
+67

No files matched your search

+47
View File
@@ -3,6 +3,53 @@ location = /config.php {
deny all;
}
# Deny PHP scripts that are not web entry points (index.php, ipn.php, installer).
# Exact matches take precedence over the PHP handler regardless of include order.
location = /cron.php {
deny all;
}
location = /console.php {
deny all;
}
location = /load.php {
deny all;
}
location = /di.php {
deny all;
}
location = /config-sample.php {
deny all;
}
location = /config.old.php {
deny all;
}
location = /install/session.php {
deny all;
}
# Deny code directories. Prefix matches skip the PHP handler.
location ^~ /library/ {
deny all;
}
location ^~ /modules/ {
deny all;
}
location ^~ /locale/ {
deny all;
}
location ^~ /install/sql/ {
deny all;
}
location ^~ /vendor/ {
deny all;
}
+4
View File
@@ -8,6 +8,10 @@ declare(strict_types=1);
* @copyright FOSSBilling (https://www.fossbilling.org)
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache-2.0
*/
if (php_sapi_name() !== 'cli') {
exit('This script can only be run from the command line.');
}
require_once __DIR__ . DIRECTORY_SEPARATOR . 'load.php';
use FOSSBilling\Environment;
@@ -12,3 +12,19 @@ test('theme configuration directories are protected at any nesting depth', funct
expect($configuration)->not->toBeFalse()
->and($configuration)->toContain('RewriteCond %{REQUEST_URI} ^/themes/(?:[^/]+/)+config/ [NC]');
});
test('cron entry point refuses non-CLI execution before bootstrapping', function (): void {
$cron = file_get_contents(Path::join(__DIR__, '..', '..', 'src/cron.php'));
expect($cron)->not->toBeFalse()
->and($cron)->toMatch(
"/if\s*\(\s*php_sapi_name\(\)\s*!==\s*'cli'\s*\)\s*\{\s*exit\s*\(/s"
);
$guardPosition = strpos((string) $cron, 'php_sapi_name()');
$bootstrapPosition = strpos((string) $cron, 'require_once __DIR__');
expect($guardPosition)->not->toBeFalse()
->and($bootstrapPosition)->not->toBeFalse()
->and($guardPosition)->toBeLessThan($bootstrapPosition);
});