d5DetectabilityOperational debt — how invisible misuse is to your safety net
Closest to 'specialist tool catches it' (d5). The detection_hints list phpstan, semgrep, and deptrac — these are specialist static analysis tools, not default linters. The code_pattern confirms they catch direct superglobal use in SQL/file paths or domain service classes, but this requires deliberate tool configuration and won't surface in a standard linter pass.
e5EffortRemediation debt — work required to fix once spotted
Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix says to filter at the controller boundary and pass clean values inward — but the common_mistakes show superglobals leaking into domain/service classes, session handling spread across many places, and direct use throughout the codebase. Introducing a request abstraction layer and pushing validation to the boundary while updating all call sites spans multiple files and components, landing solidly at e5.
b7BurdenStructural debt — long-term weight of choosing wrong
Closest to 'strong gravitational pull' (e7). The applies_to covers web, cli, and queue-worker contexts — all PHP contexts — and the why_it_matters explains that direct superglobal access 'creates hidden input coupling and makes testing harder' throughout the codebase. Every new feature and test strategy is shaped by whether superglobals are accessed directly or through an abstraction, and the common_mistakes show this pattern spreading into domain/service layers, giving it a strong gravitational pull across the whole application.
t7TrapCognitive debt — how counter-intuitive correct behaviour is
Closest to 'serious trap — contradicts how a similar concept works elsewhere' (t7). The misconception field is explicit: $_REQUEST appears to be a convenient safe shorthand for $_GET and $_POST, but it merges GET, POST, and COOKIE with configurable and manipulable precedence — the 'obvious' convenience alternative is subtly unsafe. Additionally, $_SERVER['HTTP_HOST'] looks like a server-controlled value but is user-controllable, contradicting typical developer intuition about server variables. These are documented gotchas that contradict reasonable assumptions about how similar input concepts behave.
About DEBT scoring →
scored by claude-sonnet-4-6 · 2026-05-11 · reviewed by human
PHP's built-in global arrays that provide access to request data, environment, and server variables — all potentially attacker-controlled.
Explanation
PHP superglobals ($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER, $_SESSION, $_ENV, $_REQUEST) are accessible in any scope without declaration. Critically, all data from HTTP requests ($_GET, $_POST, $_COOKIE, $_REQUEST, and many $_SERVER keys) is attacker-controlled and must be validated and sanitised before use. $_SERVER['HTTP_HOST'], $_SERVER['HTTP_REFERER'], and $_SERVER['HTTP_X_FORWARDED_FOR'] are trivially spoofed. Never trust superglobal data without validation, and avoid $_REQUEST which merges GET, POST, and cookies.
Common Misconception
✗ $_REQUEST is a convenient and safe alternative to $_GET and $_POST. $_REQUEST merges GET, POST, and COOKIE data — the precedence order is configurable and can be manipulated to override expected input sources. Always read from the explicit $_GET or $_POST superglobal.
Why It Matters
PHP superglobals ($_GET, $_POST, $_SERVER, $_SESSION) are accessible everywhere without declaration — accessing them directly throughout the codebase creates hidden input coupling and makes testing harder.
Common Mistakes
Reading $_GET/$_POST directly in domain or service classes — those layers should receive already-validated data.
Trusting $_SERVER['HTTP_HOST'] for security decisions — it is user-controlled.
Modifying $_SESSION directly in many places instead of through a session service — hard to trace and test.
Not filtering and validating superglobal values at the application boundary before passing them inward.
Avoid When
Never use $_REQUEST — it merges GET, POST, and COOKIE, making the input source ambiguous.
Do not use extract($_GET) or extract($_POST) — it overwrites arbitrary variables with user-controlled values.
When To Use
Access $_GET, $_POST, $_SERVER through a request abstraction layer rather than directly — makes testing and sanitisation consistent.
Always validate and sanitise superglobal values before use — they contain raw user input.
Code Examples
✗ Vulnerable
// Superglobals accessed deep in domain logic:
class OrderService {
public function create(): Order {
$userId = $_SESSION['user_id']; // Coupled to HTTP context
$items = $_POST['items']; // Should be injected, not read directly
}
}
✓ Fixed
// PHP superglobals — always available, all scopes
// $_GET — URL query params
// $_POST — HTTP POST body (form data)
// $_COOKIE — HTTP cookies
// $_FILES — uploaded file metadata
// $_SERVER — server and request info
// $_SESSION — session data (after session_start())
// $_ENV — environment variables
// $_REQUEST — merged GET+POST+COOKIE (avoid — ambiguous)
// $GLOBALS — all global variables
// Safe access pattern:
$page = max(1, (int) ($_GET['page'] ?? 1));
$email = filter_var($_POST['email'] ?? '', FILTER_VALIDATE_EMAIL) ?: '';
// JSON API body:
$body = json_decode(file_get_contents('php://input'), true) ?? [];
🧱FUNDAMENTALS— new to this? Start with the ground floor.
$_GET superglobalphp$_GET is a built-in PHP array that holds values passed to your script through the URL's query string (the part after the ?).
Almost every PHP page reads user input, and query-string parameters are the simplest, most common form. Understanding $_GET is the first step to building search, pagination, and shareable links.
💡 Always check with isset() and escape with htmlspecialchars() before displaying anything from $_GET.
$_POST superglobalphp$_POST is a built-in PHP array that holds data sent to your script from an HTML form submitted with method="post". Each form field becomes a key in that array.
Almost every PHP app that accepts user input — logins, signups, checkouts, comments — reads from $_POST. Understanding it is the gateway to handling forms safely.
💡 Never trust $_POST directly: check it exists, validate the value, and escape it on output.
PHPphpA server-side scripting language that generates web pages and APIs — the code runs on the server, and only its output (usually HTML or JSON) reaches the browser.
PHP is often the first server-side language people meet, and understanding its execution model — script starts fresh on every request, no memory between requests — explains most of how the web backend works: sessions, databases, and caching all exist to bridge that per-request amnesia.
💡 Start with PHP 8.x, declare(strict_types=1), and PDO — skip any tutorial that mentions mysql_query().
RequestgeneralA request is a message sent from a client (like your browser) to a server, asking for something—a webpage, data, or an action to be performed.
Every web interaction begins with a request. Understanding requests lets you control what data your code receives, validate user input, and build features that respond to what users actually ask for.
💡 Always check if request data exists with isset() before using it—never assume the data arrived.
Never use superglobal values directly in business logic — filter and validate at the controller boundary using filter_input() or a validation library, then pass clean values to services