A common security mistake I see WordPress plugin authors (and PHP coders in general) make is using
$_SERVER['REQUEST_URI'] as the action of a form or part of an anchor’s
href attribute. This is not safe to do, and opens your code up to XSS (cross-site scripting) exploits.
<form action="<?php echo $_SERVER['PHP_SELF']; ?>">
<a href="<?php echo $_SERVER['PHP_SELF']' ?>?foo=bar">link title</a>
Here are my two rules regarding
$_SERVER['REQUEST_URI'] in forms:
- Do not use them
- If you use one of them, escape it with
Most uses of
$_SERVER['REQUEST_URI'] are in HTML forms. If you want the
action attribute to point to the current URL, leave it blank. URI references that are blank point to the current resource.
If you do want to specify the action (and there are good reasons for wanting to do that, such as stripping the query string from the current URL), you must run it through
<form action="<?php echo esc_url( $_SERVER['PHP_SELF'] ); ?>">
The same applies to links… run the
href attribute through
<a href="<?php echo esc_url( $_SERVER['PHP_SELF'] . '?foo=bar' ); ?>">link title</a>
A quick search through the WordPress Plugin Directory showed that this problem is far too common.
Examples of URLs that could exploit this for double-quoted actions:
And single-quoted actions:
No, just using a plain old
htmlentities() wrapper is not going to help! That’s still vulnerable to XSS in certain situations. If you’re not using WordPress, you should copy the WordPress escaping functions (just remove the
If you are using the
base tag, Safari will apply that base to the blank
action attribute. So if you use the
base tag (I never do), a blank
action isn’t going to be for you. Use what you’ve been using, but escape it.
Lester Chan has a handy snippet for the form action of WordPress plugin settings pages:
<form action="<?php echo admin_url( 'admin.php?page=' . plugin_basename( __FILE__ ) ); ?>">
admin_url() takes care of escaping for you, and is an easy way to create a full WP admin URL from a