Title: Common Vulnerabilities
Author: theMikeD
Published: November 20, 2022
Last modified: January 7, 2025

---

# Common Vulnerabilities

## In this article

 * [Types of Vulnerabilities](https://developer.wordpress.org/apis/security/common-vulnerabilities/?output_format=md#types-of-vulnerabilities)
    - [SQL Injection](https://developer.wordpress.org/apis/security/common-vulnerabilities/?output_format=md#sql-injection)
    - [Cross Site Scripting (XSS)](https://developer.wordpress.org/apis/security/common-vulnerabilities/?output_format=md#cross-site-scripting-xss)
    - [Cross-site Request Forgery (CSRF)](https://developer.wordpress.org/apis/security/common-vulnerabilities/?output_format=md#cross-site-request-forgery-csrf)
    - [Staying Current](https://developer.wordpress.org/apis/security/common-vulnerabilities/?output_format=md#staying-current)

[ Back to top](https://developer.wordpress.org/apis/security/common-vulnerabilities/?output_format=md#wp--skip-link--target)

Security is an ever-changing landscape, and vulnerabilities evolve over time. The
following is a discussion of common vulnerabilities you should protect against, 
and the techniques for protecting your theme from exploitation.

## 󠀁[Types of Vulnerabilities](https://developer.wordpress.org/apis/security/common-vulnerabilities/?output_format=md#types-of-vulnerabilities)󠁿

### 󠀁[SQL Injection](https://developer.wordpress.org/apis/security/common-vulnerabilities/?output_format=md#sql-injection)󠁿

SQL injection happens when values being inputted are not properly sanitized allowing
for any SQL commands in the inputted data to potentially be executed. To prevent
this, the WordPress API is extensive, offering functions like `add_post_meta();`
instead of you needing to adding the post meta manually via SQL (`INSERT INTO wp_postmeta…`).

![exploits_of_a_mom](https://i0.wp.com/make.wordpress.org/docs/files/2013/03/exploits_of_a_mom.
png?ssl=1)

xkcd [Exploits of a Mom](https://xkcd.com/327/)

The first rule for hardening your theme against SQL injection is: When there’s a
WordPress function, use it.

But sometimes you need to do complex queries, that have not been accounted for in
the API. If this is the case, always use the [`$wpdb` functions](https://developer.wordpress.org/reference/classes/wpdb/).
These were built specifically to protect your database.

All data in SQL queries must be SQL-escaped before the SQL query is executed to 
prevent against SQL injection attacks. The best function to use for SQL-escaping
is `$wpdb->prepare()` which supports both a [sprintf()](http://secure.php.net/sprintf)-
like and [vsprintf()](http://secure.php.net/vsprintf)-like syntax.

    ```php
    $wpdb->get_var( $wpdb->prepare(
        "SELECT something FROM table WHERE foo = %s and status = %d",
        $name, // an unescaped string (function will do the sanitization for you)
        $status // an untrusted integer (function will do the sanitization for you)
    ) );
    ```

### 󠀁[Cross Site Scripting (XSS)](https://developer.wordpress.org/apis/security/common-vulnerabilities/?output_format=md#cross-site-scripting-xss)󠁿

Cross Site Scripting (XSS) happens when a nefarious party injects JavaScript into
a web page.

Avoid XSS vulnerabilities by escaping output, stripping out unwanted data. As a 
theme’s primary responsibility is outputting content, a theme should [escape dynamic content](https://developer.wordpress.org/themes/theme-security/data-sanitization-escaping/)
with the proper function depending on the type of the content.

An example of one of the escaping functions is escaping URL from a user profile.

    ```php
    <img src="<?php echo esc_url( $great_user_picture_url ); ?>" />
    ```

Content that has HTML entities within can be sanitized to allow only specified HTML
elements.

    ```php
    $allowed_html = array(
        'a' => array(
            'href' => array(),
            'title' => array()
        ),
        'br' => array(),
        'em' => array(),
        'strong' => array(),
    );

    echo wp_kses( $custom_content, $allowed_html );
    ```

### 󠀁[Cross-site Request Forgery (CSRF)](https://developer.wordpress.org/apis/security/common-vulnerabilities/?output_format=md#cross-site-request-forgery-csrf)󠁿

Cross-site request forgery or CSRF (pronounced sea-surf) is when a nefarious party
tricks a user into performing an unwanted action within a web application they are
authenticated in. For example, a phishing email might contain a link to a page that
would delete a user’s account in the WordPress admin.

If your theme includes any HTML or HTTP-based form submissions, use a [nonce](https://developer.wordpress.org/apis/security/nonces/)
to guarantee a user intends to perform an action.

    ```php
    <form method="post">
        <!-- some inputs here … -->
        <?php wp_nonce_field( 'name_of_my_action', 'name_of_nonce_field' ); ?>
    </form>
    ```

### 󠀁[Staying Current](https://developer.wordpress.org/apis/security/common-vulnerabilities/?output_format=md#staying-current)󠁿

It is important to stay current on potential security holes. The following resources
provide a good starting point:

 * [WordPress Security Whitepaper](https://wordpress.org/about/security/)
 * [WordPress Security Release](https://wordpress.org/news/category/security/)
 * [Open Web Application Security Project (OWASP) Top 10](https://www.owasp.org/index.php/OWASP_Top_Ten_Cheat_Sheet)

First published

November 20, 2022

Last updated

January 7, 2025

[  Previous: User Roles and Capabilities](https://developer.wordpress.org/apis/security/user-roles-and-capabilities/)

[  Next: Example](https://developer.wordpress.org/apis/security/example/)