I have been trying to figure out how to escape quotes (single and double) from shortcode attributes.

Basically the content is written by the user and therefore can potentially include " and ' quotes. Problem being, with " quotes it is stopping the shortcode attribute from functioning eg:

attibute="some text here with "quotes" so it stops the attribute...."

So instead of getting the entire string it is stopping at the second pair of quotes.

Now, I know it could be possible to set it up with single quotes but that leaves the same predicament if a user uses single quotes in the text.

I have looked at a variety of PHP/WP resolutions but I cant seem to get any of them to work, eg esc_html, htmlspecialchars, htmlentities.

Maybe I have set it up wrong or am not actioning the encoding at the right place.

This is currently what I am using (without encoding) as the shortcode (shortened a bit)

function aps_person_schema_shortcode( $atts, $content = null)   {

extract( shortcode_atts( array(     
            'aps_person_description' => ''
        ), $atts

$aps_person_return = '<div class="aps_person_container aps_container">';
$aps_person_return .= '<p class="aps_person_description" itemprop="description">' . $aps_person_description . '</p>';
$aps_person_return .= '</div>';

return $aps_person_return;

add_shortcode('aps_person', 'aps_person_schema_shortcode');

I've tried adding in after the extract array things like

$aps_person_description = esc_html($atts['aps_person_description']); 

but as the attribute is already broken (print_r displays that the string after the quote is separated into an array item for each word) escaping the string there doesnt work.

Tried it before the array and it doesn't work either I get a Notice: Undefined index

So, to clarify, how do you go about sanitizing user input for shortcode attribute data?

3 Answers 3


It seems you are working on the wrong end.

Try sanitizing the user input, for instance by means of sanitize_text_field, not the shortcode output.

  • 2
    Thanks! Though I didn't use the sanitize_textfield you led me back to where I needed to be. The input is added with jQuery so I added a .replace to change the quotes, not perfect but stops it from breaking.
    – Apina
    Mar 8, 2013 at 18:41

It turns out WordPress shortcode system uses function shortcode_parse_atts($text); to parse a shortcode entry to retrive attributes' names and values and store them in pairs in the array $atts, which is then passed to the shortcode function. So in your case adding escaping actions in the shortcode function like this:

$aps_person_description = esc_html($atts['aps_person_description']); 

will not work because shortcode_parse_atts() has already retrived attributes' names and values, and might have wrongly interpreted quotes in attributes' values.

To look closer, function shortcode_parse_atts() use this regex pattern:


to recognize attributes' names and values in the formats belows:

1. attr1="value1"
2. attr2='value2'
3. attr3=value3
4. "value4"
5. value5

So if a user puts quotes in values, it can easily go wrong. For example:

[my_shortcode dog='Santa's Little Helper' /]    
// $attr is Array ( [0] => dog='Santa's [1] => Little [2] => Helper' )
// should be Array ( [dog] => Santa's Little Helper )

Sanitizing after the parsing is obviously too late, what about sanitizing before the parsing? We will have to sanitize the entire entry since we don't have any attribute's values to work on yet. But this also causes problems, for example:

html_entities("[my_shortcode dog='Santa's Little Helper' /]", ENT_QUOTES);
// now entry is [my_shortcode dog=&#039;Santa&#039;s Little Helper&#039; /]
// after parsing: 
    [dog] => &#039;Santa&#039;s
    [0] => Little
    [1] => Helper&#039;

The paradox is: in order to make sure the parsing engine parses correctly, you have to sanitize the attributes values; but to do this you have to run the parsing engine first to get the values.

In conclusion, I think the reasonable way to make sure everything goes fine is to ensure users input attributes in proper formats, once users posted poorly formatted attributes, it will be a big headache. FYI, my experience is to make use of $content. In your case, I would put aps_person_description in the $content, it may look like this:

[my_shortcode]some text here with "quotes" so it stops the attribute....[/my_shortcode]

and quotes will be less a problem.

  • 2
    There's no paradox, it's a simple but significant flaw in shortcode_parse_atts(). That's just not how one should parse quoted attributes. Escape sequences are essential, you won't find a programming language without them. It should have had this built in from the start. Your example could be easily written as [my_shortcode dog='Santa\'s Little Helper' /] if the parser had a clue.
    – Walf
    Feb 27, 2015 at 2:51

I faced a similar issue printing out a PHP variable into a shortcode attribute. In my case, this value a taxonomy term name, not user-generated content, so there was no input to sanitize.

Using htmlentities() with the flag ENT_QUOTES allows strings including ' and " to be used as shortcode attributes. However, it also converts other characters to HTML entities, such as & into &amp;, which was not ideal for me.

To only convert ' and " characters into HTML entities, while not converting other characters like &:

htmlspecialchars_decode( htmlentities($value_to_print, ENT_QUOTES), ENT_NOQUOTES )

htmlspecialchars_decode() reverses all the HTML entities converted by htmlentities(). Using the flag ENT_NOQUOTES prevents ' & " characters from being converted back.

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.