Lập trình · 22/09/2026

Laravel 13 Course – Lesson 23: Laravel 13 Production Security Checklist

Lesson 23 — Production Security Checklist: TaskFlow now has authentication, policies and CSRF tests. Deployment still requires runtime and infrastructure checks; a green test suite does not prove a server is secure.

Checklist bảo mật Laravel 13 trước khi lên production

Lesson 23 — Production Security Checklist: TaskFlow now has authentication, policies and CSRF tests. Deployment still requires runtime and infrastructure checks; a green test suite does not prove a server is secure.

1. Match each claim to evidence

Use tests for code behavior, commands for configuration and real requests for network behavior. APP_URL=https does not install TLS, and selecting database sessions does not prove all instances share a database.

We add taskflow:security-check, a read-only command that inspects current configuration without printing keys or passwords or changing the system. It exits unsuccessfully when a configured criterion fails. This is a narrow misconfiguration gate, not a vulnerability scanner.

2. Inspect configuration safely

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class SecurityCheck extends Command
{
    protected $signature = 'taskflow:security-check';

    protected $description = 'Read-only production configuration checks without printing secrets';

    public function handle(): int
    {
        $checks = [
            'Production environment' => app()->environment('production'),
            'Debug disabled' => config('app.debug') === false,
            'HTTPS application URL' => parse_url((string) config('app.url'), PHP_URL_SCHEME) === 'https',
            'Application key present (not cryptographic validation)' => is_string(config('app.key')) && config('app.key') !== '',
            'Secure session cookie' => config('session.secure') === true,
            'HttpOnly session cookie' => config('session.http_only') === true,
            'SameSite is lax or strict' => in_array(config('session.same_site'), ['lax', 'strict'], true),
            'Server-side shared-session candidate' => in_array(config('session.driver'), ['database', 'redis'], true),
        ];
        foreach ($checks as $label => $passed) {
            $this->line(($passed ? 'PASS ' : 'FAIL ').$label);
        }
        $this->warn('Configuration only: verify TLS, proxy, storage access, permissions, dependencies and recovery separately.');

        return in_array(false, $checks, true) ? self::FAILURE : self::SUCCESS;
    }
}
php artisan taskflow:security-check
php artisan test --filter=SecurityCheckTest

Run under the release and environment being evaluated, with suitable runtime permissions. Local HTTP/debug settings may legitimately fail; do not relabel development as production to make output green. The key check proves only that a string exists, not entropy, valid length or successful decryption.

Lax/Strict cookies and database/Redis sessions are TaskFlow's baseline, not universal architecture rules. Cross-site applications or alternative session designs need adjusted criteria and tests. Command tests cover passing/failing fixtures and no key echo; the complete suite passed 68 tests with 290 assertions.

3. Public root, secrets and file permissions

Point the web root at public rather than the repository root. Verify externally that environment files, source, logs and backups cannot be downloaded. Gitignore alone cannot stop a misconfigured web server from serving an untracked file.

Grant only necessary writes to storage and bootstrap/cache for the appropriate runtime identity; do not make the entire application world-writable. Limit runtime database privileges and consider separate deployment migration credentials. Store secrets with restricted access and a revocation plan.

Do not casually regenerate an established application's encryption key. Rotation can invalidate encrypted data; inventory affected data and test migration/recovery before changing keys.

4. HTTP and data boundaries

Disable production debug and verify real 500 responses do not disclose traces. Check TLS, session-cookie flags and trusted proxies against the actual network. Broad proxy trust is unsafe when clients can reach the backend directly.

Preserve per-resource authorization, project-scoped queries, field/sort allowlists and bound SQL values. Blade currently escapes user content; do not switch to raw HTML merely to format descriptions. Uploads and outbound URL fetching will need file limits, download authorization and SSRF controls; those features are not present at this milestone.

CSRF, throttling and authorization solve different problems. Do not disable CSRF to fix 419 or treat 429 as proof that every attack is blocked. Earlier lessons test adversarial access, but account recovery, MFA and production provisioning remain incomplete.

5. Dependencies, logs and recovery

Run composer audit and npm audit in a network-enabled dependency-check workflow. Review advisories and runtime/development exposure. Avoid untested blanket updates on production; prepare a tested change and rollback plan. This lesson does not claim all dependencies were audited clean.

Keep credentials and sensitive request bodies out of logs, with controlled access and retention. Protect backups separately from application permissions and test restores in an isolated environment. A backup file's existence does not demonstrate recoverability.

Before opening service, retain evidence for configuration, authorization/CSRF tests, HTTPS/public-root checks, dependency review and restore. Assign ownership and verification steps to unresolved items. TaskFlow remains a local teaching project; publishing these articles does not deploy that application.

Reference: Laravel Deployment. Navigation: Lesson 22 · Roadmap. Next: REST APIs, Resources and validation.

Laravel 13 course navigation

Previous lesson (22) · Next lesson (24) · All 37 lessons

Discussion

Comments 0

Sign in to comment

You need an account to join the discussion and reply to other readers.

Sign inRegister

No comments yet. Be the first to share your thoughts.