PixelYourSite <= 11.2.0 - Unauthenticated Stored Cross-Site Scripting
Description
The PixelYourSite – Your smart PIXEL (TAG) & API Manager plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'pysTrafficSource' parameter and the 'pys_landing_page' parameter in all versions up to, and including, 11.2.0 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page. CVE-2026-27072 is likely a duplicate of this issue.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:NTechnical Details
<=11.2.0Source Code
WordPress.org SVNThis plan outlines the research and exploitation steps for **CVE-2026-1841**, a Stored Cross-Site Scripting (XSS) vulnerability in the PixelYourSite plugin. --- ### 1. Vulnerability Summary The PixelYourSite plugin (up to version 11.2.0) fails to properly sanitize and escape tracking parameters ca…
Show full research plan
This plan outlines the research and exploitation steps for CVE-2026-1841, a Stored Cross-Site Scripting (XSS) vulnerability in the PixelYourSite plugin.
1. Vulnerability Summary
The PixelYourSite plugin (up to version 11.2.0) fails to properly sanitize and escape tracking parameters captured from the URL. Specifically, the pysTrafficSource and pys_landing_page parameters are stored in the database or session and later rendered in the WordPress administrative dashboard or on frontend pages. Because these values are not escaped during output, an unauthenticated attacker can inject malicious JavaScript that executes when an administrator views reports or when other users visit the site.
2. Attack Vector Analysis
- Endpoint: Any frontend URL (e.g., the homepage).
- Parameters:
pysTrafficSourceandpys_landing_page(sent via GET). - Authentication: None required (Unauthenticated).
- Preconditions: The plugin must be active. The vulnerability is triggered when the plugin captures these tracking parameters to determine attribution.
3. Code Flow (Inferred)
- Entry Point: The plugin hooks into
initorwp_loaded(likely via a class likePixelYourSite\PYSor a dedicatedTrafficSourceManager). - Capture: The code checks
$_GET['pysTrafficSource']and$_GET['pys_landing_page']. - Storage:
- The plugin likely stores these values in a cookie (e.g.,
pys_traffic_source,pys_landing_page). - Crucially, for Stored XSS, these values are often synced to a backend log table or an option (e.g.,
wp_optionsor a custom table likewp_pys_logs) to provide the "Reports" functionality in the Admin area.
- The plugin likely stores these values in a cookie (e.g.,
- Sink:
- Admin Sink: An administrator navigates to PixelYourSite > Reports or the Dashboard. The plugin fetches the stored traffic source strings and echoes them into a table without calling
esc_html(). - Frontend Sink: The plugin localizes these values using
wp_localize_scriptinto a global JS object (oftenpysOptions) without usingesc_js()or proper JSON encoding.
- Admin Sink: An administrator navigates to PixelYourSite > Reports or the Dashboard. The plugin fetches the stored traffic source strings and echoes them into a table without calling
4. Nonce Acquisition Strategy
This vulnerability typically does not require a nonce because it involves passive tracking of URL parameters. However, if the plugin requires an AJAX call to "persist" the discovered traffic source, a nonce might be needed.
Method to obtain nonce (if required):
- Navigate to the homepage where PixelYourSite is active.
- Use
browser_evalto look for the localization object:browser_eval("window.pysOptions?.nonce")- Or check for common PYS localization keys:
window.pys_ajax_object?.nonce.
- The localization key is usually registered via
wp_localize_script('pys', 'pysOptions', ...)inincludes/class-pixelyoursite.php.
5. Exploitation Strategy
Step 1: Inject the Payload
Send an unauthenticated HTTP GET request to the site root with the XSS payload in the vulnerable parameters.
- Tool:
http_request - URL:
https://<target-site>/?pysTrafficSource="><script>alert('XSS_TRAFFIC')</script>&pys_landing_page="><script>alert('XSS_LANDING')</script> - Method: GET
- Expected Behavior: The plugin captures these values and stores them in the database for attribution reporting.
Step 2: Trigger the XSS (Admin Context)
The payload must be rendered in the Admin dashboard to fulfill the "Stored XSS" impact.
- Tool:
browser_navigate - URL:
https://<target-site>/wp-admin/admin.php?page=pixelyoursite - Method: GET (Authenticated as Admin)
- Action: Observe if the
alerttriggers when the Admin views the main plugin page or the "Reports" tab.
Step 3: Trigger the XSS (Frontend Context)
Check if the payload is reflected globally for other users.
- Tool:
http_request - URL:
https://<target-site>/ - Method: GET
- Check: Look for the raw payload in the response body, specifically inside
<script>blocks orpysOptionsdefinitions.
6. Test Data Setup
- Plugin Installation: Install PixelYourSite version 11.2.0.
- Activation: Ensure the plugin is active. No specific configuration is usually required as tracking is often enabled by default.
- Admin User: Ensure an administrator account exists to verify the backend trigger.
7. Expected Results
- The
http_requestin Step 1 should return a200 OK. - The
wp-adminresponse in Step 2 should contain the unescaped script:"><script>alert('XSS_TRAFFIC')</script>. - A successful exploit will execute the JavaScript in the context of the administrator's session, which could be used to exfiltrate nonces or create a new admin user.
8. Verification Steps (Post-Exploit)
Use wp-cli to confirm the data was stored in the database:
# Check if the payload exists in the options table (if stored as a 'last visit' option)
wp option list --search="*pys*" --allow-root
# Check for custom PixelYourSite tables that might store logs
wp db query "SHOW TABLES LIKE '%pys%';" --allow-root
# If a log table exists (e.g., wp_pys_logs), check its contents
wp db query "SELECT * FROM wp_pys_logs WHERE data LIKE '%script%';" --allow-root
9. Alternative Approaches
- Cookie-based Persistence: If the plugin only stores the value in a cookie but then echoes that cookie back into an admin-facing "Current Sessions" page, use the
http_requesttool to set the cookie manually:Cookie: pys_traffic_source="><script>alert(1)</script>
- Event Injection: PixelYourSite often tracks "Events". Try sending the payload through an AJAX event trigger:
- Action:
pys_event - Param:
traffic_source
- Action:
- Bypassing simple filters: If
<script>is blocked, use:pysTrafficSource=" onmouseover="alert(1)" style="position:absolute;width:100%;height:100%;top:0;left:0;pysTrafficSource=<img src=x onerror=alert(1)>
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.