Yoast SEO Plugin Authenticated, Stored XSS Vulnerability

The “snippet preview” functionality of the Yoast WordPress SEO plugin was susceptible to cross-site scripting in versions before 2.2 (<= 2.1.1). This vulnerability appears to have been reported 2 years ago by someone named “badconker”, but the plugin author said that it was already patched. Unfortunately, it appears that this is not the case. If you are running this plugin, I recommend updating to the latest version.

Yoast WordPress SEO XSS in action

Yoast WordPress SEO XSS in action

Vulnerable URL:

/wp-admin/post-new.php?post_title=<img src=x onerror=alert(1)>

Vulnerable Code (wordpress-seo/js/wp-seo-metabox.js):

function yst_clean(str) {
    	if (str == '' || str == undefined)
		    return '';

	    try {
		        str = jQuery('<div/>').html(str).text();
		        str = str.replace(/<\/?[^>]+>/gi, '');
		        str = str.replace(/\[(.+?)\](.+?\[\/\\1\])?/g, '');
	    } catch (e) {

	return str;

Link )

function sanitize_title( title ) {
    	// Run possibly set filters
    	title = wpseo_apply_filter( title, 'title');

    	title = yst_clean(title);

    	// and now the snippet preview title
    	title = yst_boldKeywords(title, false);

    	return title;

( Link )

The vulnerable part is on line 6 of wordpress-seo/js/wp-seo-metabox.js where the yst_clean function passes the “str” parameter to the jQuery .html() function, then tries to get the text from that object. This means that any HTML will be executed when it is passed through the sanitization function.

It seems the fix introduced in 2.2 was to move the .html() call below the regex replacements:

	try {
    		str = str.replace( /<\/?[^>]+>/gi, '' );
    		str = str.replace( /\[(.+?)](.+?\[\/\\1])?/g, '' );
    		str = jQuery( '<div/>' ).html( str ).text();

Link )

One Reply to “Yoast SEO Plugin Authenticated, Stored XSS Vulnerability”

  1. I have been used this plugin, but switched to All in one SEO. Great alternative, maybe even better then Yoast.


Leave a Reply

Your email address will not be published. Required fields are marked *