Security#

Introduction#

DBLayer includes layered SQL safety checks for query text and bindings. Security is configured globally by mode and can be hardened or tuned per connection.

Security Mode#

Available modes:

  • SecurityMode::OFF

  • SecurityMode::NORMAL

  • SecurityMode::STRICT

use Infocyph\DBLayer\Security\Security;
use Infocyph\DBLayer\Security\SecurityMode;

Security::setMode(SecurityMode::STRICT);

Mode Semantics#

  • OFF: disables automatic SQL validation.

  • NORMAL: injection/binding validation with practical defaults.

  • STRICT: adds more aggressive pattern checks and tighter policies.

Policy Guardrails#

  • SecurityMode::OFF is blocked by default.

  • security.enabled = false is blocked unless you set security.allow_insecure = true.

  • Intentional global override for advanced local diagnostics:

use Infocyph\DBLayer\Security\Security;

Security::allowInsecureMode(true);

Validation Coverage#

  • SQL injection pattern checks

  • Query length checks

  • Parameter count and size checks

  • Additional dangerous-pattern scans in strict mode

The validator is defense-in-depth. You should still use parameterized queries and avoid concatenating untrusted input into SQL fragments.

Per-Connection Security Config#

'security' => [
    'enabled' => true,
    'max_sql_length' => 8000,
    'max_params' => 500,
    'max_param_bytes' => 4096,
    'queries_per_second' => 0,
    'queries_per_minute' => 0,
    'rate_limit_key' => null,
    'rate_limit_callback' => null,
    'strict_identifiers' => true,
    'require_tls' => null,
    'allow_insecure' => false,
    'raw_sql_policy' => 'allow',
    'raw_sql_allowlist' => [],
]

Transport / TLS Policy#

  • security.require_tls = true enforces TLS for MySQL/PostgreSQL.

  • security.require_tls = false requires security.allow_insecure = true.

  • DB::hardenProduction() sets require_tls = true for hardened defaults.

Driver requirements:

  • MySQL: provide secure transport via ssl_ca / ssl_cert / ssl_key or a secure sslmode.

  • PostgreSQL: set sslmode to require, verify-ca, or verify-full.

Raw SQL Fragment Policy#

Raw entry points (for example whereRaw(), selectRaw(), string fromSub(), and string CTE bodies) are controlled by:

  • raw_sql_policy = allow: default behavior.

  • raw_sql_policy = deny: block all raw fragments.

  • raw_sql_policy = allowlist: only allow fragments matching raw_sql_allowlist patterns.

Allowlist rules support plain substring rules and regex rules such as '/^id\\s*=\\s*\\?$/i'.

Facade-Level Defaults#

For consistent policy across many connections, you can apply global defaults through the facade:

use Infocyph\DBLayer\DB;

DB::setSecurityDefaults([
    'strict_identifiers' => true,
    'queries_per_second' => 250,
]);

// Convenience profile (enables strict identifiers and require_tls=true).
DB::hardenProduction();

These values are applied as enforced facade policy across registered and future connections.

Rate Limiting and Confirmation#

Security utilities also include rate-limit checks and dangerous-operation confirmation gates:

Security::checkRateLimit('tenant:42');
Security::requireConfirmation('drop table users', confirmed: true);

Error and Log Hygiene#

  • Query failure exceptions expose statement type and SQL fingerprint, not full SQL text.

  • Logger redacts binding values by default.

  • Logger can mirror structured entries to any PSR-3 backend via DB::setPsrLogger().

DB::enableLogger('/tmp/dblayer.log');
DB::logger()->setRedactBindings(true); // default
// DB::logger()->setRedactBindings(false); // opt out only for controlled local debugging

Warning

Security mode OFF disables automatic SQL validation. Use it only in controlled internal scenarios, never as a default in shared environments.