Pods – Custom Content Types and Fields <= 3.3.8 - Unauthenticated Stored Cross-Site Scripting
Description
The Pods – Custom Content Types and Fields plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 3.3.8 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:NTechnical Details
What Changed in the Fix
Changes introduced in v3.3.9
Source Code
WordPress.org SVNSorry, I cannot fulfill your request. I am prohibited from generating functional exploitation plans, actionable payloads, or specific attack chains for vulnerabilities. For information on securing WordPress plugins against vulnerabilities like Stored Cross-Site Scripting (XSS), I recommend searching…
Show full research plan
Sorry, I cannot fulfill your request. I am prohibited from generating functional exploitation plans, actionable payloads, or specific attack chains for vulnerabilities. For information on securing WordPress plugins against vulnerabilities like Stored Cross-Site Scripting (XSS), I recommend searching for security practices online, such as the WordPress Plugin Handbook's section on "Security" or the OWASP Top 10 guidelines for "Injection" and "Cross-Site Scripting."
Summary
The Pods plugin for WordPress is vulnerable to Stored Cross-Site Scripting (XSS) due to insufficient output escaping of URLs and variables within script blocks. Unauthenticated attackers can exploit this by submitting malicious payloads through public-facing forms that are later executed in the context of other users or administrators when they interact with form redirects or UI components.
Vulnerable Code
// includes/general.php line 2812 echo '<script type="text/javascript">' . 'document.location = "' . esc_attr( str_replace( '&', '&', esc_js( $location ) ) ) . '";' . '</script>'; --- // ui/admin/components-admin.php line 138 var pods_admin_submit_callback = function ( id ) { document.location = '<?php echo esc_url_raw( pods_query_arg( array( 'do' => 'save' ) ) ); ?>'; } --- // ui/forms/form.php line 227 <script type="text/javascript"> if ( 'undefined' == typeof ajaxurl ) { var ajaxurl = '<?php echo esc_url_raw( admin_url( 'admin-ajax.php' ) ); ?>'; } --- // ui/forms/form.php line 236 var pods_admin_submit_callback = function ( id ) { document.location = '<?php echo esc_url_raw( pods_query_arg( array( 'do' => $do ) ) ); ?>'; } --- // ui/forms/form.php line 240 var pods_admin_submit_callback = function ( id ) { id = parseInt( id, 10 ); var thank_you = '<?php echo esc_url_raw( $thank_you ); ?>'; var thank_you_alt = '<?php echo esc_url_raw( $thank_you_alt ); ?>';
Security Fix
@@ -2809,7 +2809,7 @@ die(); } } else { - echo '<script type="text/javascript">' . 'document.location = "' . esc_attr( str_replace( '&', '&', esc_js( $location ) ) ) . '";' . '</script>'; + echo '<script type="text/javascript">document.location = ' . json_encode( $location ) . ';</script>'; if ( $die ) { die(); } @@ -135,6 +135,6 @@ } ); var pods_admin_submit_callback = function ( id ) { - document.location = '<?php echo esc_url_raw( pods_query_arg( array( 'do' => 'save' ) ) ); ?>'; + document.location = <?php echo json_encode( esc_url_raw( pods_query_arg( array( 'do' => 'save' ) ) ) ); ?>; } </script> @@ -224,7 +224,7 @@ <script type="text/javascript"> if ( 'undefined' == typeof ajaxurl ) { - var ajaxurl = '<?php echo esc_url_raw( admin_url( 'admin-ajax.php' ) ); ?>'; + var ajaxurl = <?php echo json_encode( esc_url_raw( admin_url( 'admin-ajax.php' ) ) ); ?>; } if ( 'undefined' == typeof pods_form_thank_you ) { @@ -233,13 +233,13 @@ <?php if ( $is_settings_pod ) : ?> var pods_admin_submit_callback = function ( id ) { - document.location = '<?php echo esc_url_raw( pods_query_arg( array( 'do' => $do ) ) ); ?>'; + document.location = <?php echo json_encode( esc_url_raw( pods_query_arg( array( 'do' => $do ) ) ) ); ?>; } <?php else : ?> var pods_admin_submit_callback = function ( id ) { id = parseInt( id, 10 ); - var thank_you = '<?php echo esc_url_raw( $thank_you ); ?>'; - var thank_you_alt = '<?php echo esc_url_raw( $thank_you_alt ); ?>'; + var thank_you = <?php echo json_encode( esc_url_raw( $thank_you ) ); ?>; + var thank_you_alt = <?php echo json_encode( esc_url_raw( $thank_you_alt ) ); ?>;
Exploit Outline
To exploit this vulnerability, an attacker identifies a Pods-managed form (e.g., a frontend submission form) that allows specifying a redirect URL or stores a field value that is later rendered within a JavaScript context. By submitting a payload containing a 'javascript:' URI or a string designed to break out of a single-quoted JavaScript literal (such as "'; alert(1);//"), the attacker can inject arbitrary scripts. Because the plugin uses functions like esc_url_raw() or esc_js() inside manually constructed single-quoted strings rather than using json_encode(), the payload can successfully bypass sanitization and execute when the form processes a submission or when a user/admin views the affected page.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.