Global Variables Analyzer
| Analyzer ID | Category | Severity | Time To Fix |
|---|---|---|---|
global-variables | ✅ Reliability | Medium | 15 minutes |
What This Checks
- Detects reads from PHP superglobals:
$_GET,$_POST,$_REQUEST,$_COOKIE,$_SESSION,$_SERVER,$_FILES,$GLOBALS,$_ENV— writes to superglobals (e.g.$_SERVER['HTTPS'] = 'on') are intentionally not flagged as they have no Laravel equivalent - Detects
filter_input()andfilter_input_array()calls that bypass Laravel's request validation - Detects the
globalkeyword (global $var;) which imports hidden global state - Detects discouraged session functions:
session_start(),session_destroy(),session_id(),session_regenerate_id(),session_name(),session_unset(),session_write_close(),session_abort(),session_reset()— note:session_status()is intentionally excluded as it is a read-only diagnostic - Detects discouraged header/response functions:
header(),header_remove(),http_response_code(),setcookie(),setrawcookie()— note:headers_sent()andheaders_list()are intentionally excluded as they are read-only diagnostics - Detects discouraged environment functions:
getenv()(Medium severity),putenv()(High severity — mutates the process environment globally) - Suggests the correct Laravel alternative for each detected pattern
- Context-aware exclusions: automatically skips middleware, kernel files, console commands, bootstrap files, and
routes/console.php
Why It Matters
- Testability: Superglobals are difficult to mock in unit tests, making code that uses them harder to verify
- Security: Direct superglobal access bypasses Laravel's request validation, sanitization, and CSRF protection
- Portability: Code tightly coupled to superglobals cannot be reused in Artisan commands, queued jobs, or other non-HTTP contexts
- Consistency: Mixing native PHP functions with Laravel abstractions leads to unpredictable behavior (e.g.,
session_start()conflicts with Laravel's session middleware) - Caching: Using
getenv()orputenv()outside of config files breaksphp artisan config:cache, causing hard-to-diagnose production issues - Process safety:
putenv()mutates the environment globally, corrupting state across Octane/Horizon workers and affecting third-party packages
How to Fix
Quick Fix (5 minutes)
Replace superglobals with their Laravel equivalents:
php
// ❌ BAD - Direct superglobal access
$name = $_GET['name'];
$email = $_POST['email'];
$token = $_COOKIE['token'];
$host = $_SERVER['HTTP_HOST'];
$avatar = $_FILES['avatar'];
$value = $GLOBALS['setting'];
$dbHost = $_ENV['DB_HOST'];
// ✅ GOOD - Laravel request helpers
$name = request()->query('name');
$email = request()->post('email');
$token = request()->cookie('token');
$host = request()->server('HTTP_HOST');
$avatar = request()->file('avatar');
$value = app('setting'); // or dependency injection
$dbHost = config('database.connections.mysql.host');Replace filter_input() with Laravel validation:
php
// ❌ BAD - filter_input
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
// ✅ GOOD - Laravel validation
$validated = request()->validate([
'email' => 'required|email',
]);
$email = $validated['email'];Replace native session functions:
php
// ❌ BAD - Native session functions
session_start();
$_SESSION['user'] = $userId;
session_destroy();
// ✅ GOOD - Laravel session helpers
session(['user' => $userId]);
session()->flush();
session()->invalidate();Proper Fix (15 minutes)
1: Use Form Request Classes for Input Validation
php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreUserRequest extends FormRequest
{
public function rules(): array
{
return [
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users',
'avatar' => 'nullable|image|max:2048',
];
}
}php
// Controller uses type-hinted Form Request
public function store(StoreUserRequest $request): RedirectResponse
{
$validated = $request->validated();
// All input is validated and safe
$user = User::create($validated);
if ($request->hasFile('avatar')) {
$user->updateAvatar($request->file('avatar'));
}
return redirect()->route('users.show', $user);
}2: Replace Header Functions with Response Methods
php
// ❌ BAD - Native header functions
header('Content-Type: application/json');
header('X-Custom-Header: value');
setcookie('preference', 'dark', time() + 86400);
http_response_code(200); // success code
http_response_code(404); // error code
// ✅ GOOD - Laravel response
return response()->json($data)
->header('X-Custom-Header', 'value')
->cookie('preference', 'dark', 1440);
// ✅ GOOD - http_response_code() replacements
return response('', 200); // success codes: use response()
abort(404); // error codes (4xx/5xx): use abort()3: Replace Environment Functions with Config
php
// ❌ BAD - getenv / putenv
$apiKey = getenv('API_KEY');
putenv('TEMP_VAR=value');
// ✅ GOOD - Use config() everywhere except config files
// In config/services.php:
'api_key' => env('API_KEY'),
// In application code:
$apiKey = config('services.api_key');ShieldCI Configuration
To exclude certain files that legitimately need superglobal access, publish the config:
bash
php artisan vendor:publish --tag=shieldci-configThen in config/shieldci.php:
php
return [
'analyzers' => [
'reliability' => [
'enabled' => true,
'global-variables' => [
'exclude_paths' => [
'app/Legacy/*',
'app/ThirdParty/*.php',
],
],
],
],
];References
- Laravel HTTP Requests
- Laravel Form Request Validation
- Laravel Session
- Laravel HTTP Responses
- Laravel Configuration
Related Analyzers
- Cache Prefix Configuration Analyzer - Ensures shared cache backends use unique prefixes
- Composer Validation Analyzer - Ensures composer.json is valid and follows best practices
- Env Variables Complete Analyzer - Verifies all required environment variables are set