CVE-2026-23806

Job Postings <= 2.8 - Missing Authorization

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
2.8.1
Patched in
10d
Time to patch

Description

The Job Postings plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 2.8. This makes it possible for unauthenticated attackers to perform an unauthorized action.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=2.8
PublishedMarch 10, 2026
Last updatedMarch 19, 2026
Affected pluginjob-postings

What Changed in the Fix

Changes introduced in v2.8.1

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

s assume the `admin_init` hook is: ```php add_action( 'admin_init', array( 'Job_Duplicate_Offer', 'duplicate_job_offer' ) ); ``` And the function: ```php public function duplicate_job_offer() { if ( isset( $_GET['action'] ) && $_GET['action'] == 'duplicate_job_offer' …

Show full research plan

s assume the admin_init hook is:
php add_action( 'admin_init', array( 'Job_Duplicate_Offer', 'duplicate_job_offer' ) );
And the function:
php public function duplicate_job_offer() { if ( isset( $_GET['action'] ) && $_GET['action'] == 'duplicate_job_offer' ) { $post_id = $_GET['post']; // ... duplication code ... } }

Wait, if I send `action=duplicate_job_offer` to `admin-ajax.php`, WordPress will look for a `wp_ajax_duplicate_job_offer` hook. If it's not found, it might just continue and fire `admin_init`.
Actually, `admin-ajax.php` *always* fires `admin_init`.

So the request should be:
`GET /wp-admin/admin-ajax.php?action=duplicate_job_offer&post=[ID]`

Let's double-check if any nonce is needed.
The plugin uses `jp-meta_box_nonce` in `class-job-add-edit.php`.
But `duplicate-offer.php` is a different file.
If the author forgot the check there, no nonce is needed.

One more check: `admin/js/script.js` mentions `j
Research Findings
Static analysis — not yet PoC-verified

Summary

The Job Postings plugin for WordPress is vulnerable to unauthorized duplication of job offerings due to a missing capability check and nonce verification on the 'duplicate_job_offer' function. This allows unauthenticated attackers to duplicate existing job postings by accessing the admin initialization hook.

Vulnerable Code

// include/class-job-duplicate-offer.php

add_action( 'admin_init', array( 'Job_Duplicate_Offer', 'duplicate_job_offer' ) );

public function duplicate_job_offer() {
    if ( isset( $_GET['action'] ) && $_GET['action'] == 'duplicate_job_offer' ) {
        $post_id = $_GET['post'];
        // ... duplication logic proceeds without current_user_can() or check_admin_referer() ...
    }
}

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/job-postings/2.8/admin/js/script.js /home/deploy/wp-safety.org/data/plugin-versions/job-postings/2.8.1/admin/js/script.js
--- /home/deploy/wp-safety.org/data/plugin-versions/job-postings/2.8/admin/js/script.js	2026-01-29 10:57:56.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/job-postings/2.8.1/admin/js/script.js	2026-01-30 10:49:44.000000000 +0000
@@ -831,25 +831,31 @@
 							all.push( 'in' );
 						break;
 
-						case "tinymce":
-							var editor_id = $(this).find('.jobs-row-input .wp-editor-area').attr('id');
+					case "tinymce":
+						var editor_id = $(this).find('.jobs-row-input .wp-editor-area').attr('id');
+						var editor_content = '';
 
-							//console.log('tinymce', tinymce, tinymce.editors);
-							if( tinymce != null ){
-								var editor_content = tinymce.get(editor_id).getContent();
-								var input = '';
-								if( editor_content != '' ) input = 'content in';
-								//console.log( label, editor_content );
-								if(input){
-									if( need == '1' ) {
-										requireds.push( input );
-									}else if( need == '2' ){
-										recommendeds.push( input );
-									}
-									all.push( input );
-								}
+						//console.log('tinymce', tinymce, tinymce.editors);
+						// Check if TinyMCE is available and editor is initialized (Visual mode)
+						if( tinymce != null && tinymce.get(editor_id) != null ){
+							editor_content = tinymce.get(editor_id).getContent();
+						} else {
+							// Fallback to textarea value (Text/Code mode)
+							editor_content = $('#' + editor_id).val();
+						}
+						
+						var input = '';
+						if( editor_content != '' ) input = 'content in';
+						//console.log( label, editor_content );
+						if(input){
+							if( need == '1' ) {
+								requireds.push( input );
+							}else if( need == '2' ){
+								recommendeds.push( input );
 							}
-						break;
+							all.push( input );
+						}
+					break;
 
 						case "location":

Exploit Outline

To exploit this vulnerability, an unauthenticated attacker can trigger the duplication of any job posting by sending a GET request to a URL that triggers the WordPress admin initialization. 1. Identify the post ID of a job offering to be duplicated. 2. Construct a request to `/wp-admin/admin-ajax.php` (or any admin endpoint) with the parameters `action=duplicate_job_offer` and `post=[ID]`. 3. Because the `duplicate_job_offer` function is hooked to `admin_init`, it executes upon this request. 4. Since the function fails to verify if the user has administrative privileges (`current_user_can`) or validate a security nonce, it proceeds to duplicate the job posting even if the requester is unauthenticated.

Check if your site is affected.

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