⚠️ Critical Security Warning
The technique described below involves temporarily disabling a core WordPress security feature called KSES. KSES (Kses Strips Evil Scripts) is what filters out malicious code like JavaScript, iframe tags, and other potentially dangerous HTML when content is saved.
Do NOT use this solution if:
- You are taking content from an untrusted source (like a public form).
- The user creating the post does not have the
unfiltered_htmlcapability (typically only granted to Administrators/Super Admins).
Proceed with extreme caution and only if you fully understand the security trade-offs!
The Problem: WordPress Filters Your HTML
Back in WordPress version 3.6 (and similar versions), developers often ran into an issue when programmatically inserting posts using wp_insert_post(). Even if the post content was created by a trusted source or a custom script, WordPress would aggressively strip certain HTML tags (like script, iframe, and even some div attributes) as a security measure.
This is because the KSES filters are attached to the post-saving hooks to ensure safe data. To insert raw, unfiltered HTML, you must temporarily remove these filters.
The WordPress 3.6 Workaround
The solution I found—and wanted to share for those still dealing with this scenario—is to use the procedural functions kses_remove_filters() and kses_init_filters() to create a very small window where the post can be inserted without filtering.
These functions essentially control the global registration of the filters that clean post data, title data, and comment data.
The Code Snippet
Here is the exact pattern to use when you execute your post insertion:
// 1. **REMOVE FILTER:**
// Temporarily remove all KSES security filters from WordPress save hooks.
kses_remove_filters();
// 2. **INSERT POST:**
// Execute the function to insert the post with the $args array.
// The post content will now be saved without KSES scrubbing.
$post_id = wp_insert_post( $args );
// 3. **RESTORE FILTER:**
// Immediately re-attach the KSES security filters to restore
// the default security measures for subsequent saves.
kses_init_filters();
if ( is_wp_error( $post_id ) ) {
// Handle error...
} else {
// Post inserted successfully...
}Code language: PHP (php)
Why This Works (and Why It’s Risky)
The functions perform the following actions:
kses_remove_filters(): Detaches the primary sanitization functions (wp_filter_post_kses,wp_filter_kses, etc.) from the action hooks that fire just before a post is saved (content_save_pre,excerpt_save_pre, etc.).wp_insert_post(): The post data is inserted into the database while no sanitization filters are active on the content fields.kses_init_filters(): Re-attaches all the original sanitization functions, immediately restoring WordPress’s security defaults for all future data submissions.
By using this pattern, you contain the risk to only the single wp_insert_post() execution, ensuring that the security filters are active again immediately afterward.
