You would use it like this:
<?php the_title(); ?>
the_title
is responsible for its own escaping, much like the_content
. It’s the same with any filters that try to use it, they should perform escaping on anything they add.
In fact, I can run JS such as alert(“test”); if I place that in the post title.
This is because you are either a super admin on a multisite or an administrator role on a non-multisite, these gain the unfiltered_html
bypassing all sanitising on save. This is why you can put raw script tags in posts, other users cannot, and this capability is disabled on a lot of enterprise hosts as it’s a security concern. I recommend that you disable/remove it, though be aware that if you as a super admin depend on it, a non-super admin who tries to save that post will find the title/content sanitised and your tags disappear when they save as they won’t have that capability.
Having said that, it has nothing to do with escaping, your title could contain script tags, and escaping would still print them, but the tags would be escaped and they would be visible to people reading them on the frontend rather than executed/seen as actual tags.
So instead:
- Use
the_title()
as is, to directly output the title - Or, if you’re concerned that the user has the
unfiltered_html
capability, useecho esc_html( get_the_title(
Note though that the title is used in many other places though such as OEmbed and SEO tags, as well as the title tag, it may be easier to eliminate the unfiltered_html
capability, and I recommend you do this if only as a security measure.
I have tried (1)
<?php esc_html(the_title('<h1>','</h1>'))?>
This failed for multiple reasons that have nothing to do with WordPress but highlight missing information about PHP basics
- There’s no
echo
! So if it worked it wouldn’t print anything the_title
does not return a value by default, it outputs directly
This means that the code is the same as this:
echo esc_html('');
the_title('<h1>','</h1>');
Also tried (2)
<h1><?php echo esc_html(the_title);</h1>
with the same result
This is better as it includes an echo
but you’ve asked it to escape the function itself, not the posts title, this is almost equivalent to this:
echo esc_html( function the_title() { .... } );
Which will likely result in a PHP warning like this:
Warning: Uncaught Error: Object of class Closure could not be converted to string in...
Important things to note for the future:
- Check first but a general rule of thumb is that
the_...
will output directly without anecho
, andget_the
orget_
requires anecho
statement and an escaping function. - Functions beginning with
the_
tend to do their own escaping internally - Don’t double escape!
esc_html( esc_html(
is very bad and can let stuff leak through if it’s crafted right - calling a function involves
()
somewhere, you can’t apply escaping like a modifier or buff by callingescape(function_name)
- escape as late as you possibly can, ideally at the moment of output
- avoid gathering HTML bits in a variable then printing it at the end, it makes it super super hard to escape stuff properly
- don’t escape input, that’s what sanitising and validating are for, escaping is only for output
- Do not try to use
esc_js
andesc_sql
they don’t do what they appear to do and have very specific internal uses.wpdb->prepare
should cover all SQL related escaping, andwp_json_encode
can prepare data for javascript so you don’t have to construct it out of strings when showing the page