RSTR-XSS-006 — PHP echo / print of request superglobal
Summary
A PHP page writes $_GET[...], $_POST[...], $_REQUEST[...], or
$_COOKIE[...] directly into the HTTP response via echo, print,
or the short-echo <?= ?> form. No HTML escaping in between — the
attacker's input is parsed as HTML in the page's origin, yielding
reflected (and sometimes stored) XSS.
Severity
High.
Languages
PHP.
What rastray flags
<?php echo $_GET['name']; ?> <!-- ← flagged -->
<?php print "Hello " . $_POST['name']; ?> <!-- ← flagged -->
<p><?= $_REQUEST['msg'] ?></p> <!-- ← flagged -->
What rastray deliberately does not flag
-
Values run through
htmlspecialchars(...)first:<?= htmlspecialchars($_GET['name'], ENT_QUOTES, 'UTF-8') ?>The regex deliberately requires the superglobal to appear before any opening
(on the line, so function-wrapped uses are excluded. -
Values rendered through Twig / Blade / Smarty templates with auto-escaping on.
How to fix it
Always escape on output. The canonical helper for HTML context is
htmlspecialchars with ENT_QUOTES and an explicit charset:
<p>Hello, <?= htmlspecialchars($_GET['name'], ENT_QUOTES, 'UTF-8') ?>!</p>
For an attribute, the same call works because ENT_QUOTES escapes
both single and double quotes:
<a href="<?= htmlspecialchars($_GET['url'], ENT_QUOTES, 'UTF-8') ?>">link</a>
For URL contexts (only the path / query of a URL):
<a href="/search?q=<?= rawurlencode($_GET['q']) ?>">search</a>
For JavaScript contexts (a value embedded inside an inline <script>):
<script>
const user = <?= json_encode($_GET['user'], JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) ?>;
</script>
If your project uses a template engine (Twig, Blade), prefer those: auto-escape is on by default and the per-call helper disappears.