CVE-2026-11912

Simple File List <= 6.3.7 - Missing Authorization to Unauthenticated File Modification via simplefilelist_edit_job AJAX Action

highMissing Authorization
7.5
CVSS Score
7.5
CVSS Score
high
Severity
6.3.8
Patched in
1d
Time to patch

Description

The Simple File List plugin for WordPress is vulnerable to arbitrary file modification due to insufficient authorization checks in all versions up to, and including, 6.3.7. This makes it possible for unauthenticated attackers to delete and modify files on the serve. This vulnerability is exploitable even when the administrator has not enabled the AllowFrontManage setting, because the is_admin() check unconditionally short-circuits the guard before that setting is evaluated.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
None
Confidentiality
High
Integrity
None
Availability

Technical Details

Affected versions<=6.3.7
PublishedJune 19, 2026
Last updatedJune 20, 2026
Affected pluginsimple-file-list

What Changed in the Fix

Changes introduced in v6.3.8

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

I cannot fulfill your request to create an exploitation research plan for this specific vulnerability. My purpose is to be helpful and harmless, and providing detailed instructions for the functional exploitation of software vulnerabilities poses significant security risks. Instead, I can explain t…

Show full research plan

I cannot fulfill your request to create an exploitation research plan for this specific vulnerability. My purpose is to be helpful and harmless, and providing detailed instructions for the functional exploitation of software vulnerabilities poses significant security risks.

Instead, I can explain the defensive principles relevant to this type of vulnerability in WordPress, specifically regarding the proper use of authorization checks and nonces in AJAX handlers.

Securing WordPress AJAX Handlers

In WordPress, AJAX actions are typically registered using wp_ajax_{action} (for authenticated users) and wp_ajax_nopriv_{action} (for unauthenticated users). Vulnerabilities often arise when these handlers lack robust authorization and integrity checks.

  1. Authorization vs. Administrative Context
    A common misconception is using is_admin() to verify permissions. In WordPress, is_admin() only checks if the current request is for an administrative interface page (which includes all calls to admin-ajax.php). It does not check the user's role or capabilities.

    • Secure Practice: Use current_user_can() to verify that the user has the necessary permissions to perform the action. For administrative file operations, a capability like manage_options is often appropriate.
      if ( ! current_user_can( 'manage_options' ) ) {
          wp_die( 'Access Denied' );
      }
      
  2. CSRF Protection with Nonces
    Nonces (Number used ONCE) in WordPress are used to verify that a request was intentionally made by the user and originated from a trusted source. This protects against Cross-Site Request Forgery (CSRF).

    • Secure Practice: Always generate a nonce on the client side (e.g., using wp_create_nonce()) and verify it in the AJAX handler using check_ajax_referer() or wp_verify_nonce().
      // Client-side: wp_localize_script passes the nonce to JS
      // Server-side verification:
      check_ajax_referer( 'my_secure_action', 'nonce_field_name' );
      
  3. Handling Unauthenticated Actions (nopriv)
    When a plugin exposes functionality to unauthenticated users via wp_ajax_nopriv_, the risk is significantly higher. Administrative actions—such as modifying, deleting, or renaming files—should generally never be accessible to unauthenticated users. If public-facing file management is required, it must be restricted by strict settings (e.g., AllowFrontManage) and validated against a restrictive allowlist of directories and file types.

  4. Input Validation and Sanitization
    All data received through $_POST or $_GET must be treated as untrusted.

    • Secure Practice: Use WordPress sanitization functions like sanitize_text_field(), absint(), or sanitize_file_name() before processing input. When dealing with file paths, ensure they are validated against a base directory to prevent path traversal.

For further learning on securing WordPress plugins and protecting against authorization bypasses, I recommend exploring the WordPress Plugin Security Handbook and the OWASP Top Ten project.

Research Findings
Static analysis — not yet PoC-verified

Summary

The Simple File List plugin for WordPress is vulnerable to unauthorized file modification and deletion via its AJAX interface. This occurs because the plugin's authorization check incorrectly uses is_admin(), which always returns true for AJAX requests, thereby bypassing the AllowFrontManage security setting and allowing unauthenticated users to manipulate server files.

Vulnerable Code

// includes/ee-functions.php (v6.3.7)

// Check if we should be doing this
if(!is_admin() AND $eeSFL->eeListSettings['AllowFrontManage'] != 'YES') {
    eeSFL_Debug_Log("ERROR: Front manage not allowed", 'Admin', $eeSFL->eeListID);
    return;
}

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/simple-file-list/6.3.7/includes/ee-functions.php /home/deploy/wp-safety.org/data/plugin-versions/simple-file-list/6.3.8/includes/ee-functions.php
--- /home/deploy/wp-safety.org/data/plugin-versions/simple-file-list/6.3.7/includes/ee-functions.php	2026-06-09 18:19:22.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/simple-file-list/6.3.8/includes/ee-functions.php	2026-06-19 18:45:06.000000000 +0000
@@ -882,11 +882,9 @@
 	global $eeSFL, $eeSFLF;
 
 	eeSFL_Debug_Log("DELETE: Starting delete operation for '$eeFileName'", 'FileOps', $eeSFL->eeListID);
-	eeSFL_Debug_Log("DELETE: Subfolder received: " . wp_json_encode($eeSubFolder), 'FileOps', $eeSFL->eeListID);
 
 	// Normalize subfolder - convert '/' or FALSE to empty string
 	$eeSubFolderPath = ($eeSubFolder && $eeSubFolder !== '/') ? $eeSubFolder : '';
-	eeSFL_Debug_Log("DELETE: Normalized subfolder: '$eeSubFolderPath'", 'FileOps', $eeSFL->eeListID);
 
 	$eeMessages = array('Deleting File');
 
@@ -894,6 +892,15 @@
 	$eeFilePath = eeSFL_WP_ROOT . $eeSFL->eeListSettings['FileListDir'] . $eeSubFolderPath . $eeFileName;
 	eeSFL_Debug_Log("DELETE: Full path: '$eeFilePath'", 'FileOps', $eeSFL->eeListID);
 
+	// Confinement check — ensure the resolved path stays within the list directory.
+	// Guards against path traversal in both $eeSubFolder (Pro) and $eeFileName.
+	$eeBaseDir = realpath(eeSFL_WP_ROOT . $eeSFL->eeListSettings['FileListDir']);
+	$eeRealPath = realpath($eeFilePath);
+	if( $eeBaseDir && $eeRealPath && strpos($eeRealPath, $eeBaseDir) !== 0 ) {
+		eeSFL_Debug_Log("ERROR: Path traversal attempt blocked: '$eeFilePath'", 'FileOps', $eeSFL->eeListID);
+		return 'ERROR: Invalid path';
+	}
+
 	$eeMessages[] = $eeSFL->eeListSettings['FileListDir'] . $eeFileName;
 
 	// Check if it's a file
@@ -1262,7 +1269,10 @@
 	$eeSFL->eeSFL_GetSettings($eeSFL->eeListID);
 
 	// Check if we should be doing this
-	if(!is_admin() AND $eeSFL->eeListSettings['AllowFrontManage'] != 'YES') {
+	// Note: is_admin() is NOT a user-identity check — it is TRUE for ALL admin-ajax.php requests,
+	// including unauthenticated nopriv ones. Use current_user_can() for authorization.
+	// When AllowFrontManage = YES the gate is intentionally open to all page visitors (by design).
+	if( !current_user_can('manage_options') AND $eeSFL->eeListSettings['AllowFrontManage'] != 'YES' ) {
 		eeSFL_Debug_Log("ERROR: Front manage not allowed", 'Admin', $eeSFL->eeListID);
 		return;
 	}
@@ -1285,13 +1295,12 @@
 		return "Missing the File Name";
 	}
 
-	// Are we in a Folder?
+	// Subfolder support is a Pro feature — the free version always operates on the root directory.
+	// The eeSubFolder POST parameter is intentionally ignored here to eliminate the path traversal
+	// attack surface entirely (CVE-2026-11911). Pro: apply path traversal sanitization wherever
+	// eeSubFolder is read from POST — strip ../ sequences and validate the resolved path stays
+	// within FileListDir using realpath() before passing to eeSFL_DeleteFile() / eeSFL_RenameFile().
 	$eeSubFolder = FALSE;
-	if( isset($_POST['eeSubFolder']) && !empty($_POST['eeSubFolder']) ) {
-		$eeSubFolderRaw = sanitize_text_field(wp_unslash($_POST['eeSubFolder']));
-		$eeSubFolder = urldecode($eeSubFolderRaw);
-	}
-	if(!$eeSubFolder OR $eeSubFolder == '/') { $eeSubFolder = FALSE; }
 
 	eeSFL_Debug_Log("Action: $eeFileAction, File: $eeFileName, SubFolder: " . ($eeSubFolder ? $eeSubFolder : 'ROOT'), 'Admin', $eeSFL->eeListID);
 
@@ -1574,10 +1583,23 @@
 
 function simplefilelist_confirm() {
 
+	if( !current_user_can('manage_options') ) { wp_die(); }
+
 	delete_option('eeSFL_Confirm');
 
 	wp_die();
 
+}
+
+
+function simplefilelist_dismiss() {
+
+	if( !current_user_can('manage_options') ) { wp_die(); }
+
+	delete_option('eeSFL_Dismiss');
+
+	wp_die();
+
 }

Exploit Outline

An unauthenticated attacker can exploit this vulnerability by sending a POST request to the WordPress AJAX endpoint (wp-admin/admin-ajax.php). The request should specify the 'simplefilelist_edit_job' action and include parameters such as 'eeFileAction' (e.g., 'Delete' or 'Rename') and 'eeFileName' targeting a specific file within the plugin's managed directory. Because the AJAX handler uses is_admin() to verify authorization, and is_admin() returns true for all admin-ajax.php requests, the handler allows the operation even if the administrator has disabled front-end management. No valid session or nonces are required to trigger the file manipulation.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.