# Superglobals: $_GET, $_POST, $_FILES and More

> PHP superglobals explained: what $_GET, $_POST, $_FILES, $_SERVER and others contain, how PHP fills them before your code and how to use request data safely.

Source: https://phpsos.de/en/php/superglobals/  
As of: 25/10/2026  
Provider: PHP SOS, PHP emergency help and server security. Immediate help via WhatsApp: https://wa.me/491736494914?text=Hello%20PHP%20SOS%2C%20we%20need%20help%20with%20our%20PHP%20server.%20Company%3A%20%E2%80%A6%20Website%3A%20%E2%80%A6

**In short:** Superglobals are predefined arrays that PHP fills automatically on every request and that are available everywhere in the code. `$_GET` contains the parameters from the address, `$_POST` the form data, `$_FILES` uploaded files, `$_COOKIE` the cookies and `$_SERVER` details about the request and server. PHP creates these arrays before your application code starts. That is why flaws in exactly this processing, as with PHP2Shell, cannot be caught by checks in the application.

## What are superglobals?

In PHP, a variable normally applies only within the function in which it was created. Superglobals are the exception: they are available in every scope without having to fetch them with `global`. The PHP manual lists nine of them.

For non-technical readers this can be described as follows: the superglobals are the application's mailbox. Everything a visitor sends lands there before the application reads it. And everything in the mailbox potentially comes from a stranger.

## The superglobals at a glance

| Superglobal | Content | Origin |
|---|---|---|
| `$_GET` | parameters from the address (query string) | client |
| `$_POST` | form fields of a POST request | client |
| `$_FILES` | details of uploaded files | client, prepared by PHP |
| `$_COOKIE` | cookies sent along by the browser | client |
| `$_REQUEST` | mixture of GET, POST and possibly cookies | client |
| `$_SERVER` | request headers, method, paths, server details | web server and client mixed |
| `$_ENV` | environment variables | server |
| `$_SESSION` | data of the current session | server storage |
| `$GLOBALS` | all global variables | script |

`$_SERVER` is particularly tricky. According to the manual, PHP creates an entry beginning with `HTTP_` for every request header, such as `HTTP_USER_AGENT`. The client sets these values itself. According to the manual, `SERVER_NAME` can also contain the hostname supplied by the client and is not reliable for security decisions.

## How PHP fills the superglobals

Before the first character of your script is executed, PHP has already been at work. It reads the address, the headers and the content of the request, breaks them down and places the results in the arrays. Several settings control this step:

1. **`variables_order`** (default `EGPCS`) determines which superglobals are created at all: Environment, GET, POST, Cookie, Server.
2. **`request_order`** (default empty) determines what `$_REQUEST` is built from. If it is empty, `variables_order` applies. According to the manual, the php.ini files shipped with PHP leave cookies out for security reasons.
3. **`max_input_vars`** (default `1000`) and **`max_input_nesting_level`** (default `64`) limit the number and nesting depth of input variables.
4. **`post_max_size`** (default `8M`) limits the request body. If a request is larger, `$_POST` and `$_FILES` remain empty.
5. **`enable_post_data_reading`** (default on) controls whether PHP automatically evaluates the content of POST requests at all.

If `enable_post_data_reading` is switched off, the application reads the raw content itself via `php://input`. Since PHP 8.4.0 there is additionally `request_parse_body()`, which also evaluates form and upload data for methods other than POST and allows its own limits. How the upload part works in detail is explained on the page [How PHP processes file uploads](https://phpsos.de/en/php/datei-uploads-intern/).

## Handling request data safely

The principle is simple: every value from `$_GET`, `$_POST`, `$_COOKIE`, `$_FILES` and the `HTTP_` entries of `$_SERVER` is external input. It is validated on acceptance and escaped appropriately on output.

```php
<?php
declare(strict_types=1);

// Integer expected: validate instead of converting blindly
$seite = filter_var($_GET['seite'] ?? '1', FILTER_VALIDATE_INT, [
    'options' => ['min_range' => 1, 'max_range' => 500],
]);
if ($seite === false) {
    http_response_code(400);
    exit('Ungültige Seitenzahl');
}

// Allow only permitted values
$sortierung = in_array($_GET['sort'] ?? '', ['name', 'datum'], true)
    ? $_GET['sort']
    : 'datum';

// Always escape output
echo htmlspecialchars($_POST['kommentar'] ?? '', ENT_QUOTES, 'UTF-8');
```

A frequent stumbling block is information about where a request came from. If a reverse proxy, a load balancer or a CDN sits in front of the web server, `$_SERVER['REMOTE_ADDR']` contains the address of that intermediary, not that of the visitor. The real address is then in a header such as `X-Forwarded-For`, which any client can set itself, though. The application may evaluate such headers only if the request demonstrably comes from its own known proxy. Otherwise, blocks by IP address or logs can easily be deceived. The same applies to `HTTPS`: if encryption ends at the proxy, the application must explicitly know that the original connection was encrypted.

Further patterns for validation and filtering are shown in the article [Validating and filtering input in PHP](https://phpsos.de/en/blog/eingaben-validieren-php/). Session data in `$_SESSION` follows its own rules; they are on the page [Sessions and cookies in PHP](https://phpsos.de/en/php/sessions-und-cookies/).

## Superglobals and PHP2Shell: what happens before your code

This is where the link to the current situation lies. [CVE-2026-109618](https://phpsos.de/en/php2shell/cve-2026-109618/) describes how an out-of-memory condition can interrupt PHP while request data is only partially initialised; during the clean-up of the request, invalid data can then be treated as valid. With CVE-2026-109619, internal state of a request can persist after its memory has been released and be used by a later request in the same worker.

Both flaws therefore lie in the processing that PHP itself performs around the request, not in the application code. The PHP team rates the risk highest for mod_php; an exploit was demonstrated there before any application code runs. No `filter_var()` and no check in the application can prevent that.

> **Act now:**
> The update to PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35 and the restart of all PHP processes are mandatory. The interim measures from php.net, such as tighter limits for `post_max_size`, are not complete protection.

## How does PHP SOS help?

- We check the effective limits for request data per website and set them to suit the application.
- We install the PHP update, restart all workers and document the patch level as part of our [PHP patch service](https://phpsos.de/en/leistungen/php-patch-service/).
- We examine custom developments to see whether values from superglobals reach the database, file system or output unchecked.
- We secure the web server logs from 20 October 2026 onwards so that later analysis remains possible.


## Frequently asked questions

**How many superglobals are there in PHP?**  
The PHP manual lists nine: $GLOBALS, $_SERVER, $_GET, $_POST, $_FILES, $_COOKIE, $_SESSION, $_REQUEST and $_ENV. They are available in every scope, including inside functions and methods.

**Can the values in $_SERVER be trusted?**  
Only partly. Entries beginning with HTTP_ come from the client's request headers. The manual warns, for example, that SERVER_NAME can reflect the hostname supplied by the client and is not reliable for security decisions.

**Why is $_POST sometimes empty even though a form was submitted?**  
The most common cause is a request larger than post_max_size. In that case, according to the manual, $_POST and $_FILES remain empty. Switching off the setting enable_post_data_reading has the same effect.

**Should I use $_REQUEST?**  
Better not. $_REQUEST mixes data from different sources, and which source wins depends on request_order and variables_order. Read values specifically from $_GET or $_POST.

## Sources

- [PHP Manual: Superglobals](https://www.php.net/manual/de/language.variables.superglobals.php)
- [PHP Manual: $_SERVER](https://www.php.net/manual/en/reserved.variables.server.php)
- [PHP Manual: php.ini Directives](https://www.php.net/manual/de/ini.core.php)
- [PHP Manual: request_parse_body](https://www.php.net/manual/en/function.request-parse-body.php)
