Skip to content

Security: dhtml/dhtmlsql

Security

SECURITY.md

SECURITY

Supported Versions

Version PHP requirement Status
2.x PHP ^8.4 ✅ Actively supported
1.x PHP >=5.1 ❌ End of life — no security fixes

Reporting a Vulnerability

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.

Security Model

SQL Injection

DHTMLSQL 2.x prevents SQL injection through two separate mechanisms:

  1. Values are bound via native mysqli prepared statements (bind_param). User-supplied values never touch the SQL text.
  2. 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.

Identifier Safety

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(*) or MAX(col).

SQL expressions are handled explicitly via Expression::increment() / Expression::decrement() — never by parsing magic strings from user-supplied column values.

Credential Handling

  • Connection credentials are accepted through ConnectionConfig.
  • The $password parameter 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.php file with hard-coded credentials from 1.x has been removed. Use environment variables.

Exception Safety

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.

Logging Safety

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.

Import/Export Risks

  • DatabaseImporter::import($path) opens arbitrary local files. Never pass user-supplied paths. Use importWithinDirectory() to restrict to a specific directory.
  • DatabaseExporter does 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 mysqldump for production backups.

XSS (Pagination)

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().

PHP Version

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.

There aren't any published security advisories