Thoughts on “Too Much Escaping” in WordPress

Hey there! I'm currently working on a CLI tool to deploy WordPress apps to DigitalOcean. Check it out! It's free and open source.

While sanitizing and escaping everything is very important when dealing with websites, I think there are times when we need to back off a little bit, and trust the functions that have been given to us by WordPress.

<a href="<?php echo esc_url( get_permalink( get_the_ID() ) ); ?>" title="<?php echo esc_attr( sprintf( __( 'Permanent Link to %s', 'domain' ), the_title_attribute( array( 'echo' => false ) ) ) ); ?>" >

I call that paranoia (and I see it in a lot of themes.) Dirty, difficult to read and understand, and even more difficult to spot an error. The permalink and the title attribute are never going to break out of the attributes syntax and escaping them a billion times doesn’t really help. Here’s a cleaner version for comparison:

<a href="<?php the_permalink(); ?>" title="<?php the_title_attribute( array( 'before' => __( 'Permanent link to ', 'domain' ) ) ); ?>" >

Quite straightforward and easy to understand. You don’t even need to worry about escaping the “before” text, because the_title_attribute will escape it for you. One might argue that explicit escaping (right at the output) is more secure than implicit escaping, but since functions prefixed with the_ are meant for output, I tend to trust their output. You just need to know where each one should go.

With that said, if you have a super hi-jacked WordPress installation with a malicious plugin overwriting the output of the functions mentioned above, there’s really not much you can do. Even if you triple espace with get_permalink, a plugin might just filter in onĀ post_link and output whatever it needs to output by-passing all escaping.


About the author

Konstantin Kovshenin

WordPress Core Contributor, ex-Automattician, public speaker and consultant, enjoying life in Moscow. I blog about tech, WordPress and DevOps.


  • There are tons of programmers out there afraid their plugin will be the next exploit so they over kill it. Which just slows down performance..

    And yes, if they already got the code injected it doesn’t matter what your plugin does.. It’s already in..

  • Yes, i see this also often; but the authors of themes use the default themes as standard, maybe TwentyEleven and this themes have this code, that you use as bad example.
    I hope the authors read your post and change his source for an better performance and also for better to read as developer.

  • Although I agree that there is too much escaping these days, in second part of your example you’re missing a point, surprisingly since you’re non-English speaker.

    Problem with the_ functions is that they are English centric. They offer options to add before and after texts that works fine in English, but don’t in all other languages. Other language might have different text direction, word ordering, grammatical cases etc. That’s why we have placeholders so that translators can organize sentence to better suite their language. And that is the reason why it needs escaping, since translator might add unwanted content.

    So better version of your example would be:

    <a href="" title="" >

    • Hey Milan, your code got eaten up for some reason, but you did make a point in your comment, however I don’t see why you can’t use both before and after arguments of the_title_attribute. If, however, you still prefer to use sprintf with esc_attr then using get_the_title instead of the_title_attribute will be much cleaner, since you’re escaping the whole thing anyway, why do it twice?

      And that is the reason why it needs escaping, since translator might add unwanted content.

      I’ll disagree here. Translations strings are in files that you upload and store on your server, just like theme or plugin files. If a plugin or theme can output unescaped HTML, I don’t see why a translation file shouldn’t.

      The purpose of escaping in this particular case, is to prevent the translator from accidentally breaking out of the attribute markup by using a quote in their translation. In other cases you’ll just print it as is, and even pass whole chunks of HTML to translators. The tags and comments output of Twenty Eleven illustrate this.

      Thanks for stopping by to comment and if you can try and paste your code again (maybe Gist?) I’ll edit your comment :)