I'm using custom instances of wp_editor(); to allow rich text editing of Post Meta associated with a Post Object.

I'd like to perform much of the same sanitization that occurs with post_content for the values of these fields.

Here's what I've come up with:

Please let me know if this is an okay approach, or if there is more I should be doing in either of these three steps, or if there's a better or easier way.

On save_post:

$value = wp_filter_post_kses( sanitize_post_field( 'post_content', $value, 0, 'db' ) );

Passing Value to wp_editor();:

$value = wp_unslash( sanitize_post_field( 'post_content', $value, 0, 'edit' ) );

Outputting Value on Frontend:

$value = wp_unslash( sanitize_post_field( 'post_content', $value, 0, 'display' ) );

2 Answers 2


wp_kses to the rescue!

My Editor Contains everything a Post Might

Pass the result through wp_kses_post on the way in and out, and all should be good.

Remember, this will strip out anything added by the_content filter, so to preserve oembeds and shortcodes, use this:

echo apply_filters( 'the_content', wp_kses_post( $content ) );

You might also want esc_textarea for outputting the form if you're using <textarea> tags directly

My Editor contains text, but no markup

On output, esc_html is your friend. Use this for situations when you have a text area that will never contain markup. On input, try wp_strip_all_tags on input to sanitise. The other WP APIs will make sure no SQL injections occur

My Editor contains markup, but a limited subset

wp_kses to the rescue, pass it through wp_kses along with a second parameter, an array defining what tags and attributes are allowed. E.g.:

$allowed = [
    'a' => [
        'href' => [],
        'title' => []
    'br' => [],
    'em' => [],
    'strong' => [],

echo wp_kses( $content, $allowed );

Be wary though of overextending. If you add script and iframe tags, is there really any point in using wp_kses?


wp_editor outputs internally, it can't be escaped, therefore it is responsible for escaping itself. Do not try to be unhelpful by passing it pre-escaped content, this can lead ot mangled output and double escaping ( a great way for malformed content to bypass escaping ).

The function that outputs has the responsibility for escaping. This enables late escaping. Escaping earlier or multiple times is dangerous and introduces new complex problems, as you no longer know with certainty what is or isn't escaped.


I think you're on the right track.

The sanitize_post_field() function calls the content_save_pre hook which, when given the DB context, will also call the wp_filter_post_kses function so there's no need to wrap it/call it again.

As far as I can tell at this point once it's been saved to the database we don't need to unslash anything for display. Here's what I have which is fairly similar to what you already had:

Saving Value

update_post_meta( $post->ID, '_test', sanitize_post_field( 'post_content', $_POST['_test'], $post->ID, 'db' ) );

Passing Value

$editor_content = get_post_meta( $post->ID, '_test', true );

wp_editor( $editor_content, 'editor_id_here', array(
    'textarea_name' => '_test',
) );

Displaying Value

$editor_content     = get_post_meta( $post->ID, '_test', true );
$display_content    = apply_filters( 'the_content', $display_content );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.