The two generated ini drop-ins interpolated $user/$domain into an unquoted
heredoc. Measured against the pre-fix script in a real cac-lsphp:php83 container
with domain=$'evil.com\nprecision = 7\n; ':
99-cac-path-parity.ini contained the injected line and lsphp reported
`precision => 7 => 7` — an arbitrary ini directive supplied through the domain
env var and applied to every request. The `from` value was silently truncated
at the newline too, so the site also got a wrong (but "active") mapping.
Both values are panel-validated and both already feed `ln -sfn` and the
shared-ols vhost config, so this is defense-in-depth rather than a live hole. It
is worth closing anyway because the OTHER two hostile inputs the reviewer
measured — `$(...)` (ini parse error) and `"` (empty value) — leave the parity
extension INERT, which is precisely the silent failure this whole change set
exists to eliminate.
Two layers, neither of which can fatal a request:
- values are emitted double-quoted via printf instead of heredoc
interpolation. php.ini double-quoted values may span newlines, so a newline
is data, not a new directive.
- $user/$SAFE_DOMAIN are checked against [A-Za-z0-9._-]+ first, because
quoting does NOT stop php.ini's own ${VAR} interpolation. A rejected value
logs a WARNING, writes no mapping at all (not even the degraded
auto_prepend fallback, which would not be right for such a site either) and
reports `path parity = none (user/domain rejected)` on the startup line.
After: same container, same hostile domain — no 99-cac-path-parity.ini is
written, `precision => 14` (default), and the warning names the rejected values.
Happy path re-verified for domain=site.com and domain=*.site.com: mapping
written, `Rewriting => active`, from/to parse back byte-identical.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>