Yes! You should always be escaping
Escape Late, Escape Often
Escaping is about intent, if you intend to output a URL, use
esc_url, and it will definately be a URL ( if the data is malicious it will be made safe )
What I still wonder is should I always use esc_attr in HTML fields, or example the input fields of a contact form? And should I always use esc_url for all my own urls, for example image src paths?
If it's a hardcoded URL? E.g.
"http://example.com" ? No, we know it's safe
If it's a URL from a function or some other source? E.g.
echo get_permalink() or
Yes, you should escape there's no way to know if it's safe
If it's a function that outputs internally and doesn't require an
echo statement? E.g.
the_permalink()? No there's no way to escape this, the function needs to escape internally. Output buffers can be used in emergencies, but that path leads to madness
And what about the_title()? Should I use one of these escapes to all echos in my code or only where there are possible input from users?
There's no way to escape a function that outputs internally.
the_title should be good to use, as are the others
With 1 Exception
Avoid this function at all costs, for security reasons.
bloginfo doesn't always escape internally, and as it outputs internally there's no way to add escaping.
get_bloginfo and escape the result, e.g.
<a href="<?php echo esc_url( get_bloginfo( 'site' ) ); ?>">
get_bloginfo returns rather than outputs the value, allowing us to use escaping functions.
A Brief Note on Filters
Sometimes you want to pass things through a filter, such as
the_content, but escaping the result will strip out tags.
For example, this will strip any embedded videos present:
echo wp_kses_post( apply_filters( 'the_content', $stuff ) );
The solution is instead to do this:
echo apply_filters( 'the_content', wp_kses_post( $stuff ) );
The idea being that we know the input is safe, therefore the output must be safe. This assumes that any code running on that filter also escapes accordingly. Do this for these situations with WP Core filters, but avoid needing this in your own filters and code as much as possible