Laravel Cookie Missing SameSite Attribute

Medium Risk Cross-Site Request Forgery
laravelphpcookiessamesitecsrfcross-site-attacks

What it is

The Laravel application sets cookies without the SameSite attribute or with an inappropriate value, making it vulnerable to Cross-Site Request Forgery (CSRF) attacks. The SameSite attribute controls when cookies are sent with cross-site requests, providing protection against CSRF and some forms of cross-site information leakage.

// Vulnerable: Missing or inappropriate SameSite attribute public function login(Request $request) { $credentials = $request->only('email', 'password'); if (Auth::attempt($credentials)) { $token = $request->user()->createToken('auth')->plainTextToken; // Dangerous: No SameSite attribute return response('Login successful')->cookie( 'auth_token', $token, 60 * 24, // 24 hours '/', null, true, // secure true // httpOnly // Missing SameSite! ); } } // Another vulnerable pattern public function setUserPreference(Request $request) { $theme = $request->input('theme'); // Problematic: SameSite=None without proper justification Cookie::queue( 'user_theme', $theme, 60 * 24 * 30, '/', null, true, false, false, 'None' // Dangerous: Too permissive ); } // config/session.php (missing SameSite) return [ 'same_site' => null, // Problematic: No CSRF protection ];
// Secure: Proper SameSite configuration public function login(Request $request) { $credentials = $request->only('email', 'password'); if (Auth::attempt($credentials)) { $user = $request->user(); $token = $user->createToken('auth')->plainTextToken; // Secure: Strict SameSite for authentication return response('Login successful')->cookie( 'auth_token', $token, 60 * 24, // 24 hours '/', config('session.domain'), true, // secure true, // httpOnly false, 'Strict' // Strict for auth cookies ); } return response('Invalid credentials', 401); } // Different SameSite values for different use cases public function setUserPreference(Request $request) { $theme = $request->input('theme'); // Validate input $allowedThemes = ['light', 'dark', 'auto']; if (!in_array($theme, $allowedThemes)) { return response()->json(['error' => 'Invalid theme'], 400); } // Secure: Lax for non-critical preferences Cookie::queue( 'user_theme', $theme, 60 * 24 * 30, // 30 days '/', config('session.domain'), true, // secure false, // httpOnly (false for JS access to theme) false, 'Lax' // Lax allows some cross-site usage ); return response()->json(['status' => 'theme_saved']); } // Service for managing SameSite policies class CookieSameSiteService { public function getSameSiteForCookieType($cookieType) { $policies = [ 'auth' => 'Strict', // Authentication cookies 'session' => 'Strict', // Session cookies 'csrf' => 'Strict', // CSRF tokens 'preferences' => 'Lax', // User preferences 'analytics' => 'Lax', // Analytics cookies 'tracking' => 'None', // Only if absolutely necessary ]; return $policies[$cookieType] ?? 'Lax'; } public function setCookieSecurely($name, $value, $type, $minutes = 60) { $sameSite = $this->getSameSiteForCookieType($type); // For SameSite=None, Secure flag is required $secure = $sameSite === 'None' ? true : config('session.secure', true); return Cookie::make( $name, $value, $minutes, '/', config('session.domain'), $secure, true, // httpOnly for security false, $sameSite ); } } // Middleware to validate cookie security class CookieSecurityMiddleware { public function handle($request, Closure $next) { $response = $next($request); // Validate response cookies foreach ($response->headers->getCookies() as $cookie) { $this->validateCookieSecurity($cookie); } return $response; } private function validateCookieSecurity($cookie) { $name = $cookie->getName(); $sameSite = $cookie->getSameSite(); // Check for missing SameSite if (empty($sameSite)) { Log::warning('Cookie without SameSite attribute', ['cookie' => $name]); } // Validate SameSite=None has Secure flag if ($sameSite === 'None' && !$cookie->isSecure()) { Log::error('SameSite=None cookie without Secure flag', ['cookie' => $name]); } // Check sensitive cookies have Strict SameSite $sensitiveCookies = ['auth_token', 'session_token', 'csrf_token']; if (in_array($name, $sensitiveCookies) && $sameSite !== 'Strict') { Log::warning('Sensitive cookie without Strict SameSite', [ 'cookie' => $name, 'samesite' => $sameSite ]); } } } // 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, 'same_site' => env('SESSION_SAME_SITE', 'Strict'), // Secure default ];

💡 Why This Fix Works

See fix suggestions for detailed explanation.

Why it happens

Laravel applications create cookies without specifying SameSite attribute, relying on browser defaults that may not provide adequate CSRF protection. When cookie() helper is called without SameSite parameter: response()->cookie('token', $value, 60, '/', null, true, true) omitting the final parameter, or Cookie::queue() used with fewer than 9 parameters missing SameSite specification, browsers apply default behavior which varies: modern browsers (Chrome 80+, Firefox 69+) default to SameSite=Lax providing some protection, older browsers have no SameSite support leaving applications vulnerable, and inconsistent defaults create unpredictable security posture across user bases. The config/session.php file may contain 'same_site' => null or completely omit the same_site key, resulting in no SameSite protection for session cookies. This vulnerability enables CSRF attacks: attacker creates malicious website with form targeting vulnerable application, victim visits attacker site while authenticated to target application, form auto-submits (via JavaScript) sending cookies without SameSite restriction, and server processes request as legitimate because cookies are included. Real-world attack scenarios include state-changing operations (password changes, fund transfers, account deletions) triggered from attacker-controlled sites, cross-site WebSocket hijacking connecting to WebSocket endpoints with victim's cookies, and timing attacks using cross-origin requests with credentials revealing information through side channels. The problem is particularly severe for applications predating SameSite widespread adoption (pre-2019) where cookie code written without SameSite consideration remains in production, and for applications where developers are unaware of SameSite importance treating it as optional rather than essential security control. Browser compatibility adds complexity: older browsers ignoring SameSite creating security gaps for users on legacy systems, Safari and iOS browsers having quirky SameSite handling requiring special consideration, and mobile app WebView components potentially not respecting SameSite correctly.

Root causes

Missing SameSite Attribute in Cookie Configuration

Laravel applications create cookies without specifying SameSite attribute, relying on browser defaults that may not provide adequate CSRF protection. When cookie() helper is called without SameSite parameter: response()->cookie('token', $value, 60, '/', null, true, true) omitting the final parameter, or Cookie::queue() used with fewer than 9 parameters missing SameSite specification, browsers apply default behavior which varies: modern browsers (Chrome 80+, Firefox 69+) default to SameSite=Lax providing some protection, older browsers have no SameSite support leaving applications vulnerable, and inconsistent defaults create unpredictable security posture across user bases. The config/session.php file may contain 'same_site' => null or completely omit the same_site key, resulting in no SameSite protection for session cookies. This vulnerability enables CSRF attacks: attacker creates malicious website with form targeting vulnerable application, victim visits attacker site while authenticated to target application, form auto-submits (via JavaScript) sending cookies without SameSite restriction, and server processes request as legitimate because cookies are included. Real-world attack scenarios include state-changing operations (password changes, fund transfers, account deletions) triggered from attacker-controlled sites, cross-site WebSocket hijacking connecting to WebSocket endpoints with victim's cookies, and timing attacks using cross-origin requests with credentials revealing information through side channels. The problem is particularly severe for applications predating SameSite widespread adoption (pre-2019) where cookie code written without SameSite consideration remains in production, and for applications where developers are unaware of SameSite importance treating it as optional rather than essential security control. Browser compatibility adds complexity: older browsers ignoring SameSite creating security gaps for users on legacy systems, Safari and iOS browsers having quirky SameSite handling requiring special consideration, and mobile app WebView components potentially not respecting SameSite correctly.

Using Inappropriate SameSite Values for Application Context

Applications set SameSite attribute but choose wrong value for specific cookie's security requirements and functionality needs, either too permissive (risking CSRF) or too restrictive (breaking functionality). Common misconfigurations include authentication cookies with SameSite=Lax instead of Strict: response()->cookie('auth', $token, 60, '/', null, true, true, false, 'Lax') allowing cross-site GET requests to carry authentication, which enables CSRF via GET requests if application performs state changes on GET (violating HTTP semantics but unfortunately common). Using SameSite=None unnecessarily broadly: developers set Cookie::queue('pref', $data, 60, '/', null, true, false, false, 'None') for simple preferences that don't require cross-site access, increasing attack surface without justification. OAuth/OpenID callback handling with SameSite=Strict breaking legitimate flows: authentication cookies with Strict SameSite prevent cookies from being sent during OAuth redirects back to application causing authentication failures. Payment gateway integrations misconfigured: e-commerce checkout redirecting to PayPal/Stripe then back to application loses session with SameSite=Strict, developers workaround by setting SameSite=None globally rather than specifically for payment flow cookies. Single Sign-On (SSO) implementations with wrong SameSite: SAML/OAuth sessions requiring SameSite=Lax or None for cross-domain authentication flows, but developers set Strict breaking SSO functionality. Subdomain applications with inappropriate settings: cookies shared across subdomains (api.example.com, www.example.com) using SameSite=Strict even though subdomain requests are technically cross-site in some contexts. Analytics and tracking cookies with SameSite=Strict: preventing legitimate cross-site analytics tracking that product requirements depend on. The root issue is not understanding SameSite value semantics: Strict prevents all cross-site cookie transmission including legitimate navigation, Lax allows cookies on top-level navigation GET requests providing balance between security and usability, None allows all cross-site cookie transmission requiring Secure flag and HTTPS. Context-specific requirements often ignored: authentication should use Strict accepting that some OAuth flows require special handling, general sessions can use Lax as safe default, and third-party integrations may require None but should be minimized and carefully reviewed.

Inadequate Understanding of SameSite Cookie Behavior

Development teams lack comprehensive understanding of how SameSite attribute works, leading to misconfigurations that either break functionality or fail to provide security. Fundamental misunderstandings include believing SameSite provides complete CSRF protection: SameSite helps but doesn't replace CSRF tokens, especially for applications serving same-site requests where SameSite offers no protection, and believing SameSite=Lax is always safe: Lax allows GET requests to carry cookies, so applications performing state changes on GET remain vulnerable. Confusion about cross-site vs cross-origin: developers think same-site means same-origin, but same-site is more permissive (subdomains are same-site), and Public Suffix List determines site boundaries making example.com and example.co.uk different sites but www.example.com and api.example.com same-site. Not understanding navigation types: SameSite=Lax allows cookies on top-level navigations (user clicks link) but blocks subresource requests (images, scripts) and iframes, developers don't realize POST requests from external sites are blocked by Lax, and AJAX/fetch requests have special SameSite handling distinct from form submissions. Browser compatibility gaps: some browsers don't support SameSite requiring application-level CSRF protection as fallback, browser behavior evolution (Chrome changing defaults, Safari bugs) creates moving target, and developers testing in single browser miss cross-browser inconsistencies. SameSite=None requirements often misunderstood: None requires Secure flag (HTTPS only) but developers try to use on HTTP during development, older browsers reject SameSite=None as invalid requiring cookie to be set twice with and without SameSite for compatibility, and None should be exceptional case but developers use as default for simplicity. Interaction with other cookie attributes: SameSite combined with HttpOnly and Secure creates complex security matrix, Domain attribute interacts with SameSite in non-obvious ways for subdomain cookies, and Path attribute restrictions apply before SameSite evaluation. Performance and caching implications: SameSite affects cookie transmission patterns changing caching behavior, CDN and reverse proxy handling of SameSite cookies varies, and service workers have special SameSite considerations. Testing challenges: local development on localhost has different SameSite behavior than production domains, simulating cross-site requests requires proper test environment setup, and automated tests may not catch SameSite issues without browser automation. The solution requires: comprehensive developer training on SameSite semantics, documented decision matrix for choosing SameSite values by cookie type, cross-browser testing procedures, and regular security audits reviewing SameSite configurations.

Legacy Cookie Code that Doesn't Include Modern Security Attributes

Applications contain cookie management code written before SameSite attribute introduction (pre-2016 standard, widespread adoption 2019-2020) that hasn't been updated to include modern security attributes. Legacy patterns include cookie() calls with 7-8 parameters omitting SameSite: response()->cookie($name, $value, $minutes, $path, $domain, $secure, $httpOnly) from era before SameSite was standard parameter, Cookie::make() instances missing final parameters, and helper functions wrapping cookie creation that don't include SameSite in their signatures. Framework version legacy: applications on older Laravel versions (5.x, early 6.x) before SameSite was config/session.php option, upgrade paths not including SameSite configuration review, and boilerplate generated by old framework versions still in use. Third-party package legacy: authentication packages (Laravel Sanctum, Passport, Socialite older versions) not setting SameSite on their cookies, session management packages with outdated cookie creation, and middleware packages modifying cookies without SameSite awareness. Documentation and tutorials lag: Stack Overflow answers from 2015-2018 showing cookie code without SameSite copied by developers, Laravel documentation examples in older versions not demonstrating SameSite, and training materials not updated for modern security practices. Migration challenges slow updates: fear of breaking existing functionality prevents cookie security updates, lack of comprehensive testing for cookie behavior across user flows, and absence of automated detection for missing SameSite in existing code. Technical debt accumulation: initial prototype or MVP built without SameSite consideration, "if it ain't broke don't fix it" mentality toward working legacy code, and security updates deprioritized against new feature development. The impact is severe: applications vulnerable to CSRF attacks despite other security measures, inconsistent security posture where new code has SameSite but legacy code doesn't, and users on modern browsers seeing default SameSite=Lax masking underlying vulnerability until they use older browser. Remediation requires: comprehensive code audit identifying all cookie creation locations, systematic update of cookie calls to include SameSite with appropriate values, refactoring of helper functions and middleware to support SameSite, testing changes across user flows to prevent regression, and documentation of SameSite decisions for each cookie type.

Misconfigured Session Settings in Laravel

Laravel's config/session.php file lacks proper SameSite configuration or contains inappropriate values affecting all session-based authentication and state management. Common misconfigurations include 'same_site' => null explicitly setting no SameSite protection for session cookies, missing same_site key entirely relying on Laravel version defaults which may be insecure, 'same_site' => env('SESSION_SAME_SITE', null) using environment variable that's often unset in .env file defaulting to no protection. Environment-specific issues arise: development .env missing SESSION_SAME_SITE causing null default, production .env not updated from .env.example that contains old configuration, and staging environment using different SameSite setting than production causing environment-specific bugs. Framework version defaults vary: Laravel 5.x had no SameSite configuration option requiring manual cookie handling, Laravel 6.x introduced same_site option with null default, and Laravel 7+ defaults to 'lax' but applications upgraded from older versions may not have updated config files. The session configuration affects multiple cookies: primary session cookie (laravel_session by default) used for authentication and state management, remember-me cookie for persistent authentication, CSRF token cookie (XSRF-TOKEN) for CSRF protection, and Laravel Sanctum/Passport cookies for API authentication. Misconfiguration impact includes session-based CSRF vulnerability: attackers can trigger state-changing operations in user's session, authentication bypass scenarios: cross-site attacks leveraging session cookies improperly protected, and broken functionality: overly restrictive SameSite breaking legitimate cross-site workflows like OAuth callbacks. Configuration interaction problems: same_site setting in session config doesn't affect manually created cookies using response()->cookie() or Cookie facade requiring separate configuration, packages may set their own cookies independent of session configuration, and middleware order affects whether session configuration applies to all responses. Multi-application environments compound issues: microservices architecture where each service has own session configuration risking inconsistency, shared authentication across applications requiring coordinated SameSite configuration, and API vs web application requiring different SameSite policies. Validation gaps: no automated checking that SESSION_SAME_SITE environment variable is set appropriately, application starts successfully with misconfigured SameSite causing silent vulnerability, and monitoring doesn't detect missing SameSite attributes on cookies. Solutions require: explicit same_site configuration in config/session.php with secure default ('Strict' or 'Lax'), environment variable validation ensuring SESSION_SAME_SITE is set in production, automated testing verifying session cookies have correct SameSite attribute, and documentation explaining SameSite choice rationale.

Fixes

1

Set Appropriate SameSite Attribute for All Cookies (Strict, Lax, or None)

Configure SameSite attribute for every cookie based on security requirements and functionality needs, choosing from Strict, Lax, or None values with clear rationale. Understand SameSite values: Strict prevents cookie transmission in all cross-site contexts (even user clicking link from external site), Lax allows cookies on top-level navigation GET requests but blocks subresources and POST requests, and None allows all cross-site cookie transmission but requires Secure flag and HTTPS. Establish default policy: use Lax as safe default for most cookies balancing security and functionality, upgrade to Strict for sensitive authentication cookies accepting potential OAuth/SSO complications, and use None only when truly necessary (embedded widgets, cross-site APIs) with security review. Implement in cookie creation: always specify SameSite as final parameter: response()->cookie($name, $value, $minutes, $path, $domain, $secure, $httpOnly, false, $sameSite), use helper function for consistency: function appCookie($name, $value, $minutes, $sameSite = 'Lax') { return cookie($name, $value, $minutes, '/', config('session.domain'), true, true, false, $sameSite); }, and create cookie factory classes: class CookieFactory { public static function auth($name, $value, $minutes) { return cookie($name, $value, $minutes, '/', config('session.domain'), true, true, false, 'Strict'); } public static function preference($name, $value, $minutes) { return cookie($name, $value, $minutes, '/', config('session.domain'), true, false, false, 'Lax'); } }. Configure session SameSite in config/session.php: set 'same_site' => 'Strict' for highest security on authentication, use 'same_site' => 'Lax' for general applications needing OAuth/SSO compatibility, and document decision rationale in configuration comments. Handle SameSite=None correctly: always combine with Secure flag: Cookie::queue($name, $value, $minutes, '/', $domain, true, $httpOnly, false, 'None'), implement for legitimate cross-site scenarios (embedded content, third-party service integration), and maintain inventory of None cookies requiring ongoing security review. Address browser compatibility: modern browsers support all SameSite values, older browsers (pre-2019) ignore SameSite requiring CSRF tokens as fallback, and some browsers have bugs requiring workarounds (double-cookie approach setting both with and without SameSite). Validate implementation: search codebase for all cookie creation: grep -r 'cookie(' app/ resources/, verify every instance includes SameSite parameter, and use static analysis tools detecting missing SameSite. Test comprehensively: verify authentication works with SameSite=Strict, test OAuth/SSO flows with configured SameSite, check cross-site AJAX requests behave correctly, and validate across multiple browsers. Monitor production: log cookies without SameSite attribute, alert on security exceptions requiring SameSite=None, and track CSRF attack attempts correlating with SameSite configuration. Document policy: maintain cookie inventory listing each cookie's SameSite value and justification, provide decision tree for developers choosing SameSite values, and include SameSite requirements in code review checklist.

2

Use 'Strict' for Sensitive Authentication Cookies

Apply SameSite=Strict to authentication cookies, session tokens, and any credentials providing elevated privileges accepting functional trade-offs for maximum security. Identify sensitive cookies requiring Strict: primary authentication tokens used for user login, session identifiers tracking authenticated sessions, administrative access tokens for privileged operations, MFA state cookies indicating multi-factor authentication completion, and CSRF tokens themselves (for defense-in-depth). Implement Strict for authentication: login process creates Strict cookie: public function login(Request $request) { $user = Auth::attempt($request->only('email', 'password')); if ($user) { return response('Success')->cookie('auth', $token, 120, '/', config('session.domain'), true, true, false, 'Strict'); } }, API authentication uses Strict: Cookie::queue('api_token', $apiToken, 60, '/', config('session.domain'), true, true, false, 'Strict'), and admin sessions use Strict: response()->cookie('admin_session', $session, 30, '/', 'admin.example.com', true, true, false, 'Strict'). Configure session.php for Strict authentication: set 'same_site' => 'Strict' in config/session.php applying to laravel_session cookie, accepting that external OAuth/SSO redirects may require special handling, and document why Strict chosen for application. Handle OAuth/SSO with Strict sessions: implement state parameter pattern: store CSRF state in server-side session before OAuth redirect, after OAuth callback, verify state parameter matches session, then set Strict authentication cookie. Use temporary transition cookies: OAuth flow creates temporary Lax cookie during authentication process, after successful authentication, replace with Strict cookie, and expire temporary cookie. Alternative: stateless OAuth: use JWT passed in URL during OAuth flow avoiding cookies entirely during authentication, after validation, set Strict session cookie, and clear URL parameters. Educate users about Strict implications: external links to application may require login even with active session, users need to navigate directly to application or use bookmarks, and document this behavior as security feature not bug. Test Strict authentication: verify login directly to application works correctly, test that cross-site links to authenticated pages require re-login, confirm administrative operations protected by Strict cookies, and check mobile apps handling Strict cookies correctly. Balance security and usability: use Strict for session authentication accepting login friction, provide remember-me tokens as separate Lax cookies for convenience, and implement explicit re-authentication for sensitive operations. Monitor Strict cookie behavior: track authentication failures potentially related to Strict SameSite, measure user frustration from cross-site login requirements, and analyze whether security benefit justifies usability cost. Document Strict policy: explain to team why Strict chosen for authentication cookies, provide examples of attacks prevented by Strict, document exceptions where Lax might be appropriate, and include Strict requirements in security policy.

3

Use 'Lax' for General Session Cookies that Need Some Cross-Site Functionality

Apply SameSite=Lax as default for session cookies requiring balance between security and functionality, allowing top-level navigation while blocking dangerous cross-site requests. Understand Lax behavior: cookies sent with top-level navigation GET requests (user clicks link from external site), blocked on subresource requests (images, scripts, iframes), blocked on POST requests from external sites, and blocked on AJAX/fetch requests from other domains. Lax is appropriate for: general user sessions in web applications, e-commerce shopping carts allowing external links to products, content management systems where editors arrive via external links, and OAuth/SSO flows requiring cookie during authentication callbacks. Implement Lax configuration: set in config/session.php: 'same_site' => 'Lax' applying to all session cookies, create cookies with Lax: response()->cookie('session', $data, 120, '/', config('session.domain'), true, true, false, 'Lax'), and use as default in helper functions: function sessionCookie($name, $value, $minutes) { return cookie($name, $value, $minutes, '/', config('session.domain'), true, true, false, 'Lax'); }. Lax provides protection against: cross-site POST-based CSRF attacks (form submissions from malicious sites), cross-site AJAX request CSRF, embedded iframe attacks reading or modifying data, and image/script-based timing attacks. Lax doesn't protect against: GET-based CSRF if application performs state changes on GET (violating HTTP semantics), same-site attacks from subdomains or compromised same-site origins, and attacks that trick users into clicking links (phishing with legitimate-looking URLs). Combine Lax with CSRF tokens: Lax as first defense layer against cross-site attacks, CSRF tokens protect against same-site attacks and GET-based CSRF, and double-submit cookie pattern for additional protection. Test Lax functionality: verify external links to application work correctly (users can arrive from search engines, email links), confirm OAuth/SSO callbacks succeed with Lax cookies, test that cross-site AJAX requests are properly blocked, and validate embedded widgets on other domains don't receive cookies. Handle edge cases: payment gateway redirects returning to application work with Lax, email links to password reset or account verification function correctly, deep links from mobile apps to web views carry session, and bookmark/direct navigation works as expected. Optimize Lax configuration: review application for GET requests changing state (should be POST), implement idempotent GET requests following HTTP semantics, and ensure Lax provides adequate protection for application threat model. Monitor Lax effectiveness: track CSRF attacks blocked by Lax vs additional protections, measure user friction from any Lax-related issues, and analyze security incidents to validate Lax appropriateness. Document Lax rationale: explain why Lax chosen over Strict (OAuth compatibility, user navigation patterns), document which attack types Lax prevents, describe additional protections complementing Lax (CSRF tokens), and provide guidance for new features requiring Lax validation.

4

Only Use 'None' When Absolutely Necessary and with Secure Flag

Restrict SameSite=None to legitimate cross-site cookie requirements, always requiring Secure flag and HTTPS, and maintaining strict inventory of None cookies. Legitimate None use cases: embedded widgets or iframes requiring authentication (chat widgets, embedded dashboards), cross-domain single sign-on where main authentication is on different domain, third-party API integrations sending credentials cross-site, and analytics/tracking cookies explicitly requiring cross-site transmission (if business requirements mandate). Implement None securely: always require Secure flag: Cookie::queue($name, $value, $minutes, '/', $domain, true, $httpOnly, false, 'None'), validate HTTPS in production: if (app()->environment('production') && $sameSite === 'None' && !$secure) { throw new SecurityException('SameSite=None requires Secure flag'); }, and document business justification for each None cookie. Browser compatibility for None: modern browsers (Chrome 80+, Firefox 69+, Safari 12+) support SameSite=None with Secure, older browsers may reject SameSite=None as invalid, and implement dual-cookie workaround: set cookie twice, once with SameSite=None for modern browsers, once without SameSite for legacy browsers. Handle local development challenges: SameSite=None requires HTTPS but development often uses HTTP, solutions: use local HTTPS setup (self-signed certificates, mkcert), configure environment-specific SameSite: None in production, Lax in development, or disable SameSite=None validation in local environment with clear documentation. Minimize None usage: review existing None cookies for necessity, refactor architecture to eliminate cross-site cookie requirements (move to same-site deployment), use alternative patterns: message passing (postMessage) instead of cookies, JWT in Authorization header instead of cookies, or iframe-based OAuth instead of cross-domain cookies. Security review process for None: require security team approval for any new None cookies, document threat model and mitigation strategies, implement monitoring for None cookie misuse, and quarterly audit reviewing continued necessity of None cookies. Test None implementation: verify cookies transmitted correctly across domains, test with multiple browsers including older versions, confirm Secure flag always present with None, and validate that removing None would actually break functionality. Monitor None cookies: alert on new cookies using SameSite=None, track None cookie transmission in logs, detect potential abuse or hijacking of None cookies, and report on None cookie inventory in security dashboard. Alternative approaches to avoid None: redesign application architecture keeping authentication on same domain, use frontend proxy keeping all requests same-site, implement token-based authentication not requiring cookies, or use session storage with synchronization instead of cross-site cookies. Document None cookies: maintain registry of all SameSite=None cookies with business justification, explain security implications to stakeholders, provide alternatives considered and rejected, and include review schedule ensuring continued necessity.

5

Configure SameSite in Laravel Session Configuration

Set appropriate SameSite value in config/session.php ensuring consistent secure configuration for all session-based cookies across application. Edit config/session.php adding or updating same_site key: 'same_site' => 'Strict' for maximum security, 'same_site' => 'Lax' for balance between security and functionality, or 'same_site' => env('SESSION_SAME_SITE', 'Lax') using environment variable with secure default. Understand configuration scope: session.same_site applies to laravel_session cookie used for session state, XSRF-TOKEN cookie for CSRF protection, remember cookies for persistent authentication, and any cookies using session configuration. Set environment variable in .env: SESSION_SAME_SITE=Strict for production requiring maximum security, SESSION_SAME_SITE=Lax for applications with OAuth/SSO integration, and document in .env.example: SESSION_SAME_SITE=Strict as required configuration. Configure environment-specific values: production .env: SESSION_SAME_SITE=Strict for strictest security, staging .env: SESSION_SAME_SITE=Lax for realistic testing, development .env: SESSION_SAME_SITE=Lax or omit for simpler local development. Validate configuration: implement artisan command checking session configuration: php artisan config:check verifying SESSION_SAME_SITE is set appropriately, add application bootstrap validation throwing exception if misconfigured: if (config('session.same_site') === null) { throw new ConfigurationException('SESSION_SAME_SITE required'); }, and fail fast preventing misconfigured application from starting. Clear configuration cache after changes: run php artisan config:cache regenerating cached configuration, deploy new configuration to all application servers, and verify configuration active: check cookies in browser developer tools. Test session SameSite configuration: log in to application and inspect session cookie in browser DevTools, verify SameSite attribute matches configuration, test authentication across different navigation scenarios (direct access, external link, POST form), and confirm CSRF protection works correctly. Handle package compatibility: verify Laravel Sanctum/Passport respect session.same_site configuration, check third-party authentication packages use session settings, and test that middleware packages don't override SameSite. Document configuration decision: add comments in config/session.php explaining why specific SameSite chosen: // same_site: 'Strict' for maximum CSRF protection. May require users to login when arriving from external links., reference security policy or threat model justifying configuration, and note any known compatibility issues or workarounds required. Review configuration regularly: audit session.same_site during security reviews, update when application architecture changes (new OAuth integration requiring Lax), and reconsider when threat landscape evolves. Monitor session security: log authentication failures potentially related to SameSite configuration, track CSRF attacks to validate SameSite effectiveness, and collect metrics on user authentication patterns with configured SameSite. Infrastructure-as-code integration: Terraform/CloudFormation: pass SESSION_SAME_SITE as parameter to environment configuration, Kubernetes: define SESSION_SAME_SITE in ConfigMap, Docker Compose: set SESSION_SAME_SITE in environment section, and CI/CD: validate SESSION_SAME_SITE set correctly for target environment.

6

Test Cookie Behavior Across Different User Flows

Implement comprehensive testing verifying SameSite configuration provides security without breaking functionality, covering authentication flows, cross-site navigation, and third-party integrations. Manual testing procedures: test login flow: log in directly to application verifying session cookie has correct SameSite, test external links: arrive at application from external site (email, search results) confirming authentication state preserved appropriately, test OAuth/SSO: complete OAuth flow verifying authentication succeeds with configured SameSite, test embedded content: if application embeds in iframes, verify required functionality works, and test cross-site forms: confirm POST requests from external sites properly blocked. Automated browser testing: Laravel Dusk tests verifying SameSite behavior: $browser->visit('https://external.com')->clickLink('Go to app')->on('https://app.com')->assertAuthenticated(), test direct navigation: $browser->visit('https://app.com')->loginAs($user)->assertCookie('session')->assertCookieSameSite('session', 'Strict'), and test cross-site scenarios: simulate external site posting to application verifying cookies not sent. Unit tests for SameSite logic: test cookie creation functions include correct SameSite: assertEquals('Strict', $cookie->getSameSite()), verify helper methods apply appropriate SameSite for cookie types: assertEquals('Lax', $factory->preference('theme', 'dark')->getSameSite()), and validate configuration: assertEquals('Strict', config('session.same_site')). Integration tests for authentication: test complete login flow ending with correct SameSite cookies: $this->post('/login', $credentials)->assertCookie('session')->assertCookieSameSite('session', 'Strict'), test logout clearing cookies across SameSite values, and test session expiration with configured SameSite. Security testing: test CSRF protection: verify SameSite blocks cross-site POST requests, attempt cookie leakage: confirm SameSite prevents unauthorized cross-site cookie transmission, test subdomain isolation: validate cookies scoped correctly with SameSite and domain attributes, and penetration test: simulate attacks that SameSite should prevent. Cross-browser testing: test in Chrome verifying SameSite defaults and behavior, test in Firefox confirming compatibility, test in Safari (desktop and iOS) checking for quirks, and test in older browsers verifying graceful degradation. OAuth/SSO specific tests: test OAuth callback flow: verify SameSite configuration allows OAuth redirect to work, test SSO across domains: confirm single sign-on functions with configured SameSite, and test logout propagation: validate cross-domain logout works correctly. Performance testing: measure cookie transmission overhead with SameSite configured, test caching behavior with SameSite cookies, and verify CDN handling of SameSite cookies. Mobile testing: test mobile browsers (Chrome Mobile, Safari iOS) handling SameSite, test WebView components in mobile apps, and verify deep links to application handle SameSite cookies correctly. Create test matrix: document expected cookie behavior for each user flow, define pass/fail criteria for each test scenario, and maintain regression test suite for SameSite functionality. Continuous integration: include SameSite tests in CI pipeline, fail builds if cookies missing SameSite or using inappropriate values, and run cross-browser tests in automated testing infrastructure. Production monitoring: implement logging tracking SameSite-related failures, monitor authentication success rates after SameSite configuration changes, alert on anomalous cookie behavior suggesting SameSite misconfiguration, and collect user feedback on authentication/navigation issues. Document test cases: maintain test plan covering all SameSite scenarios, document known edge cases and their expected behavior, and provide troubleshooting guide for common SameSite-related issues.

Detect This Vulnerability in Your Code

Sourcery automatically identifies laravel cookie missing samesite attribute and many other security issues in your codebase.