The WordPress Codex says:
It's important to note that most WordPress functions properly prepare
the data for output, and you don't need to escape again.
For example the_permalink()
already escapes the output with:
echo esc_url( apply_filters( 'the_permalink', get_permalink( $post ), $post ) );
so you don't need to do that yourself here. But the get_the_permalink()
function doesn't:
return get_permalink( $post, $leavename );
Neither does the get_permalink()
function:
return apply_filters( 'post_link', $permalink, $post, $leavename );
They are not specific display functions.
WordPress uses filters all around the code base, to make it possible for themes and plugins to adjust the output of various core functions. Here are some possible (edge case) examples:
add_filter( 'post_link', function( $link )
{
return get_option( 'some_url' );
}, PHP_INT_MAX );
or even:
add_filter( 'post_link', function( $link )
{
return get_post_meta( 1, 'some_url', true );
}, PHP_INT_MAX );
So if we are displaying the output of get_permalink()
directly, we should escape it with e.g.
<a href="<?php echo esc_url( get_permalink() );?>">...</a>
But in general I think it would be better to escape the output of a core function if we don't know how it handles it, but it shouldn't be too much work to just check it out.