I have a custom theme. I want to output the post title of my post. I have achieved this already by using <h1><?php the_title();?></h1>
. However, some say this is not escaped. In fact, I can run JS such as <script>alert("test");</script>
if I place that in the post title. I have tried (1) <?php esc_html(the_title('<h1>','</h1>'))?>
but it runs the aforementioned JS as well and does not output any HTML. Also tried (2) <h1><?php echo esc_html(the_title);</h1>
with the same result as (1).
Happy New Year! /dfr
I have a custom theme. I want to output the post title of my post. I have achieved this already by using <h1><?php the_title();?></h1>
. However, some say this is not escaped. In fact, I can run JS such as <script>alert("test");</script>
if I place that in the post title. I have tried (1) <?php esc_html(the_title('<h1>','</h1>'))?>
but it runs the aforementioned JS as well and does not output any HTML. Also tried (2) <h1><?php echo esc_html(the_title);</h1>
with the same result as (1).
Happy New Year! /dfr
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:
the_title()
as is, to directly output the titleunfiltered_html
capability, use echo 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
echo
! So if it worked it wouldn't print anythingthe_title
does not return a value by default, it outputs directlyThis 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:
the_...
will output directly without an echo
, and get_the
or get_
requires an echo
statement and an escaping function.the_
tend to do their own escaping internallyesc_html( esc_html(
is very bad and can let stuff leak through if it's crafted right()
somewhere, you can't apply escaping like a modifier or buff by calling escape(function_name)
esc_js
and esc_sql
they don't do what they appear to do and have very specific internal uses. wpdb->prepare
should cover all SQL related escaping, and wp_json_encode
can prepare data for javascript so you don't have to construct it out of strings when showing the page