Safeguard
Security Guides•

WordPress escaping: esc_html, esc_attr, esc_url and escaping late

Which WordPress escaping function fits which output context, when to reach for wp_kses, and why the handbook says to escape as late as possible.

Safeguard Security Team
2 min read

In WordPress, escape every value at the moment you print it, using the function that matches the context: esc_html inside elements, esc_attr in attributes, esc_url for links, and wp_kses when you must keep some HTML. The handbook calls this escaping late.

Why escape at output

Cross-site scripting happens when untrusted text reaches a page as markup. The WordPress security guidance lists these principles: never trust user input, escape as late as possible, escape everything from untrusted sources including your own database, and never assume anything. It also says validation or rejection is better than sanitizing.

Pick the function by context

The escaping page gives this mapping:

  • esc_html(): Text inside an HTML element, strips HTML
  • esc_attr(): HTML attributes and most other output
  • esc_url(): All URLs, including src and href
  • esc_url_raw(): URLs stored in the database or needed unencoded
  • esc_js(): Inline JavaScript
  • esc_textarea(): Text inside a textarea
  • esc_xml(): XML blocks
  • wp_kses(): Untrusted HTML that keeps markup, with an allowlist of tags and attributes
  • wp_kses_post(): Shortcut for the HTML allowed in post content

An example

echo '<a href="' . esc_url( $link ) . '" title="' . esc_attr( $title ) . '">'
   . esc_html( $label ) . '</a>';

Each value uses a different function because each sits in a different context.

Why late

The handbook gives reasons: code is easier to review, a variable cannot change between escaping and output, automated scanners can see it, and maintainers understand it faster. If you cannot escape late, for instance when output contains scripts that wp_kses() would strip, escape while building the string and name the variable with a suffix such as _escaped, _safe or _clean. Functions that cannot escape late should return safe HTML.

Common mistakes

  • Escaping on input and printing raw later.
  • Using esc_html inside an attribute.
  • Echoing a database value because you wrote it yourself.
  • Using wp_kses_post where esc_html would do.

Quick check

If I sanitized the value on save, do I still escape on output?

Yes. The guidance says to escape everything from untrusted sources, including the database, at output.

When do I use wp_kses instead of esc_html?

When users may legitimately include some HTML. Pass an allowlist of tags and attributes.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.