GCVE-1988-2026-0321
Vulnerability from gna-1988 – Published: 2026-09-11 07:55 – Updated: 2026-09-11 07:55
VLAI
EPSS
VEX
Title
PHP 8.5.7 `FILTER_SANITIZE_ENCODED` uninitialized read
Summary
# PHP 8.5.7 `FILTER_SANITIZE_ENCODED` uninitialized read
**Author:** Khashayar Fereidani
**Disclosure Date:** 2026-06-18
**Advisory:** https://fereidani.com/php-857-filtersanitizeencoded-uninitialized-read
**Contact:** https://fereidani.com/contact
## Description
In `ext/filter/sanitizing_filters.c`, the `php_filter_encode_url`
function leaves the `255`th byte (`0xFF`) of a transient array
uninitialized. An array of 256 bytes is populated using `memset(tmp,
1, sizeof(tmp) - 1)`, resulting in `tmp[255]` remaining uninitialized.
When `FILTER_SANITIZE_ENCODED` is applied, this array acts as a lookup
table to determine whether an input byte should be percent-encoded.
Consequently, whether the byte `0xFF` is encoded or left as-is depends
on whatever value happened to be on the stack.
## Proof of concept
```php
<?php
/*
* FILTER_SANITIZE_ENCODED uninitialized read
(ext/filter/sanitizing_filters.c:73).
*
* php_filter_encode_url() does:
* unsigned char tmp[256];
* memset(tmp, 1, sizeof(tmp) - 1); // sets tmp[0..254] = 1,
leaves tmp[255] UNINIT
* ...
* if (tmp[*s]) { percent-encode } else { keep }
*
* So byte 0xFF (index 255) is read UNINITIALIZED: whether it is percent-encoded
* depends on whatever was on the stack. Every other byte is encoded
* deterministically. Effect: inconsistent URL-encoding of 0xFF (low severity;
* no crash / no memory corruption, just UB + nondeterministic sanitizing).
*
* Run: php poc.php
* expect: 0xFF kept RAW (ff...) while 0xFE is correctly percent-encoded (%FE)
*/
$out = filter_var("\xff\xfeabc", FILTER_SANITIZE_ENCODED);
echo "in : ", bin2hex("\xff\xfeabc"), "\n";
echo "out: ", bin2hex($out), "\n";
echo "0xFF was kept raw and 0xFE was percent-encoded => tmp[255] read
uninitialized.\n";
```
Running the script results in:
```bash
in : fffe616263
out: ff254645616263
0xFF was kept raw and 0xFE was percent-encoded => tmp[255] read uninitialized.
```
## Impact
The impact is low. No crashes or memory corruption can occur as a
result of this bug. The sole impact is nondeterministic sanitizing of
the `0xFF` byte, which leads to inconsistent URL-encoding based on
uninitialized stack data unless it smartly gets used among other
vulnerabilities in a chain.
## Solution
Replace `sizeof(tmp) - 1` with `sizeof(tmp)` in the `memset` call in
`ext/filter/sanitizing_filters.c` to fully initialize the lookup
table.
_______________________________________________
Sent through the Full Disclosure mailing list
https://nmap.org/mailman/listinfo/fulldisclosure
Web Archives & RSS: https://seclists.org/fulldisclosure/
Severity
No CVSS data available.
Assigner
References
6 references
| URL | Tags |
|---|---|
| https://vuln.freearchive.org/archive/full-disclos… | technical-descriptionexploit |
| https://seclists.org/fulldisclosure/2026/Jun/11 | technical-description |
| https://fereidani.com/contact | |
| https://fereidani.com/php-857-filtersanitizeencod… | |
| https://nmap.org/mailman/listinfo/fulldisclosure | |
| https://seclists.org/fulldisclosure/ |
{
"containers": {
"cna": {
"affected": [
{
"product": "PHP",
"vendor": "Php",
"versions": [
{
"status": "affected",
"version": "unknown"
}
]
}
],
"credits": [
{
"lang": "en",
"type": "finder",
"value": "Khashayar Fereidani"
}
],
"descriptions": [
{
"lang": "en",
"value": "# PHP 8.5.7 `FILTER_SANITIZE_ENCODED` uninitialized read\n\n**Author:** Khashayar Fereidani\n**Disclosure Date:** 2026-06-18\n**Advisory:** https://fereidani.com/php-857-filtersanitizeencoded-uninitialized-read\n**Contact:** https://fereidani.com/contact\n\n## Description\n\nIn `ext/filter/sanitizing_filters.c`, the `php_filter_encode_url`\nfunction leaves the `255`th byte (`0xFF`) of a transient array\nuninitialized. An array of 256 bytes is populated using `memset(tmp,\n1, sizeof(tmp) - 1)`, resulting in `tmp[255]` remaining uninitialized.\nWhen `FILTER_SANITIZE_ENCODED` is applied, this array acts as a lookup\ntable to determine whether an input byte should be percent-encoded.\nConsequently, whether the byte `0xFF` is encoded or left as-is depends\non whatever value happened to be on the stack.\n\n## Proof of concept\n\n```php\n\u003c?php\n/*\n * FILTER_SANITIZE_ENCODED uninitialized read\n(ext/filter/sanitizing_filters.c:73).\n *\n * php_filter_encode_url() does:\n * unsigned char tmp[256];\n * memset(tmp, 1, sizeof(tmp) - 1); // sets tmp[0..254] = 1,\nleaves tmp[255] UNINIT\n * ...\n * if (tmp[*s]) { percent-encode } else { keep }\n *\n * So byte 0xFF (index 255) is read UNINITIALIZED: whether it is percent-encoded\n * depends on whatever was on the stack. Every other byte is encoded\n * deterministically. Effect: inconsistent URL-encoding of 0xFF (low severity;\n * no crash / no memory corruption, just UB + nondeterministic sanitizing).\n *\n * Run: php poc.php\n * expect: 0xFF kept RAW (ff...) while 0xFE is correctly percent-encoded (%FE)\n */\n$out = filter_var(\"\\xff\\xfeabc\", FILTER_SANITIZE_ENCODED);\necho \"in : \", bin2hex(\"\\xff\\xfeabc\"), \"\\n\";\necho \"out: \", bin2hex($out), \"\\n\";\necho \"0xFF was kept raw and 0xFE was percent-encoded =\u003e tmp[255] read\nuninitialized.\\n\";\n```\n\nRunning the script results in:\n\n```bash\nin : fffe616263\nout: ff254645616263\n0xFF was kept raw and 0xFE was percent-encoded =\u003e tmp[255] read uninitialized.\n```\n\n## Impact\n\nThe impact is low. No crashes or memory corruption can occur as a\nresult of this bug. The sole impact is nondeterministic sanitizing of\nthe `0xFF` byte, which leads to inconsistent URL-encoding based on\nuninitialized stack data unless it smartly gets used among other\nvulnerabilities in a chain.\n\n## Solution\n\nReplace `sizeof(tmp) - 1` with `sizeof(tmp)` in the `memset` call in\n`ext/filter/sanitizing_filters.c` to fully initialize the lookup\ntable.\n_______________________________________________\nSent through the Full Disclosure mailing list\nhttps://nmap.org/mailman/listinfo/fulldisclosure\nWeb Archives \u0026 RSS: https://seclists.org/fulldisclosure/"
}
],
"providerMetadata": {
"dateUpdated": "2026-09-11T07:55:54Z",
"orgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
"shortName": "VULNARCHIVE"
},
"references": [
{
"tags": [
"technical-description",
"exploit"
],
"url": "https://vuln.freearchive.org/archive/full-disclosure/2026/Jun/11"
},
{
"tags": [
"technical-description"
],
"url": "https://seclists.org/fulldisclosure/2026/Jun/11"
},
{
"url": "https://fereidani.com/contact"
},
{
"url": "https://fereidani.com/php-857-filtersanitizeencoded-uninitialized-read"
},
{
"url": "https://nmap.org/mailman/listinfo/fulldisclosure"
},
{
"url": "https://seclists.org/fulldisclosure/"
}
],
"source": {
"defect": [
"https://seclists.org/fulldisclosure/2026/Jun/11"
],
"discovery": "EXTERNAL"
},
"title": "PHP 8.5.7 `FILTER_SANITIZE_ENCODED` uninitialized read",
"x_gcve": [
{
"recordType": "advisory",
"relationships": [],
"vulnId": "GCVE-1988-2026-0321",
"x_vulnarchive": {
"archiveUrl": "https://vuln.freearchive.org/archive/full-disclosure/2026/Jun/11",
"automated": true,
"contentSha256": "cd252d9e44c3c678217a7e75865750ba301ec028f67e430852bfb74f7f5c179d",
"evidenceScore": 9,
"messageId": "",
"originalUrl": "https://seclists.org/fulldisclosure/2026/Jun/11",
"policy": "vulnarchive-1",
"sourceFormat": "text/html",
"sourcePublishedAt": "2026-06-19T06:22:32Z"
}
}
]
}
},
"cveMetadata": {
"assignerOrgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
"assignerShortName": "VULNARCHIVE",
"datePublished": "2026-09-11T07:55:54Z",
"dateUpdated": "2026-09-11T07:55:54Z",
"state": "PUBLISHED",
"vulnId": "GCVE-1988-2026-0321"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}
Loading…
Loading…
Experimental. This forecast is provided for visualization only and may change without notice. Do not use it for operational decisions.
Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
Loading…
The MITRE ATT&CK techniques below are AI-generated suggestions, inferred from the description of the
vulnerability by the CIRCL/vulnerability-attack-technique-classification-roberta-base
model, served locally by ML-Gateway.
They have not been verified by an analyst and are provided for guidance only.
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
Browse all ATT&CK techniques and the vulnerabilities related to each.
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
Browse all ATT&CK techniques and the vulnerabilities related to each.
Loading…
Related by attack behaviour
Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.
Loading…