| Version | PHP requirement | Status |
|---|---|---|
| 2.x | PHP ^8.4 | ✅ Actively supported |
| 1.x | PHP >=5.1 | ❌ End of life — no security fixes |
Do not open a public GitHub issue for security vulnerabilities.
Email the maintainer directly (see author contact in composer.json) with:
- A description of the vulnerability.
- Steps to reproduce.
- Your assessment of severity.
- Whether you have a proposed fix.
You will receive an acknowledgement within 72 hours. Responsible disclosure is appreciated.
DHTMLSQL 2.x prevents SQL injection through two separate mechanisms:
- Values are bound via native
mysqliprepared statements (bind_param). User-supplied values never touch the SQL text. - Identifiers (table names, column names) are validated against a strict pattern (
/^[a-zA-Z_][a-zA-Z0-9_]*$/) and wrapped in backtick quotes. They are never passed as bound parameters.
The library does not rely on string escaping as a primary defense. The legacy 1.x approach of manually escaping and interpolating values has been replaced entirely.
The Identifier class rejects:
- Empty strings.
- Null bytes (
\0). - Identifiers starting with a digit.
- Identifiers containing hyphens, spaces, semicolons, or SQL comment sequences.
- Expressions such as
COUNT(*)orMAX(col).
SQL expressions are handled explicitly via Expression::increment() / Expression::decrement() — never by parsing magic strings from user-supplied column values.
- Connection credentials are accepted through
ConnectionConfig. - The
$passwordparameter is annotated with#[\SensitiveParameter](PHP 8.2+), which instructs PHP, Xdebug, and error reporters to redact it from stack traces. - Passwords are never included in exception messages or log output.
- The
config.default.phpfile with hard-coded credentials from 1.x has been removed. Use environment variables.
QueryException includes:
- The MySQL error code and SQL state (safe to log).
- The SQL template (with
?placeholders, never interpolated values). - The previous native exception (chained).
QueryException does not include bound parameter values.
If you use session_logging, the library logs the SQL template — not the bound values. Do not log personal data, tokens, or secrets in custom loggers you attach.
DatabaseImporter::import($path)opens arbitrary local files. Never pass user-supplied paths. UseimportWithinDirectory()to restrict to a specific directory.DatabaseExporterdoes not emit HTTP headers. The application layer controls HTTP responses.- Export output is not guaranteed to be safe for re-import in all edge cases (stored procedures, triggers, LOAD DATA INFILE). Use
mysqldumpfor production backups.
In 1.x, show_navigation() reflected $_SERVER['PHP_SELF'] into HTML without encoding — an XSS vulnerability. In 2.x, the Paginator returns a value object; the application renders HTML. The legacy facade's show_navigation() now encodes server values with htmlspecialchars().
1.x runs on PHP 5.1+, which reached end-of-life in January 2019. 2.x requires PHP 8.4+. Running any web application on an unsupported PHP version is a security risk independent of this library.