Laravel Cookie Missing HttpOnly Flag

Medium Risk Session Management
laravelphpcookieshttponlyxsssession-security

What it is

The Laravel application sets cookies without the HttpOnly flag, making them accessible to client-side JavaScript. This vulnerability exposes session cookies and other sensitive data to Cross-Site Scripting (XSS) attacks, allowing attackers to steal authentication tokens and session information.

// Vulnerable: Cookie without HttpOnly flag // In controller public function setUserPreference(Request $request) { $preference = $request->input('theme'); // Dangerous: Cookie accessible to JavaScript return response('Preference saved')->cookie( 'user_theme', $preference, 60 * 24 * 30 // 30 days // Missing HttpOnly and other security flags ); } // Using Cookie facade (also vulnerable) use Illuminate\Support\Facades\Cookie; public function storeSessionData($data) { // Dangerous: No security flags Cookie::queue('session_data', $data, 120); return response()->json(['status' => 'saved']); } // config/session.php (vulnerable configuration) return [ 'http_only' => false, // Dangerous: Allows JavaScript access 'secure' => false, // Also problematic 'same_site' => null, // Missing CSRF protection ];
// Secure: Cookie with HttpOnly and other security flags // In controller public function setUserPreference(Request $request) { $preference = $request->input('theme'); // Validate input $allowedThemes = ['light', 'dark', 'auto']; if (!in_array($preference, $allowedThemes)) { return response()->json(['error' => 'Invalid theme'], 400); } // Secure: Cookie with security flags return response('Preference saved')->cookie( 'user_theme', $preference, 60 * 24 * 30, // 30 days '/', // path null, // domain true, // secure (HTTPS only) true, // httpOnly false, // raw 'Strict' // sameSite ); } // Using Cookie facade securely use Illuminate\Support\Facades\Cookie; public function storeSessionData($data) { // Secure: With proper security flags Cookie::queue( 'session_data', $data, 120, // minutes '/', // path null, // domain true, // secure true, // httpOnly false, // raw 'Strict' // sameSite ); return response()->json(['status' => 'saved']); } // config/session.php (secure configuration) return [ 'driver' => env('SESSION_DRIVER', 'file'), 'lifetime' => env('SESSION_LIFETIME', 120), 'expire_on_close' => false, 'encrypt' => false, 'files' => storage_path('framework/sessions'), 'connection' => env('SESSION_CONNECTION', null), 'table' => 'sessions', 'store' => env('SESSION_STORE', null), 'lottery' => [2, 100], 'cookie' => env('SESSION_COOKIE', 'laravel_session'), 'path' => '/', 'domain' => env('SESSION_DOMAIN', null), 'secure' => env('SESSION_SECURE_COOKIE', true), 'http_only' => true, // Secure: Prevent JavaScript access 'same_site' => 'strict', // CSRF protection ]; // Middleware for cookie security class SecureCookiesMiddleware { public function handle($request, Closure $next) { $response = $next($request); // Ensure all cookies have security flags foreach ($response->headers->getCookies() as $cookie) { if (!$cookie->isHttpOnly()) { // Log security issue Log::warning('Cookie without HttpOnly flag detected', [ 'cookie_name' => $cookie->getName() ]); } } return $response; } }

💡 Why This Fix Works

See fix suggestions for detailed explanation.

Why it happens

Laravel applications create cookies using response()->cookie() or Cookie facade methods without specifying the HttpOnly parameter, defaulting to insecure configurations. The cookie() helper accepts multiple parameters: cookie($name, $value, $minutes, $path, $domain, $secure, $httpOnly, $raw, $sameSite), but developers commonly use only the first three: response()->cookie('user_pref', $value, 60) omitting security flags. When httpOnly parameter is not explicitly set to true, cookies become accessible via document.cookie in JavaScript, enabling XSS attacks to steal session tokens. Laravel's default behavior varies by configuration, but in many setups, cookies created without explicit flags inherit application-wide settings from config/session.php which may be misconfigured or may not apply to non-session cookies. The vulnerability manifests in various contexts: authentication tokens stored in cookies for remember-me functionality without HttpOnly protection, API tokens or JWT stored client-side accessible to JavaScript, user preference cookies that inadvertently contain sensitive data, and temporary data storage cookies used during multi-step processes. Developers often overlook HttpOnly when setting cookies manually, focusing on functionality rather than security, or copy code examples that demonstrate cookie usage without security considerations. The risk is compounded when applications have XSS vulnerabilities: attackers inject JavaScript that reads document.cookie extracting all non-HttpOnly cookies including session identifiers, then exfiltrate stolen cookies to attacker-controlled servers enabling session hijacking.

Root causes

Setting Cookies Without Explicit HttpOnly Flag Configuration

Laravel applications create cookies using response()->cookie() or Cookie facade methods without specifying the HttpOnly parameter, defaulting to insecure configurations. The cookie() helper accepts multiple parameters: cookie($name, $value, $minutes, $path, $domain, $secure, $httpOnly, $raw, $sameSite), but developers commonly use only the first three: response()->cookie('user_pref', $value, 60) omitting security flags. When httpOnly parameter is not explicitly set to true, cookies become accessible via document.cookie in JavaScript, enabling XSS attacks to steal session tokens. Laravel's default behavior varies by configuration, but in many setups, cookies created without explicit flags inherit application-wide settings from config/session.php which may be misconfigured or may not apply to non-session cookies. The vulnerability manifests in various contexts: authentication tokens stored in cookies for remember-me functionality without HttpOnly protection, API tokens or JWT stored client-side accessible to JavaScript, user preference cookies that inadvertently contain sensitive data, and temporary data storage cookies used during multi-step processes. Developers often overlook HttpOnly when setting cookies manually, focusing on functionality rather than security, or copy code examples that demonstrate cookie usage without security considerations. The risk is compounded when applications have XSS vulnerabilities: attackers inject JavaScript that reads document.cookie extracting all non-HttpOnly cookies including session identifiers, then exfiltrate stolen cookies to attacker-controlled servers enabling session hijacking.

Using Laravel's cookie() Helper Without Security Options

Developers use Laravel's convenient cookie() helper method with minimal parameters, unaware that security flags require explicit configuration and aren't automatically applied to custom cookies. Common insecure patterns include response()->cookie('token', $authToken, 120) creating authentication cookies without HttpOnly flag, Cookie::queue('data', $serialized, 60) queuing cookies with default insecure settings, and Cookie::make('pref', $value) creating cookie instances that later get attached to responses without security review. The Laravel documentation examples often show simple usage for clarity: Cookie::queue('name', 'value', $minutes) without demonstrating security parameters, leading developers to adopt these minimal patterns in production code. Third-party Laravel packages may set cookies without proper security flags, inheriting vulnerabilities into applications. Custom authentication systems built on Laravel that store tokens in cookies: return response()->json($data)->cookie('auth_token', $jwt, 60 * 24) create critical vulnerabilities when HttpOnly is omitted. Shopping cart implementations storing cart IDs: Cookie::queue('cart_id', $cartId, 60 * 24 * 7) expose cart manipulation to XSS. Multi-factor authentication implementations storing MFA state: response()->cookie('mfa_verified', true, 5) without HttpOnly allow attackers to bypass MFA via XSS. The problem extends to cookie middleware: developers write custom middleware modifying cookies without considering security implications, or extend Laravel's cookie encryption middleware disabling encryption and inadvertently removing security flags. Framework updates may change cookie defaults, and applications not explicitly setting security flags may become vulnerable after upgrades.

Missing or Incorrect Session Configuration in config/session.php

Laravel's session configuration file config/session.php controls security attributes for session cookies, and misconfiguration exposes applications to session hijacking through XSS. Critical misconfigurations include 'http_only' => false explicitly disabling HttpOnly protection making session cookies accessible to JavaScript, 'http_only' => env('SESSION_HTTP_ONLY', false) using environment variable with insecure default when SESSION_HTTP_ONLY not set, or completely missing http_only key relying on framework defaults which may be insecure in older Laravel versions. Session configuration affects the main session cookie (typically laravel_session) used for user authentication: when http_only is false or unset, attackers exploiting XSS can execute document.cookie to steal session IDs, then use stolen sessions to impersonate authenticated users. The session configuration also influences remember-me tokens: Laravel's remember token stored in cookies for persistent authentication may not inherit http_only setting depending on implementation, creating separate vulnerability. Environment-specific configuration problems arise when developers use different settings across environments: development with http_only => false for debugging, then deploying to production without changing configuration, or environment variable SESSION_HTTP_ONLY set to false in .env files that get accidentally committed to version control and deployed. Framework scaffolding generates default config/session.php that may prioritize compatibility over security: older Laravel versions (5.x) had less secure defaults, and projects scaffolded years ago may retain outdated configurations. Configuration drift occurs when security best practices evolve but applications aren't updated: Laravel documentation recommendations change over versions, security guides publish new guidance, but existing applications continue with legacy configurations. Developers may intentionally disable HttpOnly believing it necessary for legitimate JavaScript to access session data, not understanding that proper architecture separates authentication (HttpOnly cookies) from client-side state (localStorage or non-HttpOnly cookies).

Custom Cookie Handling that Bypasses Laravel's Secure Defaults

Applications implement custom cookie management logic using PHP's native setcookie() function or third-party packages, bypassing Laravel's cookie encryption and security features. Direct use of PHP setcookie(): setcookie('user_token', $token, time() + 3600) in controllers or middleware sets cookies outside Laravel's cookie queue system, missing automatic encryption, HttpOnly flags, and other security attributes Laravel provides. Custom middleware modifying cookies: developers write middleware directly manipulating response headers: $response->headers->setCookie(new Cookie('name', 'value')) potentially using Cookie class incorrectly without security parameters. Integration with legacy code: Laravel applications wrapping older PHP codebases may include legacy cookie management functions that don't use Laravel's APIs, continuing insecure cookie patterns from pre-Laravel code. Third-party authentication packages implementing custom cookie strategies: OAuth libraries, SSO integrations, or custom auth guards may set cookies directly without following Laravel conventions. API integration requirements: external systems mandating specific cookie formats or attributes leading developers to bypass Laravel's cookie handling to meet integration specifications, inadvertently removing security protections. Performance optimization attempts: developers trying to avoid Laravel's cookie encryption overhead for high-traffic endpoints may use native setcookie() for perceived performance gains, sacrificing security. AJAX/SPA architectures: single-page applications making AJAX requests may handle cookies differently, with developers implementing custom token storage in cookies accessed by JavaScript for API authentication, intentionally making cookies JavaScript-accessible without understanding session hijacking risks. WebSocket implementations storing connection tokens in cookies: real-time features using WebSocket libraries that require client-side cookie access for connection authentication, creating tension between functionality and security where developers choose functionality. The fundamental issue is developers not understanding Laravel's cookie system provides security by default through encryption, HttpOnly flags, and secure transmission, and that bypassing the system requires reimplementing these protections manually.

Inadequate Understanding of Cookie Security Implications

Development teams lack security knowledge about cookie attributes, treating HttpOnly as optional or unimportant feature rather than critical security control preventing session hijacking. Developers may not understand what HttpOnly does: believing it relates to HTTP protocol rather than JavaScript access prevention, thinking it's only necessary for HTTPS connections (confusing with Secure flag), or assuming Laravel automatically makes all cookies secure without explicit configuration. Risk misunderstanding: developers don't recognize that XSS + non-HttpOnly cookies = guaranteed session hijacking, fail to appreciate that XSS vulnerabilities are common making cookie protection essential defense-in-depth, or believe their application has no XSS therefore HttpOnly is unnecessary (ignoring that XSS can be introduced through dependencies, third-party scripts, or future code changes). Training gaps: bootcamp graduates or junior developers without security background may not learn about cookie security attributes, online tutorials and courses often omit security details focusing on functionality, and code review processes don't catch missing HttpOnly flags if reviewers lack security expertise. Framework over-reliance: developers assume Laravel handles all security automatically without understanding which security features require explicit configuration, trust that default settings are secure without verifying, or copy configuration from project templates without understanding security implications of each setting. Development environment differences: developers work in local environments where security matters less, testing with localhost where Secure flag doesn't apply leading to false assumption that security flags aren't important, and staging environments mimicking production security reducing awareness that production security requires explicit configuration. Business pressure: security features seen as impediments to rapid development, security flags omitted from MVP implementations with intention to add later but never revisited, and technical debt accumulation where initial insecure implementations become standard patterns copied throughout codebase. The root cause is treating security as separate concern rather than integral part of development: security training as one-time onboarding rather than continuous education, security reviews as post-development checklist rather than design consideration, and penetration testing as final validation rather than iterative security verification throughout development.

Fixes

1

Configure HttpOnly Flag in config/session.php

Set http_only to true in Laravel's session configuration ensuring session cookies have HttpOnly attribute preventing JavaScript access. Edit config/session.php setting 'http_only' => true in the configuration array, which applies to Laravel's main session cookie (default name laravel_session). This configuration affects all session cookies created by Laravel's session system including authentication sessions, remember-me tokens, and any data stored in Session facade. Verify environment variables: if configuration uses env() helpers like 'http_only' => env('SESSION_HTTP_ONLY', true), ensure .env file contains SESSION_HTTP_ONLY=true (or omit it to use true default), check .env.example includes SESSION_HTTP_ONLY=true as documentation for required variables, and verify production environment variables in hosting platforms (Laravel Forge, Laravel Vapor, AWS Elastic Beanstalk) have SESSION_HTTP_ONLY=true set. Complete session security configuration: set 'secure' => env('SESSION_SECURE_COOKIE', true) enabling Secure flag requiring HTTPS, configure 'same_site' => 'strict' or 'same_site' => 'lax' for CSRF protection, set reasonable 'lifetime' => 120 (minutes) implementing session timeout, and enable 'encrypt' => false (session data encryption is separate from cookie encryption; cookie values are automatically encrypted by Laravel's EncryptCookies middleware). Test session configuration: after changing config/session.php, clear configuration cache: php artisan config:cache, inspect cookies in browser DevTools: session cookie should show HttpOnly attribute checked, attempt to access session cookie via JavaScript: document.cookie.match(/laravel_session/) should return null, and verify authenticated sessions work correctly with new flags. Document configuration: add comments in config/session.php explaining security implications of each flag, create deployment checklist verifying session configuration in production, and include session security verification in application security documentation. Monitor for issues: watch for bug reports about session behavior after configuration changes, implement logging around session creation/destruction detecting anomalies, and use Laravel Telescope or similar monitoring tools tracking session middleware behavior. Review Laravel version compatibility: older Laravel versions (pre-5.6) may have different default configurations or cookie handling, ensure session configuration follows current version's documentation, and consider upgrading Laravel to latest LTS version for best security defaults.

2

Use Laravel's Secure Cookie Methods with Proper Flags

Always specify all security parameters when creating cookies using Laravel's cookie() helper or Cookie facade methods. Use response()->cookie() with full parameter list: return response('Success')->cookie('pref', $value, 60 * 24 * 30, '/', null, true, true, false, 'Strict'); where parameters are name, value, minutes, path, domain, secure (true = HTTPS only), httpOnly (true = JavaScript inaccessible), raw (false = URL encode), sameSite ('Strict'|'Lax'|'None'). For Cookie facade: Cookie::queue('name', 'value', $minutes, $path, $domain, $secure, $httpOnly, $raw, $sameSite); using identical parameters. Create helper functions for consistent secure cookie creation: function secureCookie($name, $value, $minutes = 120) { return cookie($name, $value, $minutes, '/', null, true, true, false, 'Strict'); } centralizing security policy. Use Cookie::make() for cookie instances: $cookie = Cookie::make('token', $authToken, 60, '/', null, true, true, false, 'Strict'); then $response->withCookie($cookie); providing fluent API for cookie attachment. Never use PHP native setcookie(): always use Laravel's cookie methods benefiting from automatic encryption via EncryptCookies middleware and consistent security flag application. Implement cookie factory pattern: class SecureCookieFactory { public static function create($name, $value, $minutes) { return cookie($name, $value, $minutes, '/', config('session.domain'), config('session.secure'), true, false, config('session.same_site')); } } centralizing cookie creation configuration. Audit existing cookie creation: search codebase for cookie(): grep -r '->cookie(' app/ resources/, find Cookie facade usage: grep -r 'Cookie::' app/, and identify native setcookie(): grep -r 'setcookie(' app/, reviewing each instance ensuring security flags present. Replace insecure cookie patterns: change response()->cookie('name', $value, 60) to response()->cookie('name', $value, 60, '/', null, true, true, false, 'Strict'), update Cookie::queue('name', $value, 60) to Cookie::queue('name', $value, 60, '/', null, true, true, false, 'Strict'), and document security requirements in code comments. Test cookie security: use browser developer tools inspecting cookie attributes verifying HttpOnly, Secure, SameSite flags set correctly, attempt JavaScript access: document.cookie should not reveal HttpOnly cookies, and verify cookies only transmitted over HTTPS when Secure flag is set. Create integration tests: Laravel's HTTP tests can verify cookie attributes: $response->assertCookie('name', $value); and $response->assertCookieNotExpired('name');, though testing security flags specifically may require additional assertions. Implement linting rules: create custom Laravel Pint or PHP_CodeSniffer rules detecting cookie() calls without adequate parameters, configure IDE inspections warning on insecure cookie patterns, and add pre-commit hooks preventing commits with insecure cookie code.

3

Set http_only to True in Session Configuration

Explicitly configure http_only attribute in config/session.php eliminating ambiguity and ensuring session cookies always have HttpOnly flag regardless of framework defaults. Locate session configuration: config/session.php in Laravel application root, find or add 'http_only' => true in returned configuration array, typically near other cookie-related settings ('secure', 'same_site', 'domain'). Set secure defaults for all cookie attributes: 'http_only' => true preventing JavaScript access, 'secure' => env('SESSION_SECURE_COOKIE', true) enforcing HTTPS (using environment variable for local development flexibility), 'same_site' => 'strict' or 'lax' preventing CSRF, 'domain' => env('SESSION_DOMAIN', null) restricting cookie scope, and 'path' => '/' specifying cookie path. Understand configuration priority: config/session.php provides application defaults, individual cookie() calls can override defaults by specifying parameters, and EncryptCookies middleware applies encryption to all cookies except those in $except array. Handle environment-specific requirements: local development often uses HTTP not HTTPS, so 'secure' might need environment variable: env('SESSION_SECURE_COOKIE', request()->secure()), use request()->secure() detecting HTTPS automatically, but always keep 'http_only' => true even in development as HttpOnly works on both HTTP and HTTPS. Document configuration decisions: add comments explaining why each flag is set: // http_only: Prevents XSS attacks from accessing session cookies, // secure: Ensures cookies only transmitted over HTTPS, // same_site: Prevents CSRF attacks, and include references to security documentation or OWASP guidelines. Verify configuration applied: after editing config/session.php run php artisan config:cache to regenerate cached configuration, test in browser: authenticate and inspect session cookie seeing HttpOnly and Secure flags checked, use curl with -v flag inspecting HTTP response headers: curl -v https://app.test/login should show Set-Cookie with HttpOnly; Secure; SameSite=Strict attributes. Create configuration validation: implement custom artisan command: php artisan app:verify-security-config checking configuration values against security requirements, run in CI/CD pipeline failing builds if security misconfiguration detected, and document security configuration requirements in README or deployment guides. Review configuration on Laravel upgrades: Laravel version upgrades may introduce new security flags or change defaults, review release notes for security-related configuration changes, and audit config/session.php ensuring alignment with latest security best practices. Implement configuration monitoring: log configuration values on application boot verifying production configuration matches expectations, alert if configuration drift detected (manual changes, failed deployments), and maintain infrastructure-as-code ensuring configuration consistency across deployments.

4

Implement Consistent Cookie Security Across the Application

Establish organization-wide cookie security policies ensuring all cookies, not just session cookies, use appropriate security flags. Create cookie policy documentation: define when cookies should have HttpOnly flag (authentication tokens, session data, any sensitive information), specify that HttpOnly should be omitted only for cookies explicitly needing JavaScript access (CSRF tokens, user preferences that JavaScript must read), and document required security flags: HttpOnly for sensitive data, Secure for all cookies in production, SameSite for CSRF protection. Implement helper classes: create SecureCookie class wrapping Laravel's cookie methods with secure defaults: class SecureCookie { public static function make($name, $value, $minutes = null) { return cookie($name, $value, $minutes ?? config('session.lifetime'), '/', config('session.domain'), config('session.secure'), true, false, config('session.same_site')); } public static function makeJavaScriptAccessible($name, $value, $minutes = null) { return cookie($name, $value, $minutes ?? config('session.lifetime'), '/', config('session.domain'), config('session.secure'), false, false, config('session.same_site')); } }, forcing explicit choice for JavaScript-accessible cookies. Implement service provider: register cookie macros in AppServiceProvider providing convenient secure cookie creation: Response::macro('secureCookie', function($name, $value, $minutes = 120) { return $this->cookie($name, $value, $minutes, '/', null, true, true, false, 'Strict'); }); enabling usage: return response($data)->secureCookie('token', $authToken). Audit all cookie usage: identify every location setting cookies using grep/IDE search, categorize cookies by purpose (authentication, preferences, CSRF, tracking), and determine appropriate security flags for each cookie type. Create cookie inventory: maintain spreadsheet or documentation listing all application cookies: name, purpose, expiration, security flags (HttpOnly, Secure, SameSite), and JavaScript access requirements, review quarterly ensuring cookies still necessary and properly secured, and remove unused cookies reducing attack surface. Implement middleware enforcing cookie security: create middleware examining outgoing responses, validate all cookies have minimum required security flags, log or throw exceptions on insecure cookies in non-production environments, and provide development-time warnings helping developers identify security issues early. Use static analysis: configure PHP static analysis tools (PHPStan, Psalm, Rector) with custom rules detecting insecure cookie patterns: cookie() calls missing security parameters, Cookie facade usage without flags, or native setcookie() usage, integrate static analysis in CI/CD pipelines preventing insecure code merges. Provide developer training: educate team on cookie security implications, demonstrate attack scenarios showing XSS + insecure cookies = session hijacking, and conduct code review workshops focusing on cookie security. Implement code review checklist: require reviewers verify cookie security on every PR touching cookie code, check that new cookies have documented purpose and appropriate flags, and ensure custom cookie handling doesn't bypass security middleware. Monitor production cookies: use browser extension or monitoring tools periodically checking production cookies verify all security flags present, alert on newly introduced cookies without proper security configuration, and track cookie security metrics in security dashboard.

5

Review and Update All Custom Cookie Handling Code

Conduct comprehensive audit of custom cookie implementation identifying and fixing security vulnerabilities in non-standard cookie handling. Search for cookie-related code: grep -r 'cookie(' app/ finding Laravel cookie helper usage, grep -r 'Cookie::' app/ locating Cookie facade calls, grep -r 'setcookie(' app/ vendor/ identifying native PHP cookie usage (exclude vendor/ if not necessary), and grep -r 'Set-Cookie' app/ finding raw header manipulation. Identify custom implementations: custom authentication systems setting cookies directly, third-party package integration modifying cookies outside Laravel conventions, legacy code converted from other frameworks with own cookie handling, API clients setting cookies for external services, and WebSocket or real-time features using cookies for connection management. Review each instance: verify security flags present (HttpOnly, Secure, SameSite), check if cookie encryption needed and properly implemented, validate cookie expiration appropriateness, confirm no sensitive data stored unencrypted, and ensure cookie domain/path restrict scope appropriately. Refactor insecure patterns: replace native setcookie() with Laravel cookie() helper, move cookie creation into dedicated service classes providing secure defaults, eliminate direct Set-Cookie header manipulation, and remove custom cookie encryption in favor of Laravel's EncryptCookies middleware. Fix identified issues: add missing HttpOnly flags: change setcookie($name, $value, $expire) to cookie($name, $value, minutes, '/', null, true, true, false, 'Strict'), enable Secure flag for HTTPS: verify production uses HTTPS and Secure flag is true, add SameSite attribute: include 'Strict' or 'Lax' in cookie creation, and encrypt sensitive cookies: ensure sensitive cookies pass through EncryptCookies middleware or use encrypted cookie queuing. Test custom implementations: verify cookies set correctly with expected flags in browser DevTools, test authentication flows ensuring sessions work with security flags enabled, check API integrations still function with secured cookies, and validate WebSocket connections with HttpOnly cookies. Document custom cookie usage: add inline comments explaining why custom cookie handling necessary, document security considerations and risk acceptance if HttpOnly cannot be used for legitimate reasons, and create architecture documentation describing cookie strategy across application. Create migration plan: for large codebases with extensive custom cookie handling, prioritize fixes based on cookie sensitivity (session cookies highest priority, preference cookies lower priority), implement fixes incrementally with testing between changes, and monitor production after each change detecting issues early. Implement automated checks: add PHPUnit tests asserting cookies have correct security flags: $response->assertCookie('name')->assertCookieHttpOnly('name'), create integration tests covering authentication flows with secure cookies, and set up browser automation tests (Laravel Dusk) verifying cookies cannot be accessed via JavaScript. Establish code standards: define when custom cookie handling is acceptable, require security review for any custom cookie implementation, and default to Laravel's cookie methods unless compelling reason otherwise documented. Schedule regular audits: quarterly review of all cookie handling code, automated security scanning detecting insecure cookie patterns, and track cookie security metrics in application security dashboard.

6

Use Middleware to Enforce Secure Cookie Attributes

Implement Laravel middleware that automatically validates and enforces security attributes on all outgoing cookies, providing defense-in-depth ensuring no cookies leave application without proper security flags. Create enforcement middleware: php artisan make:middleware SecureCookiesMiddleware implementing handle() method that inspects response cookies: public function handle($request, Closure $next) { $response = $next($request); foreach ($response->headers->getCookies() as $cookie) { if (!$cookie->isHttpOnly()) { if (app()->environment('production')) { throw new SecurityException('Cookie without HttpOnly: ' . $cookie->getName()); } Log::warning('Insecure cookie detected', ['name' => $cookie->getName()]); } } return $response; }. Register middleware: add to app/Http/Kernel.php in $middleware array for global application, in $middlewareGroups['web'] for web routes only, or in $routeMiddleware for selective route application. Implement automatic flag enforcement: rather than throwing exceptions, automatically add missing flags: $cookies = $response->headers->getCookies(); foreach ($cookies as $cookie) { if (!$cookie->isHttpOnly() && !$this->isJavaScriptAccessible($cookie->getName())) { $response->headers->setCookie($this->addHttpOnly($cookie)); } }, with helper method determining if cookie legitimately needs JavaScript access: protected function isJavaScriptAccessible($name) { $jsAccessible = ['csrf_token', 'user_preferences']; return in_array($name, $jsAccessible); }. Configure allowed exceptions: define cookies that legitimately cannot have HttpOnly: protected $javascriptAccessibleCookies = ['XSRF-TOKEN', 'theme_preference']; public function handle($request, Closure $next) { $response = $next($request); foreach ($response->headers->getCookies() as $cookie) { if (!$cookie->isHttpOnly() && !in_array($cookie->getName(), $this->javascriptAccessibleCookies)) { Log::alert('Unexpected JavaScript-accessible cookie', ['cookie' => $cookie->getName()]); } } return $response; }, documenting why each exception exists. Implement comprehensive validation: check not only HttpOnly but also Secure flag in production: if (app()->environment('production') && !$cookie->isSecure()), verify SameSite attribute: if (!in_array($cookie->getSameSite(), ['Strict', 'Lax'])), validate expiration: if ($cookie->getExpiresTime() > $maxExpiration), and check domain restriction: if ($cookie->getDomain() === null). Provide detailed logging: log cookie security violations with context: Log::warning('Cookie security violation', ['cookie_name' => $cookie->getName(), 'missing_flags' => $missingFlags, 'route' => $request->path(), 'controller' => $request->route()?->getActionName()]), aggregate violations showing which code paths create insecure cookies, and alert on repeated violations from same source. Implement testing: test middleware catches insecure cookies: $response = $this->get('/set-insecure-cookie'); $this->expectException(SecurityException::class);, verify middleware allows legitimate exceptions: $response = $this->get('/set-csrf-cookie'); $response->assertCookie('XSRF-TOKEN'); $this->assertFalse($response->getCookie('XSRF-TOKEN')->isHttpOnly());, and integration tests ensuring middleware doesn't break existing functionality. Configure environment behavior: strict enforcement in production throwing exceptions on violations preventing insecure cookies from being set, warning mode in staging logging violations but allowing cookies for testing, and disabled in local development or with explicit flag for debugging. Document middleware: explain purpose in middleware class docblock, document allowed exceptions with security justification, and include middleware configuration in deployment documentation. Combine with monitoring: integrate with application monitoring tools (Sentry, Bugsnag) reporting cookie security violations as events, track metrics: number of insecure cookies by route/controller showing hotspots, and create dashboards visualizing cookie security compliance over time. Regular review: quarterly audit of JavaScript-accessible cookie exceptions ensuring still necessary, review logged violations identifying patterns requiring code fixes, and update middleware as security requirements evolve.

Detect This Vulnerability in Your Code

Sourcery automatically identifies laravel cookie missing httponly flag and many other security issues in your codebase.