Skip to content

PHP Tutorial PHP Security

Production Security Checklist

Lesson 302 of 369 3 min read By Deepak Paswan Updated Oct 5, 2026

Use this list before you launch, and again every few months. Each item links to the lesson that explains it.

Server and PHP

  • [ ] A supported PHP version (see PHP Versions), with updates applied.
  • [ ] HTTPS everywhere, with HTTP redirected to it.
  • [ ] display_errors = Off, log_errors = On (Production Error Handling).
  • [ ] expose_php = Off; unused extensions disabled.
  • [ ] allow_url_include = Off (Include Security).
  • [ ] Only public/ is reachable. Code, config, logs and uploads are outside it.
  • [ ] Directory listing off; dotfiles, .git, backups and phpinfo() pages not served.

Code and dependencies

  • [ ] composer audit shows no known vulnerabilities; dependencies are current (Updating Packages).
  • [ ] No secrets in Git; credentials come from the environment (Sensitive Data).
  • [ ] declare(strict_types=1) and types on new code.

Input and output

  • [ ] Prepared statements for every database value; allow-lists for column names (SQL Injection).
  • [ ] Input validated by type, length, range and allowed values (Input Validation).
  • [ ] Output escaped for its context (Output Escaping, XSS).
  • [ ] No include of paths built from user input.
  • [ ] No eval(), no unserialize() on untrusted data, no shell commands with user input.

Authentication and sessions

Files

  • [ ] Uploads checked by real content type, size, random names, stored safely (Secure File Uploads).
  • [ ] The uploads folder cannot run PHP.

Headers

  • [ ] X-Content-Type-Options, Referrer-Policy, a CSP, HSTS, framing rules (Security Headers).

Database

  • [ ] A dedicated database user with least privilege, not root.
  • [ ] The database is not reachable from the internet.
  • [ ] Regular, tested backups, stored off the server.

Monitoring

  • [ ] Errors and security events are logged, without secrets (Error Logging).
  • [ ] Someone actually reads the logs, or alerts exist.
  • [ ] You know how to rotate a secret and restore a backup.

A tiny self-check script

index.php
PHP
<?php
function checkSettings(array $ini): array
{
    $problems = [];

    if (($ini["display_errors"] ?? "0") !== "0") {
        $problems[] = "display_errors should be off in production";
    }

    if (($ini["expose_php"] ?? "0") !== "0") {
        $problems[] = "expose_php should be off";
    }

    if (($ini["allow_url_include"] ?? "0") !== "0") {
        $problems[] = "allow_url_include should be off";
    }

    return $problems;
}

print_r(checkSettings(["display_errors" => "1", "expose_php" => "0", "allow_url_include" => "0"]));
Output
OUTPUT
Array
(
    [0] => display_errors should be off in production
)

In real code you would pass ini_get(...) values. It is a starting point for your own deployment checks.

Security is a habit

No checklist makes a site “secure” forever. New bugs, new attacks and new dependencies appear all the time. The habits that matter are: trust nothing from outside, escape on output, use the safe tool for each job, keep things updated, and log what happens.

info
Why this matters in WordPress and Laravel
Both ecosystems publish hardening guides that cover the same points: updates, least privilege, backups, HTTPS and limiting login attempts. The PHP rules in this chapter apply equally to your own plugins, themes and Laravel apps.