Skip to content
Back to all articles
WordPress6 min readSeptember 30, 2026

WordPress Security Functions Every Developer Should Know

Sanitize, validate, escape, nonces and capabilities: the handful of WordPress functions that prevent most plugin and theme vulnerabilities, with real examples.

WordPress Security Functions Every Developer Should Know article
In this guide
  1. The mental model: trust nothing that crosses a boundary
  2. Habit 1: Sanitize input
  3. Habit 2: Escape output
  4. Habit 3: Verify intent with nonces
  5. Habit 4: Check capabilities
  6. Putting it together: a safe settings handler
  7. Database queries
  8. Mistakes reviewers catch again and again
  9. Quick reference
  10. Building it in from the start
  11. Four habits, most problems solved

Most WordPress security problems do not come from clever attackers breaking WordPress itself. They come from small gaps in themes and plugins: a form that trusts whatever is submitted, a value printed straight onto the page, a settings screen any logged-in user can reach. Each gap is usually one missing function call. The frightening part is how ordinary the code looks; the reassuring part is how few functions you need to close most of them.

This guide covers the handful of WordPress functions that prevent the majority of vulnerabilities, grouped into four simple habits: sanitize what comes in, escape what goes out, verify intent with nonces, and check permissions. Each comes with a real example.

The mental model: trust nothing that crosses a boundary

Data changes hands at boundaries: when a visitor submits a form, when a URL parameter is read, when a value from the database is printed into HTML, when an AJAX request arrives. At each boundary, ask two questions:

  • Coming in: is this data what I expect, and is it safe to store?
  • Going out: could this data break the HTML, JavaScript or URL it is placed into?

WordPress provides a function for each situation. Using them consistently is most of the job.

Habit 1: Sanitize input

Sanitizing cleans data as it arrives, before you store or use it. Pick the function that matches what the value should be:

FunctionUse for
sanitize_text_field()Single-line text, such as names and titles
sanitize_textarea_field()Multi-line plain text
sanitize_email()Email addresses
absint()IDs and other non-negative whole numbers
sanitize_key()Lowercase keys and slugs
esc_url_raw()URLs you are about to save
wp_kses_post()HTML that should allow only safe post formatting

Values from $_POST and $_GET may be slashed, so unslash them first:

php
$name = isset( $_POST['name'] ) ? sanitize_text_field( wp_unslash( $_POST['name'] ) ) : '';
$email = isset( $_POST['email'] ) ? sanitize_email( wp_unslash( $_POST['email'] ) ) : '';
$post_id = isset( $_GET['post'] ) ? absint( $_GET['post'] ) : 0;

Sanitizing is not the same as validating. After cleaning, check the value makes sense: is the email address valid according to is_email(), is the ID a post that exists, is the option one of the allowed choices?

Habit 2: Escape output

Escaping happens at the moment you print data, and it depends on where the data is going. This is the defence against cross-site scripting (XSS), where malicious script ends up running in someone else's browser.

FunctionUse when printing into
esc_html()Normal HTML text
esc_attr()An HTML attribute value
esc_url()An href or src
esc_js()Inline JavaScript strings
wp_kses_post()Content that may contain safe HTML formatting
php
<a href="" title="">

The golden rule is escape late: escape right where you echo, even if you believe the value was sanitized earlier. Code changes, data sources change, and late escaping keeps each output safe on its own.

Habit 3: Verify intent with nonces

A nonce is a token that proves a request came from your own form, protecting against cross-site request forgery (CSRF), where another website tricks a logged-in user's browser into submitting a request. Add one to every form that changes something:

php

<button type="submit">Save</button>

And check it before processing:

php
if ( ! isset( $_POST['acme_nonce'] )
|| ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['acme_nonce'] ) ), 'acme_save_settings' ) ) {
wp_die( esc_html__( 'Security check failed.', 'acme' ) );
}

For AJAX, create the nonce with wp_create_nonce(), send it with the request, and check it with check_ajax_referer().

Habit 4: Check capabilities

A nonce proves the request came from your form. It does not prove the person is allowed to do the action. Always pair it with a capability check:

php
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'You do not have permission to do this.', 'acme' ) );
}

Choose the capability that matches the action: manage_options for site settings, edit_posts for content editing, edit_post with an ID for a specific post. For REST API routes, put the check in the permission_callback, and never use __return_true for anything that changes data.

Putting it together: a safe settings handler

php
function acme_handle_settings() {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'Not allowed.', 'acme' ) );
}
check_admin_referer( 'acme_save_settings', 'acme_nonce' );

$title = isset( $_POST['acme_title'] )
? sanitize_text_field( wp_unslash( $_POST['acme_title'] ) )
: '';
update_option( 'acme_title', $title );

wp_safe_redirect( admin_url( 'options-general.php?page=acme&updated=1' ) );
exit;
}
add_action( 'admin_post_acme_save', 'acme_handle_settings' );

Every habit appears here: permission check, nonce check, sanitized input, and a safe redirect followed by exit, which is easy to forget and important, because a redirect only sends a header and the code would otherwise keep running.

Database queries

Prefer WordPress's own functions, like get_posts(), WP_Query and update_option(), which handle safety for you. When you genuinely need a custom SQL query, always use $wpdb-&gt;prepare() with placeholders instead of putting variables directly into the query. That single habit prevents SQL injection.

Mistakes reviewers catch again and again

  • Escaping on input instead of output. Storing esc_html()-encoded text in the database leads to double-encoded characters later. Sanitize on the way in, escape on the way out.
  • Using the wrong escaping function, such as esc_html() inside an href. A URL needs esc_url(), an attribute needs esc_attr().
  • Trusting data from your own database. If a user could have written it, treat it as untrusted when you print it.
  • Checking a nonce but not a capability, or the other way round. You almost always need both.
  • Forgetting exit after a redirect, so the rest of the handler still runs.

Quick reference

The WordPress Functions Reference covers the core security functions from this guide, including sanitize_text_field(), absint(), esc_html(), esc_attr(), esc_url(), wp_kses_post(), the nonce functions and current_user_can(), alongside the most-used functions for queries, hooks, assets, registration and caching, each with a short working example and a link to its official documentation. Press / to jump to the search box and type a task, such as "nonce" or "escape".

Building it in from the start

Security is much easier to build in than to bolt on. When you start a new plugin, the WordPress Plugin Generator produces a structure with prefixed names, escaped output and a settings page built on the Settings API, which handles nonces for you. Our guide to creating your first WordPress plugin walks through it step by step. Before launch, the WordPress Security Checker is a useful final review of your site's configuration.

If you work with AI assistants while coding, avoid pasting real credentials, keys or customer data into the chat; our guide to using ChatGPT without sharing personal data explains a safe workflow.

Four habits, most problems solved

Sanitize what comes in. Escape what goes out, as late as possible. Verify intent with nonces. Check permissions every time. None of these functions is complicated, and once they become habits, you will find yourself spotting the gaps in other people's code too, which is exactly how good WordPress developers think.

Was this article helpful?

Found this guide useful?

Share it with someone who is struggling with the same problem.

Free tool ยท No sign-up

WordPress Functions Reference

Search 49 essential WordPress functions by name or task. Each one has a plain-English description, parameters, return value, a copy-ready example and a link to the official docs.

Open tool
Toolyconvert Team profile photo

Written by

Toolyconvert Team

Web Development & Software Engineering Team

The Toolyconvert Team builds, maintains, and improves free online tools designed to make everyday digital tasks faster and easier. Our team works across web development, software engineering, APIs, performance optimization, testing, and user experience to create reliable and practical tools.