I'm writing a plug-in that stores UNIX datetimes in browser cookies and that also uses a $_POST variable based on a simple form that sends the ID number of the current WordPress post.

After reading several articles and posts on sanitization and validation in WordPress and PHP, I haven't found any that deal much or at all with handling cookie data in this way, though I have read statements (at this very site) seeming to suggest that a simple $_POST variable set programmatically via a hidden field probably wouldn't need to be validated or escaped.


Using JSON, the plugin sets and decodes the three cookies, all of which contain simple arrays with the Post-ID as key and the UNIX datetime as value. In addition to being compared to each other in conditionals, the datetimes are sometimes converted and displayed.

Now, on NetBeans, I get a "Do Not Access Superglobal COOKIE Array Directly" warning every time the code uses the COOKIE variable, even when I'm just checking whether it's set, as follows:

if (isset($_COOKIE['new_session'])) {

(Yes, I'm aware that you can also enable $_SESSION for WordPress if you want to via plug-in or other code - I decided against that route, but could still be persuaded to change my mind if someone gives me a reasons to do so!)

I also get the warning when I extract the data - for instance here:

$prev_visit = json_decode( stripslashes( $_COOKIE['prev_visit'] ), true );

EDIT: The UNIX datetime is accessed as a value from the resultant $prev_visit array. So, to get the datetime, we use $prev_visit[$id], with $id being the WP Post-ID number derived either directly or indirectly (in the second case via $_POST variable as below) from get_the_ID(), and serving as key.


As for the $_POST data, it's created, as I said, via a simple form: User presses a button, hidden input sends Wordpress Post ID number as the "mark-all-read" value. Key lines:

$id = get_the_ID();

and, within the PHP creating the button/form:

$mark-all-read-button .= '<input type="hidden" name="mark-all-read" value="' . $id . '" />';

On the next refresh (action added to "init'), we check if 'mark-all-read' is set, and, if it is, we use the $id to set keys for the above-mentioned cookies [EDIT:] as in the more general example above. (This is what I meant by "indirectly" using the ID# derived via get_the_ID().)

I don't know if this was the best way to go about achieving my objectives in this plug-in, but it works pretty well so far. Before I share it with the world, however, I want to know whether it's safe to use.


So, do we need to validate and/or sanitize superglobals as used above, and, if so, how exactly?

  • 2
    "... a simple $_POST variable set programmatically via a hidden field probably wouldn't need to be validated or escaped" - The hidden inputs can be modified directly in the HTML form and it's possible to construct an evil POST payload that would exploit fields that are not validated/sanitized.
    – birgire
    Sep 5, 2015 at 17:11

1 Answer 1


Without reading the question, just from the title, the answer is YES. Any input from the outside world should be validated and sanitized where appropriate, and this include inpude the server recieves the fact that it might have been generated in a form you designed is irrelevant. Input should never be trusted.

Now about internal consistency. After you already validate and sanitized the input fields you should check that the data makes sense in the context you expect to handle it. If you expect a post id of a post then you need to check not only that it actually exists but also that it is not a page. This is really just another aspect of validation... and the sooner you do it in your code path and more detailed your error message is the easier your life will be.

So how exactly to do it? There is no recipe, different contexts require different validation and sanitation. It is probably better to start as strict as you can and then relax checks only if you have too.

  • 1
    I appreciate the response, but I tried to provide the specific contexts above: isset, json_decode, and hidden $_POST variable originally derived via get_the_ID(), isset'd, and utilized as key in new simple cookie array - all variables integers, either UNIX datetimes or Post-ID numbers. The only directly usable indications I have found so far is to use absint() or intval() or possibly array_map('absint',$array) with the above. Will that suffice? Doesn't seem to have anything to do with the issets- or are they in fact irrelevant?
    – CK MacLeod
    Sep 5, 2015 at 17:09
  • no, the only relevant context is what your application should do and we have no idea from your question (and it would probably have been too long for the Q&A format). technical mambo jambo is relevant only when coding, not when discussing principals. You first need to decide what is a valid input and only then decide how to write the code to validate it. Sep 5, 2015 at 17:36
  • if you want to validate post id, then you first need to check it is an integer, then that it is positive, then do a get_post and validate its type. you can do intval etc, but if get_post validates it for you then you might skip the integer validation. so the validation very much depends on what you do and which WP API you are going to use. The higher level APIs will probably do some validation and sanitation for you, but lower level ones will require more work on your side. Sep 5, 2015 at 17:44
  • Thanks for your patience, and I'm sorry if the question was unclear, but the WP Post-ID, after being derived via get_the_ID() as above, is not used in any other way other than to provide a key in the simple array, with UNIX datetime as the value, that is json_encoded and added (or set) in the cookie. This allows extraction of the value after the cookie is decoded as an array.
    – CK MacLeod
    Sep 5, 2015 at 18:00
  • edited Question to illustrate how the ID is used and the datetime value extracted.
    – CK MacLeod
    Sep 5, 2015 at 18:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.