Find every insecure PHP setting without running PHP
php-ini-audit reads php.ini, conf.d, PHP-FPM pools, .user.ini and
.htaccess, rebuilds the effective configuration the way PHP does, and reports each matching
rule with its severity, confidence and the exact file and line it came from.
Quick start #
composer global require jorgsowa/php-ini-audit
php-ini-audit # discover and audit this host
php-ini-audit --root /mnt/rootfs # audit an extracted container image
php-ini-audit /etc/php/8.3/fpm/php.ini # audit one installation
What a report looks like #
Findings are grouped per effective configuration: a php.ini with its scan directory, and every overlay on top of it (FPM pools, .user.ini, [PATH=] sections).
== /etc/php/8.2/fpm/php.ini [sapi fpm, php 8.2]
files: /etc/php/8.2/fpm/php.ini, /etc/php/8.2/fpm/conf.d/20-xdebug.ini, …
CRITICAL EXEC-001 Remote file inclusion enabled (confidence high)
allow_url_include is enabled
at /etc/php/8.2/fpm/php.ini:22
fix: Set allow_url_include = Off.
HIGH SESS-002 Session IDs accepted outside cookies (confidence high)
session.use_only_cookies is Off
at /etc/php/8.2/fpm/php.ini:35
LOW ERR-004 PHP version disclosed in HTTP headers (confidence high)
expose_php is On
at built-in default
== /etc/php/8.2/fpm/php.ini + pool [www] (/etc/php/8.2/fpm/pool.d/www.conf)
CRITICAL FPM-001 FastCGI port reachable from the network (confidence medium)
listen = 0.0.0.0:9000 binds every interface without listen.allowed_clients
at /etc/php/8.2/fpm/pool.d/www.conf:4
Design principles #
Never executes anything
No php -i, no subprocesses, no eval, no network. A test fails the build if such a call is added.
Not a pass/fail verdict
Every matching rule is reported, each with its own severity and confidence. One rule can report several problems.
Defaults count
Unset directives are checked against PHP's built-in defaults, which is where Docker images without a php.ini go wrong.
Knows where values come from
Every finding points at the file and line that set the effective value, or says it is a default.
Understands overlays
FPM php_admin_value, .user.ini and .htaccess are layered with PHP's changeability rules, so ignored hardening is reported.
Known CVEs, in context
CVEs are matched to the exact PHP version and reported only when the configuration actually uses the vulnerable feature, such as php-cgi on Windows or allow_url_fopen. Every other publicly disclosed CVE for that version is listed in one warning.
Checks referenced paths
Session, upload, log, extension and CA paths are checked for world-writable permissions and for sitting inside the web root, using stat() only.
Coverage #
| Prefix | Category | Rules |
|---|---|---|
EXEC | Code execution | 17 |
FS | Filesystem and paths | 11 |
ERR | Information disclosure | 11 |
SESS | Session security | 14 |
RES | Resource limits and DoS | 11 |
CGI | CGI / FastCGI | 2 |
EXT | Debug and profiling extensions | 3 |
OPC | OPcache | 3 |
DB | Database and credentials | 3 |
ENC | Character encoding | 4 |
CFG | Configuration hygiene | 10 |
FPM | PHP-FPM pools | 8 |
HTA | Apache .htaccess | 1 |
VULN | PHP version support | 3 |
CVE | Known vulnerabilities | 29 |