Catch Import Export - Insecure deserialization
Summary
Name | Catch Import Export trun - Insecure deserialization |
Code name | skims-0061 |
Product | Catch Import Export |
Affected versions | Version trun |
State | Private |
Release date | 2025-03-14 |
Vulnerability
Kind | Insecure deserialization |
Rule | Insecure deserialization |
Remote | No |
CVSSv4 Vector | CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:N/VI:L/VA:L/SC:N/SI:N/SA:N/E:U |
CVSSv4 Base Score | 1.7 (Low) |
Exploit available | No |
CVE ID(s) | CVE-2025-31321 |
Description
Catch Import Export trun was found to be vulnerable. Unvalidated user input is used directly in an unserialize function in myapp/admin/class-catch-import-export-ad min.php.
Vulnerability
Skims by Fluid Attacks discovered a Insecure deserialization in Catch Import Export trun. The following is the output of the tool:
Skims output
337 | static private function _import( $wp_customize )
338 | {
339 | // Make sure we have a valid nonce.
340 | if ( ! wp_verify_nonce( $_REQUEST['cie-import'], 'cie-importing' ) ) {
341 | return;
342 | }
343 |
344 | // Make sure WordPress upload support is loaded.
345 | if ( ! function_exists( 'wp_handle_upload' ) ) {
346 | require_once( ABSPATH . 'wp-admin/includes/file.php' );
347 | }
348 |
349 | // Load the export/import option class.
350 | require_once plugin_dir_path( __FILE__ ) . 'classes/class-catch-import-export-option.php';
351 |
352 | // Setup global vars.
353 | global $wp_customize;
354 | global $cie_error;
355 | global $settings_page;
356 |
357 | // Setup internal vars.
358 | $settings_page = false;
359 | $cie_error = false;
360 | $template = get_template();
361 | $overrides = array( 'test_form' => false, 'test_type' => false, 'mimes' => array('dat' => 'text/plain') );
362 | $file = wp_handle_upload( $_FILES['cie-import-file'], $overrides );
363 |
364 | // Make sure the form is submitted through admin settings page.
365 | if( isset( $_REQUEST['settings-page'] ) && true == $_REQUEST['settings-page'] ){
366 | $settings_page = true;
367 | }
368 |
369 | // Make sure we have an uploaded file.
370 | if ( isset( $file['error'] ) ) {
371 | $cie_error = $file['error'];
372 | return;
373 | }
374 | if ( ! file_exists( $file['file'] ) ) {
375 | $cie_error = __( 'Error importing settings! Please try again.', 'catch-import-export' );
376 | return;
377 | }
378 |
379 | // Get the upload data.
380 | $raw = file_get_contents( $file['file'] );
> 381 | $data = @unserialize( $raw );
382 |
383 | // Remove the uploaded file.
384 | unlink( $file['file'] );
385 |
386 |
387 | // Data checks.
388 | if ( 'array' != gettype( $data ) ) {
389 | $cie_error = __( 'Error importing settings! Please check that you uploaded a customizer export file.', 'catch-import-e
390 | return;
391 | }
392 | if ( ! isset( $data['template'] ) || ! isset( $data['mods'] ) ) {
393 | $cie_error = __( 'Error importing settings! Please check that you uploaded a customizer export file.', 'catch-import-e
394 | return;
395 | }
396 | if ( $data['template'] != $template ) {
397 | $cie_error = __( 'Error importing settings! The settings you uploaded are not for the current theme.', 'catch-import-e
398 | return;
399 | }
400 |
401 | // Import images.
402 | if ( isset( $_REQUEST['cie-import-images'] ) ) {
403 | $data['mods'] = self::_import_images( $data['mods'] );
404 | }
405 |
406 | // Import custom options.
407 | if ( isset( $data['options'] ) ) {
408 |
409 | foreach ( $data['options'] as $option_key => $option_value ) {
410 |
411 | $option = new Catch_Import_Export_Option( $wp_customize, $option_key, array(
412 | 'default' => '',
413 | 'type' => 'option',
414 | 'capability' => 'edit_theme_options'
415 | ) );
416 |
417 | $option->import( $option_value );
418 | }
419 | }
420 |
421 | // If wp_css is set then import it.
422 | if( function_exists( 'wp_update_custom_css_post' ) && isset( $data['wp_css'] ) && '' !== $data['wp_css'] ) {
423 | wp_update_custom_css_post( $data['wp_css'] );
424 | }
425 |
426 | // Call the customize_save action.
427 | do_action( 'customize_save', $wp_customize );
428 |
429 | // Loop through the mods.
430 | foreach ( $data['mods'] as $key => $val ) {
431 |
432 | // Call the customize_save_ dynamic action.
433 | do_action( 'customize_save_' . $key );
434 |
435 | // Save the mod.
436 | set_theme_mod( $key, $val );
437 | }
438 |
439 | // Call the customize_save_after action.
440 | do_action( 'customize_save_after', $wp_customize );
441 | if( isset( $_REQUEST['settings-page'] ) && true == $_REQUEST['settings-page'] ){
442 | $url = admin_url( 'admin.php?page=catch-import-export' );
443 | wp_redirect( esc_url( $url ) );
444 | exit;
445 | }
446 | }
^ Col 0
Our security policy
We have reserved the ID CVE-2025-31321 to refer to this issue from now on.
System Information
- Product: Catch Import Export
- Version: trun
Mitigation
There is currently no patch available for this vulnerability.
Credits
The vulnerability was discovered by Andres Roldan from Fluid Attacks' Offensive Team using Skims
Timeline

2025-03-14
Vulnerability discovered.

2025-03-14
Vendor contacted.